Jump to content

[1.2.0] Toolbar 1.7.13 - Common API for draggable/resizable buttons toolbar


blizzy78

Recommended Posts

Hello all, I want to start by saying I am a complete NOOB at this, that includes C#... I have been trying to add toolbar to the protractor module and I am positive I have borked things pretty bad. When I run debug it pops one error message about


class ProtractorButtton : MonoBehavior

regaurding the MonoBehavior...

I created a fork at https://github.com/mrwizerd/protractor

My first goal was to get toolbar in and working, then figure out how to remove the old toolbutton. Any help would be appreciated.

I am not sure if it will find other problems, but if I can figure out how to get it in then how to get the rest out... I am a total noob though so I don't know if I will be successful.

Link to comment
Share on other sites

Well, unfortunately, I was unsure as to were to go. I had hoped, that I could get help here to add toolbar to this mod. Unfortunately the creator of the mod was not available to help so I figured I would try on my own. I don't wish to be rude, nor offend anyone I am just at a loss. The documentation that is available, shows that this is how to add the toolbar to a mod with instructions to add the line with monobehavior and though I doubt it was my only mistake, it was the only thing that Visual Studio complained about when I debugged. Anyways, I will seek help elsewhere, sorry for the inconvenience.

Link to comment
Share on other sites

I'm sorry if my previous comment sounded harsh, I certainly didn't mean to offend. I just don't think this is the right place or thread to seek help in programming KSP plugins, even with the mild Toolbar Plugin relevance.

Link to comment
Share on other sites

Thanks, I haven't added it yet because it looked like it was still a work in progress. It seems to be more complete now on a closer look. I just wish he would make use of the new PopupMenuDrawable feature instead of rolling his own drop-down menu :-/

Link to comment
Share on other sites

I just wish he would make use of the new PopupMenuDrawable feature instead of rolling his own drop-down menu :-/

Hi Blizzy, thanks for adding ScienceAlert your list. I didn't end up going with PopupMenuDrawable because it doesn't offer any advantage over IDrawable in my case.

Here's what PopupMenuDrawable and my IDrawable implementation look like side-by-side:

PopupMenudrawable-vs-custom.png

  1. The skin of PopupMenuDrawable can't be changed, and does not change with the button skins. Since I designed ScienceAlert to look as stock as possible, it was instantly jarring when compared to the options window
  2. it doesn't give you an option on placement. Feedback from my development thread made it clear consistent placement was desirable
  3. it will display either a button or a line. There's no opportunity to label anything unless I want it to be indistinguishable from a button
  4. it will only let you add buttons, not remove them. Although I could recreate it every time a new experiment changed status while it was visible, that feels like coding my way around an oversight than a good solution
  5. The actual implementation of PopupMenuDrawable is hidden so it can't be fixed or customized in any way

Link to comment
Share on other sites

it doesn't give you an option on placement. Feedback from my development thread made it clear consistent placement was desirable

Positioning is determined by the drawable mechanism itself. It doesn't matter what the actual drawable is displaying.

it will display either a button or a line. There's no opportunity to label anything unless I want it to be indistinguishable from a button

Not sure what you mean here. Are you talking about the "Available Experiments" label?

it will only let you add buttons, not remove them. Although I could recreate it every time a new experiment changed status while it was visible, that feels like coding my way around an oversight than a good solution

It is indeed intended to be recreated every time you need something changed.

The actual implementation of PopupMenuDrawable is hidden so it can't be fixed or customized in any way

I usually make things private/internal from the start, then gradually open up once I figure out what's necessary. So just speak up and we'll see :)

Link to comment
Share on other sites

  • it doesn't give you an option on placement. Feedback from my development thread made it clear consistent placement was desirable

Blizzy, in particular, what was happening there was, if you place Toolbar adjacent to a stock display, e.g., directly underneath the altimeter .. then with a "short" window, such as his 1-button case, it would appear above, overwriting the altimeter .. with a "tall" window, it would appear below. More predictability was desirable given the frequency with which Science Alert gets used! :)

Link to comment
Share on other sites

then with a "short" window, such as his 1-button case, it would appear above, overwriting the altimeter

Ah, I see. Perhaps I should add some code to the drawable positioning so that it will never block the altimeter (and other important GUI features.)

