linuxgurugamer

[1.5.1+] Toolbar Controller (for modders)

Recommended Posts

When KSP was first released, all those years ago, there wasn't any toolbar, so @blizzy78 made the very popular toolbar which many mods use.

Then KSP released the stock toolbar.  Many people like and use the stock toolbar, and many like and use the Blizzy toolbar.  Both have advantages and disadvantages.

Most if not all of my mods allow the user to use either one.  I got tired of recoding the toolbars for every mod, and came up with this mod to make life much easier, and wrote an interface to control both the Blizzy Toolbar and the stock Toolbar without having to code for each one.

This mod will do nothing without a mod being coded to support it


Most important (for mod authors)
All mods using this should add the following line to the AssemblyInfo.cs file:

 [assembly: KSPAssemblyDependency("ToolbarController", 1, 0)]

This will guarantee the load order.  One benefit is that KSP will output a warning and won't load an assembly if it's dependencies aren't met (which may be better than puking out a bunch of exceptions).  The only other real problem with the forced to the top of the sort list method is that technically there's a couple characters before zero ('~', '!', '@', etc.) and dlls directly in GameData come first too.  Of course someone pretty much has to be trying to break things if you have to worry about this particular case.

New Dependency

CKAN has been updated to install the dependencies, if needed.

MODDERS NOTE

A significant update has just been released, which adds functionality and reduces complexity

  • Buttons can now be displayed on both toolbars simultaneously.
  • Button settings can now be stored by the ToolbarController itself, eliminating the need to save it in the mod settings.  This is done by registering the button before or when the MainMenu is reached, see the example code below.
  • If using registration, then no need to have any call in the OnGUI method
  • If you do change the blizzy/stock options, then a single call to the following method will suffice:
    •     toolbarControl.UseButtons(string NameSpace);
  • The documentation below has been updated for the new features

Currently available on Github:

.

Now, instead of having gobs of code to support both toolbars, it can be reduced to three statements:

A new feature is to add the ability for a mod to register with the ToolbarController.  Registration adds the following benefits:

  1. The mod no longer has to deal with the Blizzy toolbar at all.  The ToolbarController now has the ability to store the toolbar settings as which which (or both) buttons should be displayed
  2. The ability to show the buttons on both toolbars has been added
  3. The ability to hide both buttons has been added

To use the the new features, you need to first register the mod with the ToolbarController, either before or when the MainMenu has been reached.  The following is an example:

Spoiler

 


using UnityEngine;
using ToolbarControl_NS;

namespace KerbalSlingshotter
{
	[KSPAddon(KSPAddon.Startup.MainMenu, true)]
	public class RegisterToolbar : MonoBehaviour
	{
		void Start()
		{
			ToolbarControl.RegisterMod(SlingshotCore.MODID, SlingshotCore.MODNAME);
		}
	}
}

and, in the file where the button is added to the ToolbarController:


using System;
using System.Linq;
using UnityEngine;
using KSP.UI.Screens;

using ClickThroughFix;
using ToolbarControl_NS;

namespace KerbalSlingshotter
{
	[KSPAddon(KSPAddon.Startup.Flight,false)]
	public class  SlingshotCore 
	{
		internal const string MODID = "Slingshotter_NS";
		internal const string MODNAME = "SlingShotter";
	}

	private void CreateButtonIcon()
		{
			toolbarControl = gameObject.AddComponent<ToolbarControl>();
			toolbarControl.AddToAllToolbars(ToggleOn, ToggleOff,
				ApplicationLauncher.AppScenes.FLIGHT | ApplicationLauncher.AppScenes.MAPVIEW | ApplicationLauncher.AppScenes.TRACKSTATION,
				MODID,
				"slingShotterButton",
				"SlingShotter/PluginData/Textures/icon_38",
				"SlingShotter/PluginData/Textures/icon_24",
				MODNAME
			);
		}
	}
}

 

 

 


To create the toolbars (example is from FlightPlan) without using registration:

Spoiler

 


toolbarControl = gameObject.AddComponent<ToolbarControl>();
toolbarControl.AddToAllToolbars(onAppTrue, onAppFalse,
	ApplicationLauncher.AppScenes.SPACECENTER |
	ApplicationLauncher.AppScenes.TRACKSTATION |
	ApplicationLauncher.AppScenes.FLIGHT |
	ApplicationLauncher.AppScenes.MAPVIEW,
	"FlightPlan_NS",
	"flightPlanButton",
	"FlightPlan/Textures/flight-plan-icon",
	"FlightPlan/Textures/flight-plan-icon-toolbar",
	"Flight Plan"
);
toolbarControl.UseBlizzy(HighLogic.CurrentGame.Parameters.CustomParams<FP>().useBlizzy);

 

 

 


