DMagic

PopupDialog and the DialogGUI classes

Recommended Posts

I'm wondering if anyone has looked into the PopupDialog system or made a mod using it.

From what I can tell the DialogGUI classes seem to broadly replicate the layout system used by the old OnGUI methods, but have the end result of creating UI elements using the Unity 4.6 system.

There are a number of layout related classes: DialogGUIHorizontalLayout, DialogGUIVerticalLayout, DialogGUILayoutEnd, DialogGUIFlexibleSpace, DialogGUIScrollList, etc... that would appear to have the same function as the GUILayout classes.

Then there are classes for the common UI elements: DialogGUIBox, DialogGUIImage, DialogGUILabel, DialogGUIButton, DialogGUIToggle, etc... Here you can create elements by adding a name, a callback, an image, etc..., each element type has multiple constructors that allow for different types, for instance buttons with a text label or buttons with an image, or manual size or layout data.

The PopupDialog class is used to actually display the window, and has a few static constructor methods that call for a MultiOptionDialog instance.

The MultiOptionDialog is created with an array of DialogGUIBase elements (basically the list of all your DialogGUI elements set in the order you want) and a UISkinDef, which is used to apply the UI style elements, like the window background, button sprites, font, etc... So if someone wanted to they could presumably create a UISkinDef with the old Unity GUI skin, or you can just use the default KSP skin.

 

I haven't really dug into how it works, I just noticed PopupDialogs coming up a lot when looking at things with Debug Stuff, but it seems like these could provide a good alternative to the sometimes tedious and complex Unity UI development, and would be much better than using the old, slow, OnGUI.

If someone could fill in more information that would be great.

  • Like 3

Share this post


Link to post
Share on other sites

There we go, :kiss: Sarbian has added a nice example to Module Manager of how to spawn a simple popup dialog to replace the OnGUI system.

https://github.com/sarbian/ModuleManager/blob/master/moduleManager.cs#L236-L270

        internal void Update()
        { 
			if (GameSettings.MODIFIER_KEY.GetKey() && Input.GetKeyDown(KeyCode.F11) 
                && (HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.MAINMENU)
                && !inRnDCenter)
            {
                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                    new Vector2(0.5f, 0.5f),
                    new MultiOptionDialog("",
                        "ModuleManager",
                        HighLogic.UISkin,
                        new Rect(0.5f, 0.5f, 150f, 60f),
                        new DialogGUIFlexibleSpace(),
                        new DialogGUIVerticalLayout(
                            new DialogGUIFlexibleSpace(),
                            new DialogGUIButton("Reload Database",
                                delegate
                                {
                                    MMPatchLoader.keepPartDB = false;
                                    StartCoroutine(DataBaseReloadWithMM());
                                }, 140.0f, 30.0f, true), 
                            new DialogGUIButton("Quick Reload Database",
                                delegate
                                {
                                    MMPatchLoader.keepPartDB = true;
                                    StartCoroutine(DataBaseReloadWithMM());
                                }, 140.0f, 30.0f, true),
                            new DialogGUIButton("Dump Database to Files",
                                delegate
                                {
                                    StartCoroutine(DataBaseReloadWithMM(true));
                                }, 140.0f, 30.0f, true),
                            new DialogGUIButton("Close",() => {}, 140.0f, 30.0f, true)
                            )),
                    false,
                    HighLogic.UISkin);
            }

It's just a simple script to spawn the MM Database reload window. The layout elements control the placement of the elements within the window and the buttons are each added with a name and a callback.

  • Like 4

Share this post


Link to post
Share on other sites

For a slightly more complex example of a PopupDialog check out the code from Science Relay. It uses a PopupDialog to spawn a scrollable list of buttons, each with an associated label, and allows for a separate, warning popup under certain conditions.