Link to comment
Share on other sites

Not sure what you mean here. Are you talking about the "Available Experiments" label?
In this case yes, but goes for any contents. There isn't any visible indication of which button opened the popup menu. Let me illustrate with a contrived example:

which_button_nobody_knows.png

Which "plugin" opened that menu, and how do I close it? My main issue with it isn't that though; it's that you can't customize it at all. It looks very ... utilitarian. How readable is it if it appeared over a GUI element?

8hDHV.jpg

Not great. It could be handy for a quick debug menu (in fact, my debug menu could have been done more easily this way) but it doesn't fit with the rest of the game's style.

Positioning is determined by the drawable mechanism itself. It doesn't matter what the actual drawable is displaying.
Yes it does. The drawable is expected to return the rect it used. If that rect can change, drawable can choose a new location under the right circumstances. Let's say I've got three experiments available. A fourth just became available! Recreate the menu, add the extra option, and ..

drawable_repositions_rect.png

Of course, the moment the user clicks any of those buttons and it gets removed from the list, the popup will jump back to the previous position because it'll fit there now. You can see how a user who's likely running through the list of experiments could be irritated with that. This alone is a dealbreaker in my case

I usually make things private/internal from the start, then gradually open up once I figure out what's necessary. So just speak up and we'll see :)
I asked about why you hide the texture and forced modders to go through GameDatabase once. I thought it was just an oversight. I was still unable to convince you and had to use an ugly hack and cause thousands of unnecessary string reference comparisons per second to make ScienceAlert's animation work :(
Link to comment
Share on other sites

There isn't any visible indication of which button opened the popup menu.

That is correct, and I'd agree that this needs to be worked on (in the Toolbar Plugin itself.)

The drawable is expected to return the rect it used. If that rect can change, drawable can choose a new location under the right circumstances. ... Of course, the moment the user clicks any of those buttons and it gets removed from the list, the popup will jump back to the previous position because it'll fit there now.

That's not what I actually meant. I was under the impression that you didn't use the PopupMenuDrawable because one of the reasons was that its positioning was not always the same. So I was trying to point out that the positioning is not done by the PopupMenuDrawable itself, but the drawable mechanism as a whole, regardless of what actual drawable you're implementing.

Anyway, I see your point there. The current positioning mechanism is meant more for sporadic use, which in its current implementation gets in the way when the drawable gets interacted with more often (such as in your case with the experiments buttons.) I think I should modify it to some sort of "prefer last position" kind of way. It would position things like it does right now, moving them if they don't fit. But the next time the drawable needs to be displayed, it would position it the same way as before, as long as it fits there, only moving it if necessary.

I asked about why you hide the texture and forced modders to go through GameDatabase once. I thought it was just an oversight. I was still unable to convince you and had to use an ugly hack and cause thousands of unnecessary string reference comparisons per second to make ScienceAlert's animation work :(

Actually I don't really see the point with animated toolbar buttons, but that's maybe just me. I'm perfectly fine with buttons that permanently change their icon to represent some state to notify the user, but I think doing animations is going overboard.

I haven't looked at the code you did for animations, but you could also use some sort of state machine that uses ints instead of strings to represent the current animation frame.

As for not allowing access to the actual Texture2D object, that is one of the things I mentioned keeping private at first. I don't like the idea having developers modify random textures without the Toolbar Plugin noticing. I'd rather make them go through a well-defined API.

Link to comment
Share on other sites

I use an animation to get the player's attention. The sound of rocket engines or chatterer can easily drown out the rather subtle bubble sound. But why put limits on it?

I haven't looked at the code you did for animations, but you could also use some sort of state machine that uses ints instead of strings to represent the current animation frame.

Of course I use an int. And at some point that int has to turn into a string to pass into IButton.TexturePath, and then TexturePath will compare that string to every string in GameDatabase one at a time until it gets a hit. That's exactly my problem with it.

As for not allowing access to the actual Texture2D object, that is one of the things I mentioned keeping private at first. I don't like the idea having developers modify random textures without the Toolbar Plugin noticing. I'd rather make them go through a well-defined API.

Why wouldn't the toolbar plugin notice? Why does the toolbar care what the texture is? What's wrong with a public property?

