Jump to content

KSPAddon - publishing values


Recommended Posts

Plugging along on my plugin, I've run into another problem that I've not been able to find a good answer to. How do I get a value from a MonoBehaviour class down into a partmodule?

Basically, I'd like to have a single instance of a monobehaviour class managing the behavior of the various instances of my partmodule class. I'm attempting to do this by having the single manager (monobehaviour) class keep a state table of what each partmodule class should be doing.

However, I haven't been able to figure out how to have the partmodules access the monobehaviour classes object to read the state table, and figure out what they should be doing. Is there a simple way to do this?

To put it in context:

To simplify, say I have a PartModule class:

public class AutoGimbal : PartModule
{
public override void OnUpdate()
{
print(AutoGimbalManager.rotationTarget);
}
}

And a Monobehaviour class:

[KSPAddon(KSPAddon.Startup.EveryScene, false)]
public class AutoGimbalManager : MonoBehaviour
{
public string rotationTarget = "Mun";
}

How do I get the AutoGimbalManager object in the PartModule?

Link to comment
Share on other sites

There are two easy ways. The first one is a static property:

public class AutoGimbal : PartModule
{
public override void OnUpdate()
{
Log.Debug("target = " + AutoGimbalManager.instance.rotationTarget);
}
}

[KSPAddon(KSPAddon.Startup.EveryScene, false)]
public class AutoGimbalManager : MonoBehaviour
{
public string rotationTarget = "Mun";

void Start()
{
instance = this;
}

public static AutoGimbalManager instance
{
get;
private set;
}
}

The other way is to go looking for the right type directly. It's straightforward but you don't want to go looking through the entire scene every frame, so caching the result is important:

public class AutoGimbal : PartModule
{
AutoGimbalManager manager;

void Start() {
manager = FindObjectOfType<AutoGimbalManager>();
}

public override void OnUpdate()
{
Log.Debug("target = " + manager.rotationTarget);
}
}

[KSPAddon(KSPAddon.Startup.EveryScene, false)]
public class AutoGimbalManager : MonoBehaviour
{
public string rotationTarget = "Mun";
}

Link to comment
Share on other sites

Excellent, that works, thank you!

So, to make sure I have a full understanding, basically in the partmodule, I'm creating an empty instance of the AutoGimbalManager, then on the scene start finding the object created by the game using the FindObjectOfType<>() method, and assigning it to the empty instance within the partmodule.

Then once I have that, I can access its values / methods as if it were any other object. If there were more than just the one instance, I could use the methods you described to me in my post about accessing other partmodules' fields and methods.

Link to comment
Share on other sites

If there were more than just the one instance, I could use the methods you described to me in my post about accessing other partmodules' fields and methods.

Yes, essentially. It just occurred to me there's another way you could go about this as well: Instead of the PartModule finding the MonoBehaviour, you could have the MonoBehaviour tell the PartModule which MonoBehaviour it'll be accessing. This might even be the superior solution if there's a good chance you'll be dealing with multiple manager style objects later, since you needn't modify your PartModule at all:

public class AutoGimbal : PartModule
{
public AutoGimbalManager manager;

public override void OnUpdate()
{
Log.Debug("target = " + manager.rotationTarget);
}
}

[KSPAddon(KSPAddon.Startup.EveryScene, false)]
public class AutoGimbalManager : MonoBehaviour
{
public string rotationTarget = "Mun";

void Start()
{
FlightGlobals.Vessels.ForEach(vessel =>
{
vessel.FindPartModulesImplementing<AutoGimbal>().ForEach(gimbal =>
{
gimbal.manager = this;
});
});

}
}

I don't know why that didn't occur to me earlier :)

Link to comment
Share on other sites

That works excellently, thanks!

The only part I'm not sure I understand is the part where it uses what appears to be a temporarily defined 'gimbal' to pass the object to the 'manager' within the partmodule. Is that more or less correct? In this case is gimbal the 'input' from each case of the 'foreach'?

Again, thanks for all your help!

Link to comment
Share on other sites

That's just a counting variable that refers to the current AutoGimbal instance being iterated over. You could rewrite that part as a foreach loop and it'd be equivalent. I just happen to find it slightly more readable with the ForEach is all

Link to comment
Share on other sites

Gotcha, works great, either way. Are you familiar with the way the toolbar plugin works? I'm running into a behaviour I haven't been able to nail down, and I think it might be related to the fact that I'm accessing InfernalRobotics' namespace, which has the toolbarwrapper in it. I made a post in the Toolbar dev thread but searching through the thread to see if anyone's had this problem before I saw that you've done a lot with it.

Any idea if that's what is going on, or if there's something simpler I'm missing?

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...