private PopupDialog spawnDialog(ExperimentResultDialogPage page)
		{
			List<DialogGUIBase> dialog = new List<DialogGUIBase>();

			dialog.Add(new DialogGUIHorizontalLayout(true, false, 0, new RectOffset(), TextAnchor.UpperCenter, new DialogGUIBase[]
				{
					new DialogGUILabel(string.Format("Transmit data to the selected vessel:\n{0}", page.pageData.title), false, false)
				}));

			transferAll = false;

			if (resultsDialog.pages.Count > 1)
			{
				dialog.Add(new DialogGUIHorizontalLayout(true, false, 0, new RectOffset(), TextAnchor.UpperCenter, new DialogGUIBase[]
				{
				new DialogGUIToggle(false, "Transfer All Open Data",
					delegate(bool b)
					{
						transferAll = !transferAll;
					}, 200, 20)
				}));
			}

			List<DialogGUIHorizontalLayout> vessels = new List<DialogGUIHorizontalLayout>();

			for (int i = connectedVessels.Count - 1; i >= 0; i--)
			{
				KeyValuePair<Vessel, double> pair = connectedVessels[i];

				Vessel v = pair.Key;

				float boost = signalBoost((float)pair.Value, v, currentPage.pageData, page.xmitDataScalar);

				DialogGUILabel label = null;

				if (settings.transmissionBoost)
				{
					string transmit = string.Format("Xmit: {0:P0}", page.xmitDataScalar * (1 + boost));

					if (boost > 0)
						transmit += string.Format("(+{0:P0})", boost);

					label = new DialogGUILabel(transmit, 130, 25);
				}

				DialogGUIBase button = null;

				if (settings.showTransmitWarning && page.showTransmitWarning)
				{
					button = new DialogGUIButton(
											v.vesselName,
											delegate
											{
												spawnWarningDialog(
												new ScienceRelayData()
												{
													_data = page.pageData,
													_host = page.host,
													_boost = boost,
													_source = FlightGlobals.ActiveVessel,
													_target = v,
												},
												currentPage.transmitWarningMessage);
											},
											160,
											30,
											true,
											null);
				}
				else
				{
					button = new DialogGUIButton<ScienceRelayData>(
											v.vesselName,
											transferToVessel,
											new ScienceRelayData()
											{
												_data = page.pageData,
												_host = page.host,
												_boost = boost,
												_source = FlightGlobals.ActiveVessel,
												_target = v,
											},
											true);

					button.size = new Vector2(160, 30);
				}

				DialogGUIHorizontalLayout h = new DialogGUIHorizontalLayout(true, false, 4, new RectOffset(), TextAnchor.MiddleCenter, new DialogGUIBase[] { button });

				if (label != null)
					h.AddChild(label);

				vessels.Add(h);
			}

			DialogGUIBase[] scrollList = new DialogGUIBase[vessels.Count + 1];

			scrollList[0] = new DialogGUIContentSizer(ContentSizeFitter.FitMode.Unconstrained, ContentSizeFitter.FitMode.PreferredSize, true);

			for (int i = 0; i < vessels.Count; i++)
				scrollList[i + 1] = vessels[i];

			dialog.Add(new DialogGUIScrollList(Vector2.one, false, true,
				new DialogGUIVerticalLayout(10, 100, 4, new RectOffset(6, 24, 10, 10), TextAnchor.MiddleLeft, scrollList)
				));

			dialog.Add(new DialogGUISpace(4));

			dialog.Add(new DialogGUIHorizontalLayout(new DialogGUIBase[]
			{ 
				new DialogGUIFlexibleSpace(),
				new DialogGUIButton("Cancel Transfer", popupDismiss),
				new DialogGUIFlexibleSpace(),
				new DialogGUILabel(version, false, false)
			}));

			RectTransform resultRect = resultsDialog.GetComponent<RectTransform>();

			Rect pos = new Rect(0.5f, 0.5f, 300, 300);

			if (resultRect != null)
			{
				Vector2 resultPos = resultRect.position;

				float scale = GameSettings.UI_SCALE;

				int width = Screen.width;
				int height = Screen.height;
				
				float xpos = (resultPos.x / scale) + width / 2;
				float ypos = (resultPos.y / scale) + height / 2;

				float yNorm = ypos / height;

				pos.y = yNorm;

				pos.x = xpos > (width - (550 * scale)) ? (xpos - 360) / width : (xpos + 360) / width;
			}
			
			return PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("", "Science Relay", UISkinManager.defaultSkin, pos, dialog.ToArray()), false, UISkinManager.defaultSkin);
		}

Note the use of the DialogGUIContentSizer as the first element in the DialogGUIScrollList, it controls the size of the scroll window (the full size, not the window that is currently shown).

Also note near the top where each DialogGUIButton is created, there are two possible versions, one that calls a method (and uses the DialogGUIButton<T>), and the other that spawns another popup.

The section at the bottom with the RectTransforms and positions is used to spawn the popup next to the Experiment Results Dialog (to the right or left depending on its position on the screen). The actual position on screen is defined by the Rect argument in the MultiOptionDialog constructor. It is defined as a normalized value with 0.5,0.5 being in the center of the screen, so you need to take the actual screen size and the UI scale into account when manually positioning the popup.