Link to comment
Share on other sites

I use an animation to get the player's attention. The sound of rocket engines or chatterer can easily drown out the rather subtle bubble sound. But why put limits on it?

Because there is no way for the player to turn stuff down if it gets annoying. If I go and add a nice button icon animation feature to the Toolbar, I'm almost 100% sure we'll see blinking and flashing buttons in no time. The next thing I see me adding then is an option for players to turn off animations. Of course not for all buttons at once, but for specific buttons. Things tend to spiral out of control pretty quickly if there are no restrictions.

and then TexturePath will compare that string to every string in GameDatabase one at a time until it gets a hit.

It doesn't do that. It uses GameDatabase.Instance.GetTexture("..."), and if that method doesn't use a hash map, then Squad is doing something fundamentally wrong.

Why does the toolbar care what the texture is? What's wrong with a public property?

It does not care. I just don't like things like these being changed behind my back.

Link to comment
Share on other sites

Because there is no way for the player to turn stuff down if it gets annoying. If I go and add a nice button icon animation feature to the Toolbar, I'm almost 100% sure we'll see blinking and flashing buttons in no time. The next thing I see me adding then is an option for players to turn off animations. Of course not for all buttons at once, but for specific buttons. Things tend to spiral out of control pretty quickly if there are no restrictions.

Uh ... shouldn't that be between the developers of the mod and their users? Why would you care? Why would you need to police the animations yourself? I'm not talking about adding an animation feature, I'm talking about letting a modder assign a texture with a public Texture2D property instead of making them give you a string and the toolbar fishing it out of GameDatabase. You really have no way to stop anybody from animating their buttons if they want to. You're just punishing the player by harming performance :huh:

It doesn't do that. It uses GameDatabase.Instance.GetTexture("..."), and if that method doesn't use a hash map, then Squad is doing something fundamentally wrong.

Uh, that's exactly what it does. TexturePath takes a string, gives the string to GameDatabase and GetTexture looks through System.Collections.List<GameDatabase.TextureInfo> one by one doing a comparison on the texture's url. You can access this list directly yourself and see.

It does not care. I just don't like things like these being changed behind my back.

What? Is setting an IButton's TexturePath to something different "changing stuff behind your back" too? Are we talking about the same thing? Is there a technical reason why TexturePath can take a string and notify the toolbar of a change but a Texture property can't take a Texture2D and do the same? Maybe I'm misunderstanding the API in some way

Link to comment
Share on other sites

You're just punishing the player by harming performance

Not the way you make it seem with "thousands of unnecessary string reference comparisons per second." Of course I'm holding onto the Texture2D object as long as the IButton.TexturePath does not change. I'm not looking up all buttons' textures every single frame.

You really have no way to stop anybody from animating their buttons if they want to.

That is correct. But that doesn't mean I have to open up API that I don't want to open up.

GetTexture looks through System.Collections.List<GameDatabase.TextureInfo> one by one doing a comparison on the texture's url. You can access this list directly yourself and see.

I can, but that doesn't really help because I don't have the source of GetTexture() to look at. If you believe Squad doesn't use some sort of hash map there and is hurting performance, you should file a bug report with them.

Is there a technical reason why TexturePath can take a string and notify the toolbar of a change but a Texture property can't take a Texture2D and do the same?

You can modify the texture's contents directly.

Link to comment
Share on other sites

Not the way you make it seem with "thousands of unnecessary string reference comparisons per second." Of course I'm holding onto the Texture2D object as long as the IButton.TexturePath does not change. I'm not looking up all buttons' textures every single frame.

No, I mean in the case of somebody doing an animated button. The only person who suffers is the player, and your fears that all buttons will become animated are irrelevant because that capability already exists and has been used. Either you prevent it and interested modders will find an alternative, or you allow it to occur and mod users will choose for themselves what they prefer.

I can, but that doesn't really help because I don't have the source of GetTexture() to look at. If you believe Squad doesn't use some sort of hash map there and is hurting performance, you should file a bug report with them.

ScienceAlert accesses that list directly and places textures in there. It should be apparent that Squad uses no hash map. You don't need the source of GetTexture to know that a public list is no hash map. I go right from adding items to the list to assigning a toolbar texture and it works. If Squad used some kind of hash map and rebuilt it somewhere, that wouldn't work.