For both methods, to remove the toolbars:

Spoiler

 


toolbarControl.OnDestroy();
Destroy(toolbarControl);

 

 

 

 

Unlike the Blizzy toolbar, this mod is a hard dependency, but, if the Blizzy toolbar isn't there, it will work quite nicely with the stock toolbar.

// If true, activates Blizzy toolbar, if available.  Otherwise, use the stock toolbar
// If not updating in an OnGUI, call this BEFORE creating the button
public void UseBlizzy(bool useBlizzy)

// If true, activates stock toolbar, if available.  Otherwise, use the Blizzy toolbar
// If not updating in an OnGUI, call this BEFORE creating the button
public void UseStock(bool useStock)


// The TC_ClickHander is a delegate used to pass in a method reference in the AddToAllToolbars methods below
public delegate void TC_ClickHandler();

The method AddToAllToolbars() has several definitions.  All parameters are the same, the only difference is that
the shorter ones don't pass in unneeded parameters

(Callback onTrue, Callback onFalse, Callback onHover, Callback onHoverOut, Callback onEnable, Callback onDisable, AppScenes visibleInScenes, Texture texture);

Methods to either get or set the BlizzyActive and StockActive settings:

public static bool BlizzyActive(string NameSpace, bool? useBlizzy = null)
public static bool StockActive(string NameSpace, bool? useStock = null)

Method to set status of both buttons:

public static void ButtonsActive(string NameSpace, bool? useStock, bool? useBlizzy)

 

Definitions

The onTrue parameter is unique in that it applies both to the stock toolbar and the Blizzy toolbar.
    onTrue                Corresponds to the onTrue parameter in the AddModApplication() function.  This also corresponds to the blizzyButton.OnClick setting 

The following corresponds to the same parameter in the AddModApplication() method
    onFalse    
    onHover
    onHoverOut
    onenable
    onDisable

    visibleInScenes        The values are the same as stock ApplicationLauncher.AppScenes.  The mod will use this to build the appropriate values for the Blizzy toolbar

Icons
    largeToolbarIcon    used for the stock toolbar
    smallToolbarIcon    Used for the Blizzy toolbar

If used, the following will be used to change the icon depending on whether it is active or not
    largeToolbarIconActive        large is used for the stock toolbar
    largeToolbarIconInactive

    smallToolbarIconActive        small is used for Blizzy toolbar
    smallToolbarIconInactive

The following are used by the Blizzy toolbar only
    NameSpace                    Namespace of the mod
    toolbarId                    unique id for the toolbar
    tooltip                        tooltip which is shown when hovering the mouse over the button

The following are used by the RegisterMod method
    NameSpace    Same namespace as for the AddToAllToolbars()
    DisplayName    Name of mod in display format, used on the ToolbarControl page


The following methods are available, more can be added if requested

public void AddToAllToolbars(TC_ClickHandler onTrue, TC_ClickHandler onFalse,
            ApplicationLauncher.AppScenes visibleInScenes, 
            string nameSpace, string toolbarId, 
            string largeToolbarIcon, string smallToolbarIcon, 
            string toolTip = "")

public void AddToAllToolbars(TC_ClickHandler onTrue, TC_ClickHandler onFalse,
            ApplicationLauncher.AppScenes visibleInScenes, 
            string nameSpace, string toolbarId, 
            string largeToolbarIconActive,
            string largeToolbarIconInactive,
            string smallToolbarIconActive,
            string smallToolbarIconInactive, 
            string toolTip = "")

public void AddToAllToolbars(TC_ClickHandler onTrue, TC_ClickHandler onFalse, TC_ClickHandler onHover, TC_ClickHandler onHoverOut, TC_ClickHandler onEnable, TC_ClickHandler onDisable,
            ApplicationLauncher.AppScenes visibleInScenes, 
            string nameSpace, string toolbarId, 
            string largeToolbarIcon, string smallToolbarIcon, 
            string toolTip = "")

public void AddToAllToolbars(TC_ClickHandler onTrue, TC_ClickHandler onFalse, TC_ClickHandler onHover, TC_ClickHandler onHoverOut, TC_ClickHandler onEnable, TC_ClickHandler onDisable,
            ApplicationLauncher.AppScenes visibleInScenes, 
            string nameSpace, string toolbarId, 
            string largeToolbarIconActive, string largeToolbarIconInactive, string smallToolbarIconActive, string smallToolbarIconInactive, 
            string toolTip = "")

If you need to use Left and Right clicks (seperate from the onTrue and onFalse), the following is available. Not that if you have an onTrue/onFalse specified along with an onLeftClick, both will be called:

public void AddLeftRightClickCallbacks(TC_ClickHandler onLeftClick, TC_ClickHandler onRightClick)

 

You have the ability to manually set a button active or inactive using the SetTrue() and SetFalse() methods.  If the makeCall parameter is true, then it will call the appropriate methods, assuming the methods were defined when the button was created:

public void SetTrue(bool makeCall = false)

public void SetFalse(bool makeCall = false)

If you wish to control the icon on the button directly (for example, you have 3 different icons), the following function is available.  Note that once you use this, the mod will not change the icons any more, you will be responsible for all further icon changes:

public void SetTexture(string large, string small)


The following only applies if the mod is NOT registered with the ToolbarController:

If you have the toolbar selectable in a settings page, you an ensure that any time the user changes the setting the toolbar will change immediately by adding the following (example from FlightPlanner):

private void OnGUI() 
{
	if (toolbarControl != null)
		toolbarControl.UseBlizzy(HighLogic.CurrentGame.Parameters.CustomParams<FP>().useBlizzy);
}

You can also add, if you like, various callbacks to monitor the settings.  This is a very lightweight call, if  there isn't any change, it returns immediately.  This is not needed when the mod is registered.

 

The following function was added because of Unity's inability to properly load images which aren't a power of 2.

This function will attempt to load either a file, PNG, JPG, or DDS from the specified path.  While it isn't really specific to the ToolbarController, since I needed it to make the mod work properly, I decided to make it public for others to use.
It first checks to see if the actual file is there, if not, it then looks for either a PNG, JPG, GIF or DDS format files.

public static Boolean LoadImageFromFile(ref Texture2D tex, String fileNamePath)

 

Mod authors, please let me know if you use this mod

Edited by linuxgurugamer
  • Like 14

Share this post


Link to post
Share on other sites

Given the amount of toolbar-related bugs and work I've seen come up...  I'm guessing this is going to go over well.  :wink:

  • Like 2

Share this post


Link to post
Share on other sites
29 minutes ago, DStaal said:

Given the amount of toolbar-related bugs and work I've seen come up...  I'm guessing this is going to go over well.  :wink:

I hope so, and I'll be releasing Flight Plan which uses this over the weekend, as well as updating Engine Ignitor to use this (which is where the basic code was originally done)

Share this post


Link to post
Share on other sites

@linuxgurugamer thanks for this, I'll definitely use it in Antenna Helper (now that I have a nice icon :) ).

One request tho, can you add a method that return the position of the button that have been last clicked ? Quite useful to show small GUI next to their button. (and for whatever reason the transform.postion of the stock toolbar button give strange result, that will make one more reason to use your mod).

Share this post


Link to post
Share on other sites
15 minutes ago, Li0n said:

@linuxgurugamer thanks for this, I'll definitely use it in Antenna Helper (now that I have a nice icon :) ).

One request tho, can you add a method that return the position of the button that have been last clicked ? Quite useful to show small GUI next to their button. (and for whatever reason the transform.postion of the stock toolbar button give strange result, that will make one more reason to use your mod).

Only if it is available from either of the two methods.  It's only doing a passthrough, so unless it is there, I can't add it. 

I know I haven't implemented all of the Blizzy functions, if needed I can easily add them

 

Edit:  I may be able to do it, but it won't happen until tomorrow

Edited by linuxgurugamer
  • Like 1

Share this post


Link to post
Share on other sites
25 minutes ago, linuxgurugamer said:

Only if it is available from either of the two methods.  It's only doing a passthrough, so unless it is there, I can't add it. 

I know I haven't implemented all of the Blizzy functions, if needed I can easily add them

Yes it will need some additional logic, determining which button position need to be be returned.

But in that case could you make a method that return the button(s), or set them public. Besides getting their position it could be used to change the texture. I haven't a lot experience with KSP toolbar button but there is probably other use case scenario.

Edit :

25 minutes ago, linuxgurugamer said:

Edit:  I may be able to do it, but it won't happen until tomorrow

And I probably don't implement Toolbar Control before that :wink: Going to bed soon...

Edited by Li0n

Share this post


Link to post
Share on other sites

It turns out to be easier than I thoughht.

I am going to wait a day or so before an update, but the following are slated to be in the next update:

1,  The mod will be moved into the same folder/directory as the toolbar.  Needed to ensure it gets loaded i the proper order.

2. A method to return the last position of the mouse when a button is clicked.

I am not at this time intending to expose the buttons.  If you need some special logic for a button, then you probably will want to do the button logic yourself.  This is intended to be a wrapper around both types of toolbars, and for that use case, the functionality implemented needs to be a common as possible.

  • Like 1

Share this post