This is the resulting window:

nJGbv6m.png

Edited by DMagic
  • Like 5

Share this post


Link to post
Share on other sites

In addition, you may want to know that this popup dialog (with default settings) spawned by a click on KSPEvent (button on right-click context menu) has a mechanism that blocks everything in the same context menu as long as the dialog is up. No button click or even slide drag.

Share this post


Link to post
Share on other sites
On 10/5/2016 at 9:54 AM, DMagic said:

I'm wondering if anyone has looked into the PopupDialog system or made a mod using it.

I tried using it as the main UI toolkit for Astrogator, to avoid having to use a GUI to maintain binary files as I was led to believe would be necessary for a standard Unity UI. This thread was one of my top ten must-read references during development---thanks for taking the time!

I encountered a few quirks:

  • Can't move the window to be flush with the edge of the screen; there's a 1-2cm margin that I could not eliminate with any of the exposed properties
  • If two windows have the exact same title, then the first one closes when the second opens, which I worked around by padding one with spaces
  • The layout of the components is immutable once the window opens, so I had to close and re-open it to add/remove rows of a table on the fly
  • The UI elements have a tooltipText property, but I could not figure out how to make it display
  • You can't toggle by clicking the checkbox/option button's label, only the graphical icon

Otherwise it was surprisingly flexible and pleasant to work with. In my estimation, it would not take very much effort for SQUAD to turn it into a fully capable UI toolkit if they so chose.

 

Share this post


Link to post
Share on other sites
On 2/5/2017 at 0:14 AM, HebaruSan said:

I tried using it as the main UI toolkit for Astrogator, to avoid having to use a GUI to maintain binary files as I was led to believe would be necessary for a standard Unity UI. This thread was one of my top ten must-read references during development---thanks for taking the time!

I encountered a few quirks:

  • Can't move the window to be flush with the edge of the screen; there's a 1-2cm margin that I could not eliminate with any of the exposed properties
  • If two windows have the exact same title, then the first one closes when the second opens, which I worked around by padding one with spaces
  • The layout of the components is immutable once the window opens, so I had to close and re-open it to add/remove rows of a table on the fly
  • The UI elements have a tooltipText property, but I could not figure out how to make it display
  • You can't toggle by clicking the checkbox/option button's label, only the graphical icon

Otherwise it was surprisingly flexible and pleasant to work with. In my estimation, it would not take very much effort for SQUAD to turn it into a fully capable UI toolkit if they so chose.

 

Yep, I use these in KerbalHealth, because I haven't figured out all the intricacies of Unity UI development yet. In addition to what you've mentioned, I find several frustrating issues:

- Lack of a method to enforce a redraw of a window/GUI element. So, basically, you can't change anything in the window after it's been created. The only exception I know of are labels, whcih have the SetOptionText method.

- I couldn't find how to save a window's position after it's been closed.

Share this post


Link to post
Share on other sites
49 minutes ago, garwel said:

- Lack of a method to enforce a redraw of a window/GUI element. So, basically, you can't change anything in the window after it's been created. The only exception I know of are labels, whcih have the SetOptionText method.

Even better, for my purposes at least, was the version that takes a function parameter instead of a static string. That way I can just pass in an accessor that returns a value and let Unity worry about how and when to do the refreshes. DialogGUIButton and a few others also have this capability, I believe. Not sure whether that would work for you, but just in case:

https://kerbalspaceprogram.com/api/class_dialog_g_u_i_label.html

 DialogGUILabel (Func< string > getString, UIStyle style, bool expandW=false, bool expandH=false)
 DialogGUILabel (Func< string > getString, bool expandW=false, bool expandH=false)
 DialogGUILabel (Func< string > getString, float width, float height=0f)
49 minutes ago, garwel said:

- I couldn't find how to save a window's position after it's been closed.

I capture the position from PopupDialog.RTrf.position just before it closes and save it in my own custom settings object:

        private PopupDialog dialog { get; set; }
                Vector3 rt = dialog.RTrf.position;
                geometry = new Rect(
                    rt.x / Screen.width  + 0.5f,
                    rt.y / Screen.height + 0.5f,
                    mainWindowMinWidth,
                    mainWindowMinHeight
                );
                dialog.Dismiss();

I was not able to find any property anywhere that would tell me the width or height, but that turned out to be OK since my layout isn't user-resizable anyway.

  • Like 1

Share this post


Link to post
Share on other sites
11 hours ago, HebaruSan said:

Even better, for my purposes at least, was the version that takes a function parameter instead of a static string. That way I can just pass in an accessor that returns a value and let Unity worry about how and when to do the refreshes. DialogGUIButton and a few others also have this capability, I believe. Not sure whether that would work for you, but just in case:

https://kerbalspaceprogram.com/api/class_dialog_g_u_i_label.html


 DialogGUILabel (Func< string > getString, UIStyle style, bool expandW=false, bool expandH=false)
 DialogGUILabel (Func< string > getString, bool expandW=false, bool expandH=false)
 DialogGUILabel (Func< string > getString, float width, float height=0f)

I capture the position from PopupDialog.RTrf.position just before it closes and save it in my own custom settings object:


        private PopupDialog dialog { get; set; }

                Vector3 rt = dialog.RTrf.position;
                geometry = new Rect(
                    rt.x / Screen.width  + 0.5f,
                    rt.y / Screen.height + 0.5f,
                    mainWindowMinWidth,
                    mainWindowMinHeight
                );
                dialog.Dismiss();

I was not able to find any property anywhere that would tell me the width or height, but that turned out to be OK since my layout isn't user-resizable anyway.

Thanks, will try it!

Share this post


Link to post
Share on other sites

@garwel @HebaruSan You may be interested that it is possible to add new DialogGUI components to or delete the DialogGUI components from the dialog dynamically. But this solution is neither pretty nor compact.

Assumed that you have kept the reference to the DialogGUIVerticalLayout or DialogGUIHorizontalLayout prior to the dialog spawn,

//keep reference
rowLayout = new DialogGUIVerticalLayout(10, 10, 4, new RectOffset(5, 25, 5, 5), TextAnchor.UpperCenter, someContentRows); // someContentRows is DialogGUIBase[]

To add new DialogGUI components:

Stack<Transform> stack = new Stack<Transform>(); // some data on hierarchy of GUI components
stack.Push(rowLayout.uiItem.gameObject.transform); // need the reference point of the parent GUI component for position and size
List<DialogGUIBase> rows = rowLayout.children;
rows.Add(createContentRow()); // new row
rows.Last().Create(ref stack, HighLogic.UISkin); // required to force the GUI creation

To delete one row of DialogGUI components:

List<DialogGUIBase> rows = rowLayout.children;

for (int i = 1; i < rows.Count; i++)
{
	DialogGUIBase thisChild = rows.ElementAt(i);
	if (thisChild is DialogGUIHorizontalLayout) // avoid if DialogGUIContentSizer is detected
	{
		DialogGUILabel label = thisChild.children.ElementAt(0) as DialogGUILabel;
		if (label.OptionText.EndsWith("" + id)) // you can assign unique ID to DialogGUIVerticalLayout or DialogGUIHorizontalLayout via SetOptionText too!
		{
			rows.RemoveAt(i); // drop from the scrolllist rows
			thisChild.uiItem.gameObject.DestroyGameObjectImmediate(); // necessary to free memory up
			break;
		}
	}
}

It won't be like OnGUI() though. But it is neat that DialogGUI takes in the list of DialogGUIBase prior to spawning a dialog and then edit the content on fly without repeatedly drawing like OnGUI().

Edited by TaxiService
  • Like 2

Share this post


Link to post
Share on other sites

@TaxiService Thanks! I wonder if anyone knows if it's possible to add and dynamically change tooltips in elements of PopupDialogs (such as DialogGUILabel).

Share this post


Link to post
Share on other sites
4 hours ago, garwel said:

@TaxiService Thanks! I wonder if anyone knows if it's possible to add and dynamically change tooltips in elements of PopupDialogs (such as DialogGUILabel).

There are tooltips in the DialogGUI components? I haven't came across any function, parameter or argument mentioning such tooltips.

Share this post


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

There are tooltips in the DialogGUI components? I haven't came across any function, parameter or argument mentioning such tooltips.

Yes, there is a tooltipText field in DialogGUIBase class (and, accordingly, in all the DialogGUI... sub-classes). But I couldn't make it do anything.

  • Like 1

Share this post


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

Yes, there is a tooltipText field in DialogGUIBase class (and, accordingly, in all the DialogGUI... sub-classes). But I couldn't make it do anything.

Oh, I was looking at the wrong reference (outdated one with older DialogGUIBase class). It seems DialogGUIBase only checks if a given prefab (like DialogGUILabel) has a tooltip component available. If no such component is found, then it never tries to update the tookltip.

Share this post


Link to post
Share on other sites
On 2/6/2017 at 1:32 PM, HebaruSan said:

I was not able to find any property anywhere that would tell me the width or height, but that turned out to be OK since my layout isn't user-resizable anyway.

Looks like it's in PopupDialog.RTrf.sizeDelta.

(Guessed by extrapolating from some of DMagic's previous explanations and sample code, then confirmed with debug log statements.)

Share this post


Link to post
Share on other sites

There are some cases where sizeDelta won't report the actual width and height of the rect transform. That only works when the anchors are set to specific values (which might always be the case for Popup Dialogs).

If you want the actual size I think the RectTransform.rect will always give it to you; it's just a standard Rect: x, y, width, height. But to change the size of something I think you always need to use sizeDelta, since the rect is read-only. And if the component is part of a layout you'll need to get the Layout Element and change its preferred width and/or height.

Edited by DMagic
  • Like 1

Share this post


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

There are some cases where sizeDelta won't report the actual width and height of the rect transform. That only works when the anchors are set to specific values (which might always be the case for Popup Dialogs).

If you want the actual size I think the RectTransform.rect will always give it to you; it's just a standard Rect: x, y, width, height. But to change the size of something I think you always need to use sizeDelta, since the rect is read-only. And if the component is part of a layout you'll need to get the Layout Element and change its preferred width and/or height.

Yeah, RTrf.rect looks good, but half the time both it and sizeDelta tell me the height is 0. Seems to correlate with whether I have a DialogGUIScrollList (which somehow also causes it to ignore the starting position I specify and put the window at the middle of the screen instead). Does this stuff start to make sense once you grasp the big picture, or is Unity just weird and janky?

Is there anything in RectTransform that might control the logic that clamps a Popup Dialog on-screen when the user drags it? That's causing problems for small displays, and while making my window less enormous is the right answer, I want to explore all options and possibly eliminate that annoying margin between the window and the edge of the screen as well.

Share this post


Link to post
Share on other sites

KSP.UI.UIMasterController.ClampToScreen is the function that handles this, and there are options to use offsets so that you can partially drag off the screen.

But, I don't think there is any flexibility in the Popup Dialog system there. It seems to handle dragging through a DragPanel component, so I suppose you could try to remove that and implement your own version.

Unity uses interfaces to handle all of the UI interaction (see UnityEngine.EventSystems). One of them is IDragHandler, which is where you would put the clamping method.

 

And it's not so much that the Unity UI is janky, it's more the Popup Dialog system. It probably starts to break down when you try to change it too much.

  • Like 1

Share this post


Link to post
Share on other sites

Is there a known issue with PopupDialog and KSP x86? I've implemented it in DMP but the dialog throws a NRE if the user is using the x86 version of KSP.

Share this post


Link to post
Share on other sites
22 hours ago, RockyTV said:

Is there a known issue with PopupDialog and KSP x86? I've implemented it in DMP but the dialog throws a NRE if the user is using the x86 version of KSP.

Since it is used by the stock I doubt it.

Share this post


Link to post
Share on other sites

I've pretty much copied the above example including the ScrollList, but the resulting visible scroll area is less than a line in height. Horizontally it is auto-sized to fit the size of the parent dialog. I can still scroll through all the data (sorry, no screenshot) so the contents of the scroll area are correctly sized.

dialog.Add(new DialogGUIScrollList(Vector2.one, false, true,
+-----------------------+
|   Dialog title        |
+-----------------------+
|  Some text            |
|  [ Scroll area ||]    |
|        {Button}       |
+-----------------------+
If I change the code to the following:
dialog.Add(new DialogGUIScrollList(new Vector2(200,300), false, true,

then I get a window which has a properly-sized visible scroll area.

+-----------------------+
|   Dialog title        |
+-----------------------+
|  Some text            |
|  [             ||]    |
|  [             ||]    |
|  [ Scroll area ||]    |
|  [             ||]    |
|  [             ||]    |
|  [             ||]    |
|        {Button}       |
+-----------------------+

Specifying the visible size doesn't seem to be required in the example based on the screenshot, so my question is, how is the visible size of the scroll-area determined (not the contents of the scroll-area).

 

In general, is there more information on how all of this works as trial-and-error is incredibly slow what with having to recompile and restart KSP every time..

Thanks :)

Share this post


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

I've pretty much copied the above example including the ScrollList, but the resulting visible scroll area is less than a line in height. Horizontally it is auto-sized to fit the size of the parent dialog. I can still scroll through all the data (sorry, no screenshot) so the contents of the scroll area are correctly sized.

I haven't tried that example verbatim, but I remember seeing the same thing when I tried ScrollList. By default the dialog will try to auto-size itself to fit the contents, and the ScrollList will try to auto-size itself to fit its container. Unless you specify an absolute size somewhere, they compromise at that very small height you observed.

I think the example specifies an absolute size for the dialog here:

Quote

Rect pos = new Rect(0.5f, 0.5f, 300, 300);

...

return PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("", "Science Relay", UISkinManager.defaultSkin, pos, dialog.ToArray()), false, UISkinManager.defaultSkin);

 

 

 

  • Like 1

Share this post


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

I think the example specifies an absolute size for the dialog here:

Ah ok!  I thought that just specified the dialog position, not the size as well.  I'll try adding that in again, although specifying the size in the scroll-window worked as well.

Share this post


Link to post
Share on other sites

Edit: With the benefit of clarity from a good nights sleep, turning my derp from last night into more documentation to hopefully help others who might look for this information in future.

I was trying to inject my own GUI elements into a stock dialog box, so I needed to create them as GameObjects rather than spawn my own dialog box.

I found DialogGUIBase.Create(ref Stack<Transform> layout, UISkinDef skin) , but wondered why took a stack of transforms. This kind of threw me off because I wondered just how much stuff there needed to be in the stack. But a quick reread of the thread and I found the answer that I needed to get it working: it suffice to push the parent transform. That was good enough for me to have my code working.

On 2/10/2017 at 11:10 PM, TaxiService said:

To add new DialogGUI components:


Stack<Transform> stack = new Stack<Transform>(); // some data on hierarchy of GUI components
stack.Push(rowLayout.uiItem.gameObject.transform); // need the reference point of the parent GUI component for position and size
List<DialogGUIBase> rows = rowLayout.children;
rows.Add(createContentRow()); // new row
rows.Last().Create(ref stack, HighLogic.UISkin); // required to force the GUI creation

As for why it takes a stack, it just dawned on me earlier today -- GUI elements can have their own children, so when Create() is called, it will need to recursively do the same for its own children.
The code probably looks something like:

public override GameObject Create(ref Stack<Transform> layout, UISkinDef skin) {
  //...blah
  RectTransform t = ...; // my own transform
  layouts.Push(t);
  foreach (DialogGUIBase child in children)
    child.Create(layout, skin);
  layouts.Pop(t);
  //...blah
}

TaxiService was modifying a dialog that they created earlier, so it was possible to simply keep a reference to rowLayout and add/remove children from it.

I didn't have this luxury since my goal was to inject into the existing stock UI. But it's not a big deal -- as long as you can somehow get a handle on the parent transform that you want to inject into (DebugStuff is your friend) then you can simply take the GameObject that Create() spits out and SetParent():

Transform t = ... // find the parent transform to inject into
myGUIStuff.Create(t, HighLogic.UISkin).SetParent(t);

For more examples, check out Portrait Stats source code

Edited by cake>pie
  • Like 1

Share this post


Link to post
Share on other sites

Trying to make a DialogGUIButton that is grayed-out.

DialogGUIBase has attribute

Func<bool> OptionEnabledCondition = () => { return true; }

looks like what I want; some of DialogGUIButton's constructors even take EnabledCondition as a parameter.
But I'm having no luck with it.

Starting from working code that already has the button btn, adding:

btn.OptionEnabledCondition = () =>  { return false; };

Compiles fine, but now KSP won't even load it:

AssemblyLoader: Exception loading 'AirlockPlus': System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
  at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
  at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0
  at AssemblyLoader.LoadAssemblies () [0x00000] in <filename unknown>:0

Additional information about this exception:

 System.TypeLoadException: Could not load type 'AirlockPlus.AirlockPlus' from assembly 'AirlockPlus, Version=0.0.4.5696, Culture=neutral, PublicKeyToken=null'.

 System.TypeLoadException: Could not load type '<>c__DisplayClass6' from assembly 'AirlockPlus, Version=0.0.4.5696, Culture=neutral, PublicKeyToken=null'.


Also tried the following, no joy

btn.OptionEnabledCondition = () => false;
btn.OptionEnabledCondition = delegate{ return false; };

Using DialogGUIButton constructors that takes param EnabledCondition doesn't work either.

 

What am I doing wrong here?

Share this post


Link to post
Share on other sites
On 5/21/2017 at 10:01 PM, cake>pie said:

What am I doing wrong here?

You compile for .NET 4.5 ?

  • Like 1

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