linuxgurugamer

[1.8.x] Toolbar Controller (for modders)

Recommended Posts

21 minutes ago, Apaseall said:

Merely trying to keep my game running :) Thank you for ... well lots of things :)

No problem at all, thanks for letting me know

Share this post


Link to post
Share on other sites

New release, 1.3.5

More fixes for toolbar buttons not being deleted

Share this post


Link to post
Share on other sites

New release, 0.1.4:

  • Added left/right button callbacks
  • Updated documentation
     

Share this post


Link to post
Share on other sites

@linuxgurugamer I'm trying to add support for Toolbar Control on Antenna Helper. It works but throw an exception when clicking on the Blizzy's button, stock one is fine.

Quote

[Toolbar] [ERROR] error while handling click event: AntennaHelper.823779
 
(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

NullReferenceException: Object reference not set to an instance of an object
  at ToolbarControl_NS.ToolbarControl.button_Click (ToolbarControl_NS.ClickEvent e) [0x00000] in <filename unknown>:0
  at ToolbarControl_NS.Button.clicked (System.Object realEvent) [0x00000] in <filename unknown>:0
  at Toolbar.Command.click () [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Toolbar.Log:log(LogLevel, Exception, String, Object[])
Toolbar.Log:error(Exception, String, Object[])
Toolbar.Command:click()
Toolbar.Button:click()
Toolbar.Button:drawInToolbar(Rect, Boolean)
Toolbar.Toolbar:drawButtons()
Toolbar.Toolbar:draw()
Toolbar.ToolbarManager:OnGUI()

Full log. Just launch the game, click twice on the button on quit. Error is at line 12272.

Antenna Helper source file. I've just try in the editor, relevant code in the ToolbarButton region starting line 560. Everything commented is what I used before to do the stock button.

Share this post


Link to post
Share on other sites

I may not be able to get to this intil this evening but, what version are you using?

Share this post


Link to post
Share on other sites
Just now, linuxgurugamer said:

I may not be able to get to this intil this evening but, what version are you using?

ToolbarControl 0.1.4

Toolbar 1.7.16.5

Last version of KSP (x64) on win10 (x64)

Take your time, there is no rush.

Share this post


Link to post
Share on other sites

I've replicated the problem, trying to see if I can fix it in the next few minutes

Edit:  Ok, it's harmless, so you can continue to work.  I know what's going on

and fixed:

New release, 0.1.4.1:

  • Fixed harmless nullrefs which were happening after clicking toolbar button
  • Added checks to all callbacks for nulls

You will probably have to download it manually, it may take CKAN a few hours to update

Edited by linuxgurugamer

Share this post


Link to post
Share on other sites

I'm done integrating Toolbar Contol to Antenna Helper. Very straightforward, coming from the stock applauncher and never used Blizzy's toolbar.

One thing I notice : "ToolbarControl.buttonClickedMousePos" return (0, 0) when clicked on Blizzy's toolbar, return fine with stock. I don't think that actually matter as I can get the same thing with Mouse.screenPos on OnTrue.

My point of wanting the button position was to display the gui next to it, to perfectly align it the mouse position when clicked isn't enough, the actual button position is needed. I now realize that it won't be enough for blizzy toolbar as it can have multiple column...

Anyway I wrote a little method to position the window next to the button, any button, it's not as precise as it was with the button position but it's good enough

Spoiler

private Vector2 GetWindowPosNextToButton (Rect window, Vector2 clickPos, bool useBlizzy)
		{
			float offset, posX, posY;

			if (useBlizzy) {
				offset = 20f;
			} else {
				offset = 30f;
			}

			if (clickPos.x + offset + window.width > Screen.width) {
				// Window on the left of the button
				posX = clickPos.x - offset - window.width;
			} else {
				// Window on the right of the button
				posX = clickPos.x + offset;
			}

			if (clickPos.y + offset + window.height > Screen.height) {
				// Window on the bottom of the button
				posY = clickPos.y - offset - window.height;
			} else {
				// Window on the top of the button
				posY = clickPos.y + offset;
			}

			return new Vector2 (posX, posY);
		}

 

One last thing, should I bundle Toolbar Control with my mod or do you prefer if players get it directly from you ? Personally I prefer the second option.

Share this post


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

I'm done integrating Toolbar Contol to Antenna Helper. Very straightforward, coming from the stock applauncher and never used Blizzy's toolbar.

One thing I notice : "ToolbarControl.buttonClickedMousePos" return (0, 0) when clicked on Blizzy's toolbar, return fine with stock. I don't think that actually matter as I can get the same thing with Mouse.screenPos on OnTrue.

My point of wanting the button position was to display the gui next to it, to perfectly align it the mouse position when clicked isn't enough, the actual button position is needed. I now realize that it won't be enough for blizzy toolbar as it can have multiple column...

Anyway I wrote a little method to position the window next to the button, any button, it's not as precise as it was with the button position but it's good enough

  Reveal hidden contents


private Vector2 GetWindowPosNextToButton (Rect window, Vector2 clickPos, bool useBlizzy)
		{
			float offset, posX, posY;

			if (useBlizzy) {
				offset = 20f;
			} else {
				offset = 30f;
			}

			if (clickPos.x + offset + window.width > Screen.width) {
				// Window on the left of the button
				posX = clickPos.x - offset - window.width;
			} else {
				// Window on the right of the button
				posX = clickPos.x + offset;
			}

			if (clickPos.y + offset + window.height > Screen.height) {
				// Window on the bottom of the button
				posY = clickPos.y - offset - window.height;
			} else {
				// Window on the top of the button
				posY = clickPos.y + offset;
			}

			return new Vector2 (posX, posY);
		}

 

One last thing, should I bundle Toolbar Control with my mod or do you prefer if players get it directly from you ? Personally I prefer the second option.

I'd like you to wait until this evening when I can fix that buttonClickedMousePos problem.  I'm pretty sure I know what it is, if I get some time, I might even be able to fix it during the day.

Otherwise, I'd prefer that you don't bundle, since it is still a work-in-progress.

Share this post


Link to post
Share on other sites

I can already see that this is gonna break my "Adjustable Mod Panel" since all the mods will have exactly the same looking button (same module, same callback).

Can you maybe come up with some way of distinguishing one mod from another on the gameobject level?

Edited by Morse

Share this post


Link to post
Share on other sites
1 hour ago, Morse said:

I can already see that this is gonna break my "Adjustable Mod Panel" since all the mods will have exactly the same looking button (same module, same callback).

Can you maybe come up with some way of distinguishing one mod from another on the gameobject level?

Well, how about a method which will return the button id which is passed in by the code?  It has to be unique.

Share this post


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

Well, how about a method which will return the button id which is passed in by the code?  It has to be unique.

A method where? Your class is supposed to be a component somewhere in the depth of other mods' internals. Also just id would not be enough, since if the button's callback is implemented inside your dll, there won't be even a way to find out what is the name of the mod this button belongs to.

Share this post


Link to post
Share on other sites
51 minutes ago, Morse said:

A method where? Your class is supposed to be a component somewhere in the depth of other mods' internals. Also just id would not be enough, since if the button's callback is implemented inside your dll, there won't be even a way to find out what is the name of the mod this button belongs to.

A public API, which could provide both the mod name and id which are supplied when creating the button.

It sounds like you may need another method which would essentially hide a button, but that is actually a bit more complicated.

Share this post


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

A public API, which could provide both the mod name and id which are supplied when creating the button.

It sounds like you may need another method which would essentially hide a button, but that is actually a bit more complicated.

The hiding of the button I'll manage myself :). But when I get a list of buttons from the application panel I need to know which button is which, so that to hide the ones that user chose. I use the combination of "module name" + "callback name", but it won't work for a wrapper. I also use the icon hashcode as an additional identificator, but this is more of an emergency measure, and I don't want to rely on it too much.

A "public API" is a vague term. Just adding the methods into the class would be pointless, because I don't even have an access to the object in the first place. Also, I'd rather avoid a hard dependency on your mod, since the user might not even have a single mod that uses it, but will have to install it anyway.

ok, let's maybe put it on hold for some time. I have an idea how to store the needed information, but let's wait until your code more or less stabilizes. A method I'm thinking about involves a fair share of black magic, so we'll have to wait for a full moon first :)

Share this post


Link to post
Share on other sites

You can use Reflection to see if my mod is loaded, and if so, then access it's methods

Right now I don't store any sort of list of buttons, but that's doable.  In fact, I could even take a look at your code and create the same "module name" + "callback name", and return that

Share this post


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

You can use Reflection to see if my mod is loaded, and if so, then access it's methods

"it's" methods? You don't access methods of the "mod", you access methods of the object. And with your design, every mod that uses your controller will have it's own instance of that object. Of course I could do a global lookup over all the objects in the game every time a new button is added to the stock panel, but that would be so wrong on so many levels...

Share this post


Link to post
Share on other sites

please stop the criticism of the terminology.

I could create a static, global list which would hold all the created objects, and then there could be a method of the OBJECT which could read and return the list, either one at a time or the whole list.

 

Share this post


Link to post
Share on other sites

A static list of all the mods that could be accessed using the reflection. Yep, that should solve the task. The whole list would probably be redundant, but a method that would return the name of the button (or of a mod, or... anything, to just show the user where this button came from) and some unique id based on the ApplicationLauncherButton object - that would be nice. Something like

/// <summary>
/// Checks whether the given button was created by this mod.
/// </summary>
/// <param name="button">the button to check</param>
/// <param name="name">the human-readable description of the button</param>
/// <param name="id">the unique ID of the button</param>
/// <returns>true, if the button was created by the mod, false otherwise</returns>
public static bool IsButtonManaged (ApplicationLauncherButton button, out string name, out string id)

 

Share this post


Link to post
Share on other sites

New release, 0.1.4.2:

  • Fixed mouse position for Blizzy toolbar
  • Inverted the y value for the mouse position

Share this post


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

New release, 0.1.4.2:

  • Fixed mouse position for Blizzy toolbar
  • Inverted the y value for the mouse position

I've just tested and everything works as expected, thanks.

Share this post


Link to post
Share on other sites

New release, 0.1.4.3

  • Added method/function to allow mods to check to see if a toolbarbutton is controlled by this mod
  • Renamed License.md and README.md

Share this post


Link to post
Share on other sites

New release, 0.1.4.4:

  • Improved the UseBlizzy method to now allow setting it BEFORE creating the toolbar, this makes it possible to not have to use the UseBlizzy in an OnGUI if not desired
  • Added methods:  SetTrue() and SetFalse()

The OP has been updated as well

Edited by linuxgurugamer

Share this post


Link to post
Share on other sites

I'm thinking of adding some more versions of the AddToAllToolbars methods.  The new versions will duplicate the existing ones, with the addition of one new parameter:

bool initialBlizzy

This will eliminate the need to call the UseBlizzy() method before the call to initialize it.

Any comments?

Share this post


Link to post
Share on other sites

New release, 0.1.4.5 (was a stealth release)

  • Fixed typo in the UseBlizzy method which was causing the blizzy toolbar to be always selected if it was called before the initial button creation

New release, 0.1.4.6:

  • Added code to not try to use tooltips if not in a scene which supports it

Share this post


Link to post
Share on other sites

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.