Jump to content

UI_ChooseOption - oddities when displaying long names


Recommended Posts

On 4/3/2016 at 11:34 AM, Warezcrawler said:

How does the UI_CHOOSEOPTION work? How is it defined, and how does one get a function triggered when changing it?

It's a UI control just like UI_FloatEdit, UI_Toggle, etc

[KSPField(guiActiveEditor = true, isPersistant = true, guiName = "Subtype")]
[UI_ChooseOption(affectSymCounterparts = UI_Scene.Editor, options = new[] { "None" }, scene = UI_Scene.Editor, suppressEditorShipModified = true)]
public int subtypeIndexControl = 0;

suppressEditorShipModified prevents onEditorShipModified from being fired (the default is that it is fired).  Set this if you're going to fire it yourself after doing whatever update is supposed to happen.

If you know what the options are beforehand, you can set them there.  In my case, they're dynamic, so I have to set them in OnStart()

public override void OnStart(PartModule.StartState state)
{
    // ...

    BaseField chooseField = Fields[nameof(subtypeIndexControl)];
    chooseField.guiName = switcherDescription;

    UI_ChooseOption chooseOption = (UI_ChooseOption)chooseField.uiControlEditor;
    chooseOption.options = subtypes.Select(s => s.title).ToArray();
}

You can listen for the value being changed using onFieldChanged

public override void OnStart(PartModule.StartState state)
{
    // ...
    
    chooseOption.onFieldChanged = UpdateFromGUI;
}

private void UpdateFromGUI(BaseField field, object oldValueObj)
{
    int oldValue = (int)oldValueObj; // If you actually care about it
    UpdateSubtype();
    GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
}

(modified a bit from my actual code for clarity)

Edited by blowfish
new information
Link to comment
Share on other sites

Thanks. That's a great description.

Is there really no way of calling a specific function when the UI_CHOOSEOPTION changes? That seems wierd....

I found this "onFieldChanged =" property, but I can't get it to work. The name seems as if this is want should be used when the user clicks for next option, does it not?

@NathanKell Maybe you know if there is some natural way of calling a procedure when a new option is chosen?

Link to comment
Share on other sites

I didn't notice onFIeldChanged before (was it added in a recent build?).  I think that might solve the problem actually.

Maybe the reason it doesn't work for you is that you can't set its value in the attribute (since only basic types are allowed as attribute parameters).  I've updated the code above with something I believe will work, will be testing shortly.

Link to comment
Share on other sites

Nice catch on the callback field; seems its available for all of the UI controls, as well as disabling the editor update events.  Now to figure out how to use it :)

These were def. not available in the *72 build that I previously had linked against.

Likely need to set it manually during OnStart() by accessing the module.Fields["fieldName"].uiControl.onFieldChanged field; unsure what to set it with.  Your example seems plausible though.

Those changes will clean up a ton of problems I was encountering with editor-events firing... alot... and at weird times.

 

A big thanks to whomever implemented them :)

 

Edit: Confirm that blowfish's example from above works for setting the callback method;  Yay!

Edited by Shadowmage
Link to comment
Share on other sites

Oh, and something else to note: onFieldChanged will not fire for symmetry counterparts.  The field's value will update, however (if affect symmetry is set).

Edited by blowfish
Link to comment
Share on other sites

I've been looking at the option "display =" in UI_CHOOSE option. I figured that it is the give an alternative display of the value you can choose from. But I cannot get it to override the options in the GUI.

Have anybody else had success in using this?

Link to comment
Share on other sites

7 hours ago, Warezcrawler said:

I've been looking at the option "display =" in UI_CHOOSE option. I figured that it is the give an alternative display of the value you can choose from. But I cannot get it to override the options in the GUI.

Have anybody else had success in using this?

It doesn't look like display is actually used.  Maybe this was intended to be a more human-readable form of options, but it hardly matters if you're using it on an integer field (it can be used on an int or string field).

Link to comment
Share on other sites

@blowfish I have tested the UI_CHOOSEOPTION based on your example, and I can comfirm that it is working. Very nice description :cool:

Spoiler
On 3/4/2016 at 8:48 PM, blowfish said:

It's a UI control just like UI_FloatEdit, UI_Toggle, etc



[KSPField(guiActiveEditor = true, isPersistant = true, guiName = "Subtype")]
[UI_ChooseOption(affectSymCounterparts = UI_Scene.Editor, options = new[] { "None" }, scene = UI_Scene.Editor, suppressEditorShipModified = true)]
public int subtypeIndexControl = 0;

suppressEditorShipModified prevents onEditorShipModified from being fired (the default is that it is fired).  Set this if you're going to fire it yourself after doing whatever update is supposed to happen.

If you know what the options are beforehand, you can set them there.  In my case, they're dynamic, so I have to set them in OnStart()



public override void OnStart(PartModule.StartState state)
{
    // ...

    var chooseField = Fields[nameof(subtypeIndexControl)];
    chooseField.guiName = switcherDescription;

    var chooseOption = chooseField.uiControlEditor as UI_ChooseOption;
    chooseOption.options = subtypes.Select(s => s.title).ToArray();
}