Link to post
Share on other sites
5 hours ago, linuxgurugamer said:

I am not at this time intending to expose the buttons.  If you need some special logic for a button, then you probably will want to do the button logic yourself.  This is intended to be a wrapper around both types of toolbars, and for that use case, the functionality implemented needs to be a common as possible.

Good point.

5 hours ago, linuxgurugamer said:

2. A method to return the last position of the mouse when a button is clicked.

Thanks. (no more struggling with the stock button position :D )

Share this post


Link to post
Share on other sites

I have tooltips working for stock buttons now, will be in next update

  • Like 1

Share this post


Link to post
Share on other sites

New release, 0.1.1

  • Moved mod into the 000_Toolbar directory
  • Added method to return location of mouse at last buttonclick
  • Added Enable method to enable/disable the button
  • Added tooltip for stock buttons
  • Added settings page
    • Show tooltips
    • Stock tooltip timeout

This is essentially a production-ready release.

Please, feedback is essential for a mod like this.

  • Like 1

Share this post


Link to post
Share on other sites

Minor update, 0.1.2

  • Fixed issue with stock toolbar not changing textures
  • Replaced Debug.Log with logging class to reduce log spam
  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, linuxgurugamer said:

Moved mod into the 000_Toolbar directory

Just to be clear: So this mod now uses the same folder as Blizzy's Toolbar?

Share this post


Link to post
Share on other sites
54 minutes ago, DStaal said:

Just to be clear: So this mod now uses the same folder as Blizzy's Toolbar?

Yes, but it can operate without blizzy

Share this post


Link to post
Share on other sites
11 minutes ago, linuxgurugamer said:

Yes, but it can operate without blizzy

Thanks.  I'll try to remember.  (I hate having to merge folders to install mods - Macs don't support recursive folder merging very well.)

Share this post


Link to post
Share on other sites
7 hours ago, DStaal said:

Thanks.  I'll try to remember.  (I hate having to merge folders to install mods - Macs don't support recursive folder merging very well.)

Sorry, but its necessary to be sure everything gets loaded in in the correct order

Once this starts to be used, I’ll package the toolbar dll in the same zip file, and will set up ckan to not have a problem with that

Edited by linuxgurugamer
  • Like 1

Share this post


Link to post
Share on other sites

Minor update, 0.1.3

  • Fixed harmless nullref during game startup
  • Like 1

Share this post


Link to post
Share on other sites

Awesome.  While I've had almost no problems with Blizzy's toolbar, I've struggled with the stock toolbar - non-functional buttons, duplicate buttons, buttons not appearing, my buttons being eaten by other mod's buttons (and vice versa).

On 1/14/2018 at 6:34 PM, linuxgurugamer said:

Sorry, but its necessary to be sure everything gets loaded in in the correct order

Once this starts to be used, I’ll package the toolbar dll in the same zip file, and will set up ckan to not have a problem with that

Some people quite vocally don't want Blizzy's toolbar and don't want it surprise installed.

The same vocal people are going to delete the 000_Toolbar folder and then complain about mods not working.

I guess it's not enough for the DLL to be in 000_ToolbarControl, for example?

Share this post


Link to post
Share on other sites
2 minutes ago, hab136 said:

Awesome.  While I've had almost no problems with Blizzy's toolbar, I've struggled with the stock toolbar - non-functional buttons, duplicate buttons, buttons not appearing, my buttons being eaten by other mod's buttons (and vice versa).

Some people quite vocally don't want Blizzy's toolbar and don't want it surprise installed.

The same vocal people are going to delete the 000_Toolbar folder and then complain about mods not working.

I guess it's not enough for the DLL to be in 000_ToolbarControl, for example?

I may have to,  ckan is giving me fits about this

Share this post


Link to post
Share on other sites

Ok, new release puts it into it's own folder.

Be sure to delete it from the old folder if you already installed it

Also, it's now in CKAN

Edited by linuxgurugamer

Share this post


Link to post
Share on other sites

I just released my first mod which is using the Toolbar Controller.  More to follow over time

The mod is EngineIgnitor:

Edit:  Another now available, FlightPlan:

 

Edited by linuxgurugamer
  • Like 1

Share this post


Link to post
Share on other sites

New release, 0.1.3.2

  • Fixed bug where calling the SetFalse() wasn't properly doing the callbacks

 

Share this post


Link to post
Share on other sites

Ok, it's a problem in the .version file, I'll take care of it, thanks

New release, 0.1.3.3

  • Fixed download link in .version file

 

Share this post


Link to post
Share on other sites

and of course, right after I do that, a real bug is reported :-)

New release, 0.1.3.4:

  • Fixed problem where stock toolbar button wasn't being deleted

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now