Jump to content

App Launcher Button in SpaceCenter


Recommended Posts

Hey Guys,

Just a little bug I'm trying to figure out.  I've got a toolbar button (Stock Toolbar) I'm trying to get to show up ONLY in the Space Center Scene, but there is a small issue...

  • Upon initial loading of the game, the button doesn't load. Fixed: Added OnGUIApplicationLauncherReady (); to the end of my awake section
  • If I go into Flight Scene and come right back out to Space Center Scene, the button shows fine.
  • If I keep going back and forth, the button duplicates itself.

Here is what I have:

[KSPAddon (KSPAddon.Startup.SpaceCentre, false)]
public class CLASSY : MonoBehaviour
{
		//Initialize Textures & Events
		private void Awake ()
		{
			if (GameDatabase.Instance.ExistsTexture ("Plugin/Textures/ToolbarButtonDefault")) {
				ToolbarButtonTexture = GameDatabase.Instance.GetTexture ("Plugin/Textures/ToolbarButtonDefault", false);
			}
			GameEvents.onGUIApplicationLauncherReady.Add (OnGUIApplicationLauncherReady);
			OnGUIApplicationLauncherReady (); //This fixed my first issue
		}
		
		//Create the App Launcher when ready
		private void OnGUIApplicationLauncherReady ()
		{
			if (ToolbarButton == null) {
				ToolbarButton = ApplicationLauncher.Instance.AddModApplication (
					GUISwitch, GUISwitch,
					null, null,
					null, null,
					ApplicationLauncher.AppScenes.SPACECENTER,
					ToolbarButtonTexture
				);
			}
		}
		
		//Switch(from toolbar button) to trigger OnDraw
		public void GUISwitch ()
		{
			RenderingManager.AddToPostDrawQueue (0, OnDraw);
			
			SettingsGUI = new Rect (Screen.width / 2, Screen.height / 2, 250, 400);
			
			if (ShowSettings == false) {
				ShowSettings = true;
			} else {
				ShowSettings = !ShowSettings;
			}
		}
		
		//OnDraw Shows the MainGUI Window
		private void OnDraw()
		{
			GUI.skin.window.richText = true;
			if (ShowSettings == true) {
				SettingsGUI = GUI.Window (151844, SettingsGUI, MainGUI, "<b>Title</b>");
			} 
		}
		
		//MainGUI Window Content
		private void MainGUI (int WindowID)
		{
			GUI.Box (new Rect (1,1,25,25), "box text" );
		}
}

How can I stop that button from duplicating?

Any help is appreciated =)

 

Edited by wrcsubers
Link to comment
Share on other sites

If I change:

[KSPAddon (KSPAddon.Startup.SpaceCentre, false)] to  [KSPAddon (KSPAddon.Startup.Instantly, false)]

It will load upon first startup, but I don't get the texture, I'm guessing this means something...

Fixed =)

Edited by wrcsubers
Link to comment
Share on other sites

Because your KSPAddon does not have the run once flag set, it runs every time the Space Center scene loads.

Therefore every time that scene change is triggered you are adding a new button because you code runs again.

You need to remove the button when you leave that scene. As you are using a KSPAddon, KSP automatically destroys that class when you leave the scene and you can run code then in the OnDisable() method.

public void OnDisable()
{
ApplicationLauncher.Instance.RemoveModApplication(ToolbarButton);
GameEvents.onGUIApplicationLauncherReady.Remove (OnGUIApplicationLauncherReady);
}

 

Something like that should work. (on mobile, check the syntax)

Note I also removed the GameEvents hook, if you don't do that it hangs around and KSP tries to trigger the OnApplicationLauncherReady event again the second time you enter the scene but will throw a nullRef because it can't find the KSPAddon from the first entry of the scene any more.

D.

 

Edited by Diazo
Link to comment
Share on other sites

Thanks Diazo!

I thought it might be something along those lines, I didn't think of removing the GameEvents hook though, so extra thanks for that tip.

I'm assuming OnDisable() gets called automatically when KSPAddon is destroyed, is that correct?

Link to comment
Share on other sites

Yes, it's actually a Unity thing so anytime anything that inherits from MonoBehavior is destroyed, the OnDisable() method runs.

So KSPAddon, Part, PartModule, ScenarioModule, VesselModuel, etc. all have it.

Just be careful with race conditions, I managed to gloriously screw up my save/load routine once that way as Unity destroys them in order, not in a batch.

So Class1/2/3 are scheduled for destruction at the same time, Class1 runs OnDisable() and is destroyed, then Class2 runs OnDisable() and is destroyed, then Class3 runs OnDisable() and is destroyed.

It doesn't run OnDisable() in all 3 classes before any of them are destroyed. So if you try to refer to Class1 from Class3's OnDisable(), it throws a nullRef because Class 1 is already destroyed.