You can listen for the value being changed using onFieldChanged



public override void OnStart(PartModule.StartState state)
{
    // ...
    
    chooseOption.onFieldChanged = UpdateFromGUI;
}

private void UpdateFromGUI(BaseField field, object oldValueObj)
{
    int oldValue = (int)oldValueObj; // If you actually care about it
    UpdateSubtype();
    GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
}

(modified a bit from my actual code for clarity)

 

Link to comment
Share on other sites

display =? Hmm, I may have missed something, I'll take a look.

As for the font size issues, that's Unity. All the UI_ChooseOption code does is set the text to display.

On 03/04/2016 at 6:15 AM, blowfish said:

Oh, and something else to note: onFieldChanged will not fire for symmetry counterparts.  The field's value will update, however (if affect symmetry is set).

This was a deliberate decision. onEditorShipModified never fired for counterparts, either, so it seemed valid. My thinking was that the callback would handled counterparts as necessary (saves on callback storms).

Link to comment
Share on other sites

32 minutes ago, taniwha said:

This was a deliberate decision. onEditorShipModified never fired for counterparts, either, so it seemed valid. My thinking was that the callback would handled counterparts as necessary (saves on callback storms).

Makes sense, I figured it was just worth mentioning so that people know what the expected behavior is.

Link to comment
Share on other sites

5 hours ago, taniwha said:

I had indeed missed implementing display. The fix should be in the next build.

Sounds great :)

Another thing. I had some issues creating an UI_CHOOSEOPTION which worked in flight based on the description blowfish did.

What I found was, that setting inFieldChanged and the options from code, I had to code specific for each (editor and flight). Is there some way to do it in one go? It's nice having the posibility to set it individually, but in my case they are to be symmetric.

Is this a "feature" or is it an oversight or is it just me :wink:?

        public override void OnStart(PartModule.StartState state)
        {
            var chooseField = Fields["ChooseOption"];
            chooseField.guiName = "Choose Something";
			
			//for VAB
            var chooseOptionEditor = chooseField.uiControlEditor as UI_ChooseOption;
            chooseOptionEditor.options = new string[3] { "1", "2", "3" };
            chooseOptionEditor.onFieldChanged = UpdateFromGUI;

			//For inflight
			var chooseOptionFlight = chooseField.uiControlFlight as UI_ChooseOption;
            chooseOptionFlight.options = new string[3] { "1", "2", "3" };
            chooseOptionFlight.onFieldChanged = UpdateFromGUI;
        }

 

Link to comment
Share on other sites

I have observed something odd..... Which is great for thing thread :D

I've created a UI_CHOOSEOPTION to change engine setup (thrust, fuel consumption etc.). Now when changing midair using my new UI_CHOOSEOPTION, all of a sudden the A + D buttons get linked to the functions for next and previous option.

If I click somewhere else (closing the right click menu) then the "link" is reset, and A + D does not impact the choose option.....

@taniwha Is this a bug that need being reported? Or is it intended. (I can say this. It has caused me to crash my plane :sealed:)

Link to comment
Share on other sites

1 hour ago, Warezcrawler said:

I have observed something odd..... Which is great for thing thread :D

I've created a UI_CHOOSEOPTION to change engine setup (thrust, fuel consumption etc.). Now when changing midair using my new UI_CHOOSEOPTION, all of a sudden the A + D buttons get linked to the functions for next and previous option.

If I click somewhere else (closing the right click menu) then the "link" is reset, and A + D does not impact the choose option.....

@taniwha Is this a bug that need being reported? Or is it intended. (I can say this. It has caused me to crash my plane :sealed:)

That issue has already been reported on the tracker (UI controls responding to keyboard input after adjusting them with the mouse), and I believe it is already confirmed/being looked into.

Link to comment
Share on other sites

4 hours ago, Warezcrawler said:

What I found was, that setting inFieldChanged and the options from code, I had to code specific for each (editor and flight). Is there some way to do it in one go? It's nice having the posibility to set it individually, but in my case they are to be symmetric.

uiControlFlight and uiControlEditor are the same type, so you don't need the two blocks like that, just:

UI_ChooseOption control = is_flight ? field.uiControlFlight : field.uiControlEditor;

and then the rest of your code can be shared if appropriate. "var" might work for that expression, dunno. (NOTE: that's pseudo code, edit as appropriate :))

Edited by taniwha
Link to comment
Share on other sites

brilliant..... will change the code ASAP :cool: THANKS

----

I ended up with this if it can help anybody else

UI_ChooseOption chooseOption = HighLogic.LoadedSceneIsFlight ? chooseField.uiControlFlight as UI_ChooseOption : chooseField.uiControlEditor as UI_ChooseOption;

chooseOption.options = Options;					//Options is an array with my options
chooseOption.display = arrIntakeNames;			//arrIntakeNames is an array of the names I want shown when the function is fixed
chooseOption.onFieldChanged = selectIntake;		//selectIntake is the currently selected option

 

Edited by Warezcrawler
Code example added
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...