I want to make a GUI list that I can expand and contract, like this: Nested List.
I can’t think of how to go about it, though. I have an array for the first level, and arrays for the sub-columns, and arrays for a sub-sub-column, but I can’t figure out how to accept a random number of each and expand and contract. Any suggestions?
The Editor GUI has a Foldout control; you’d have to replicate it in-game with a clickable icon+label.
Expandable GUI is easiest to accomplish with GUILayout:
[pseudocode]
GUILayout.BeginVertical();
foreach button {
button.open = GUIUtils.Foldout(button.name);
if ( button.open ) {
GUIUtils.BeginIndent(); // see below snippet
// display contents of the button
GUIUtils.EndIndent();
}
}
GUILayout.EndVertical();
I actually wrote a fully-clickable foldout control because I hate clicking the triangle:
(This is from my GUIUtils.cs file, comment out the (FontStyle)1 bit if you don’t want bold text)
/* These functions begin and end a horizontal indentation */
public static void BeginIndent(string style) { GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(style); }
public static void BeginIndent() { BeginIndent(""); }
public static void EndIndent() { GUILayout.EndVertical(); GUILayout.EndHorizontal(); }
/////////////////////////////////////////////////////////////////////////////
/*
* This section makes an EditorGUILayout.Foldout, except you can actually click anywhere on the word to open it
* instead of having to click on the teeny-tiny triangle.
*
* ... what the bananas, Unity
*/
private static GUIStyle openFoldoutStyle;
private static GUIStyle closedFoldoutStyle;
private static bool initted;
private static void Init() {
openFoldoutStyle = new GUIStyle( GUI.skin.FindStyle("Foldout") );
openFoldoutStyle.fontStyle = (FontStyle)1;
openFoldoutStyle.stretchHeight = true;
closedFoldoutStyle = new GUIStyle( openFoldoutStyle );
openFoldoutStyle.normal = openFoldoutStyle.onNormal;
openFoldoutStyle.active = openFoldoutStyle.onActive;
initted = true;
}
public static bool Foldout(bool open, string text ) { return Foldout(open, new GUIContent(text)); }
public static bool Foldout(bool open, GUIContent text ) {
if ( !initted ) Init();
if ( open ) {
if ( GUILayout.Button( text, openFoldoutStyle, GUILayout.Height(20) ) ) {
GUI.FocusControl ("");
GUI.changed = false; // force change-checking group to take notice
GUI.changed = true;
return false;
}
} else {
if ( GUILayout.Button( text, closedFoldoutStyle, GUILayout.Height(20) ) ) {
GUI.FocusControl ("");
GUI.changed = false; // force change-checking to take notice
GUI.changed = true;
return true;
}
}
return open;
}