D.

Link to comment
Share on other sites

OnDisable or OnDestroy? I think you mean the latter, but...

7 hours ago, Diazo said:

It doesn't run OnDisable() in all 3 classes before any of them are destroyed. So if you try to refer to Class1 from Class3's OnDisable(), it throws a nullRef because Class 1 is already destroyed.

Use a single master class to handle the unity interactions and create/destroy any actual modules manually. Using multiple KSPAddon type classes in the same scene normally leads to trouble -.-

Link to comment
Share on other sites

I was actually trying to refer to Squad's editor scene KSPAddon class (which isn't technically a KSPAddon I realize).

Depending on how you exit the editor, behavior was inconsistent on what was being destroyed first. Sometimes my KSPAddon was so OnDisable ran fine and could refer to editor objects, sometimes the editor was destroyed first and my OnDisable would throw nothing but null refs.

However, I really intended that warning for PartModules. If you have a PartModule with code in OnDisable and multiple copies of the module on a vessel, you have no control over the order in which the PartModules are destroyed and their OnDisable code will run.

D.

Link to comment
Share on other sites

Diazo another question for you...

Within ApplicationLauncher.Instance.AddModApplication(), you have RUIToggleButton.onEnable and .onDisable

Can you use these two delegates (or fields?) to trigger removing the Toolbar Button?

Or is this basically just going to do the same thing as what I'm already doing by calling an OnDisable () Method?

Thanks

Edited by wrcsubers
Link to comment
Share on other sites

Erg, I won't have access to my KSP computer for another day so I'm going to try an answer this from memory.

First, you are talking about multiple values within the .AddModApplication() method correct?

Here's the line of code I use in AGX for this:

AGXAppFlightButton = ApplicationLauncher.Instance.AddModApplication(onStockToolbarClick, onStockToolbarClick, DummyVoid, DummyVoid, DummyVoid, DummyVoid, ApplicationLauncher.AppScenes.FLIGHT, (Texture)GameDatabase.Instance.GetTexture("Diazo/AGExt/icon_button", false));

AGXAppFlightButton is my ApplicationLauncherButton object I've previously created.

onStockToolbarClick is the method that I want to run when the button is clicked. Note it is there twice, the first one (onEnable) is what runs when the button is darker gray and clicking it turns is lighter. The second one (onDisable) is what runs when the button is lighter and clicking it turns it dark. I want to run the same code when the button is clicked regardless of it's current state so I just call the same method here.

DummyVoid is a nothing method, I can't remember all 4 of the methods but one's an OnMouseOver with a second being OnMouseOff. I don't run code there so call a dummy method that's empty.

Application.Launcher.App-Scenes.FLIGHT is set so this only runs in flight mode. (I run a different KSPAddon class in the editor.)

(Texture)GameDatabase.Instance.GetTexture("Diazo/AGExt/icon_button", false)  is where I tell the button what texture to use. I can't remember what the false setting is for , I think it means my texture doesn't have an alpha channel?

 

Then I run

ApplicationLauncher.Instance.RemoveModApplication(AGXAppFlightButton);

in OnDisable() of my KSPAddon class to remove the button when the player leaves the flight scene.

Hope that answers your question, if it doesn't I'll be back at my KSP computer tomorrow and can actually look at the code then.

D.

Edited by Diazo
Link to comment
Share on other sites

Exactly right! Good memory... I'm doing pretty much the same thing:

private void OnGUIApplicationLauncherReady ()
		{
			if (EVAOK_MSC_ToolbarButton == null) {
				EVAOK_MSC_ToolbarButton = ApplicationLauncher.Instance.AddModApplication (
					EVAOK_MSC_GUISwitch, EVAOK_MSC_GUISwitch,
					null, null,
					null, null,
					ApplicationLauncher.AppScenes.SPACECENTER,
					EVAOK_MSC_Button
				);
			}
		}

My question was this, the last two 'null' values refer to RUIToggleButton.onEnable and RUIToggleButton.onDisable respectively.  I don't think I've ever seen them used, but I was wondering what they are for... I'm guessing they get called when the Toolbar Button is enabled/disabled.  You could refer to a method in there instead of listening for the GameEvent when the button is disabled right?  I know they would end up with the same conclusion, but it might be a cleaner way to do it? Just curious...

Link to comment
Share on other sites

Back at my KSP computer and see what you are talking about.

Looking in the object browser those are events just like the OnClick event is.

However, there is an OnTrue and OnFalse event in the code (not part of .AddModApplication though) that looks like they are what triggers when the button's state changes.

So I have no clue what onEnable or onDisable do.

D.

Link to comment
Share on other sites

  • 2 weeks later...

I have a feeling that onDisable is the event, which is triggered when the button gets grayed out, like KER's button does, when the editor is empty - just disabled, so you cannot control it and change its state.

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...