You can modify the texture's contents directly.

Every texture you use is kept in a public list so trying to prevent modders from changing a texture is like trying to hold back a river with your hands. I can, of course, always change the texture myself without informing the toolbar at any time. That's why it's surprising to hear how vehement you are against "mods changing the texture behind your back". You realize that adding such a property does the exact opposite thing right? You'll be informed any time the plugin wants the texture to change

Texture2D tex = GameDatabase.Instance.GetTexture("000_Toolbar/folder", false);

if (tex == null)
Log.Error("Toolbar tex is null");

var pixels = tex.GetPixels32();

for (int i = 0; i < pixels.Length; ++i)
{
var c = pixels[i];

pixels[i] = new Color((1f - c.r / 255f), 1f - c.g / 255f, 1f - c.b / 255f, 0.5f);
}

tex.SetPixels32(pixels);
tex.Apply();

That is correct. But that doesn't mean I have to open up API that I don't want to open up.

Fair enough. It's your mod. It's not your right to opening it that I question, I just don't agree with the reasons that you're giving. They don't make sense to me. It's apparent that you don't see any logic fault in your argument so I won't argue any further. Thanks for a great mod

Link to comment
Share on other sites

ScienceAlert accesses that list directly and places textures in there. It should be apparent that Squad uses no hash map. You don't need the source of GetTexture to know that a public list is no hash map.

The way you describe it makes it apparent, of course. It didn't occur to me to place textures into that list directly, because that list should have been private from the get go. So this is where my previous statement comes in, that is, Squad is doing something wrong there. Access to an internal list like that should never be granted directly.

Every texture you use is kept in a public list so trying to prevent modders from changing a texture is like trying to hold back a river with your hands.

I know that. Still it doesn't mean I need to open up specific API. If you want to modify it by fetching it from the GameDatabase first, please do so. If you want to use reflection to put it directly into the Toolbar Plugin's structures, then by any means, please do it. But don't complain later if something breaks for any reason.

It's not your right to opening it that I question

Not quite, but you're kind of pressuring to open up API to accomplish things that "can be achieved using different tools anyway" (my words.) As stated above, I am aware that the textures can be changed without me ever noticing it. I'm not happy about that, quite to the contrary - I'd rather have them be immutable, or have developers jump through some other hoops to be able to change them. But at least I can make Toolbar API users go into some direction by not allowing access to the textures directly.

Link to comment
Share on other sites

The way you describe it makes it apparent, of course.

I thought I made it clear I knew exactly what I was talking about. You didn't even look into it?

But at least I can make Toolbar API users go into some direction by not allowing access to the textures directly.

We just agreed you can't force them to do anything. All you can do is punish the player when the api user goes around you. You don't want them to go around you but you're also not willing to provide a method that lets them go through you either.

I'm not pressuring you to add a public texture property because it will let me do what I can't already, I'm doing it because the average player can benefit from not wasting cpu time in a cpu-limited game on what I consider to be an API oversight. If that's not a good enough reason then we aren't going to be able to find any common ground.

Link to comment
Share on other sites

I'm doing it because the average player can benefit from not wasting cpu time in a cpu-limited game

I wonder what kind of CPU time waste you are thinking of here. I don't know the specifics of the animations you are doing, but I can't imagine they're beyond the 5-10 FPS range.

Link to comment
Share on other sites

Gentlemen, please don't take anything personally -- you are both very intelligent people with awesomely useful mods that have contributed a lot to the community.

You disagree about the API - and sadly, in part due to my feedback to xEvilReeperx during WIP testing; I feel some responsibility.

I would prefer you two to get along, or if not, at least keep cool enough heads that you've no forum-feud bad blood!

Link to comment
Share on other sites

I wonder what kind of CPU time waste you are thinking of here. I don't know the specifics of the animations you are doing, but I can't imagine they're beyond the 5-10 FPS range.

It's not a lot, but why waste it?

You disagree about the API - and sadly, in part due to my feedback

Actually, this aspect of the api doesn't have anything to do with any feedback from ScienceAlert so you're in the clear. It's just a discussion

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...