Scriptname _test_ListMenuScript extends ObjectReference  
{Basic example script for UI Extensions list menu. Scripts + .esp of UI Extensions need to be installed.
If the .esp is merged into a masterfile, UIExtensions.psc GetMenu() function needs to be adjusted.}

;importing
Import UIExtensions
Import debug

Actor Property PlayerREF Auto

Event OnActivate(ObjectReference akActionRef)
	;The player interacts with the Object Reference to which this script is attached and we call the function to display the menu.
	If akActionRef == PlayerREF
		ShowMenu()
	EndIf
	
EndEvent

Function ShowMenu()
	;We are creating the menu.
	UIListMenu listmenu = GetMenu("UIListMenu") as UIListMenu
	
	;We are creating an array that contains all the strings.
	string[] myList = new string[19]
	
	;Simple entry.
	myList[0] = "Option 0"
	
	;Entries can be parents and children, a children can also be a parent.
	;If a parent entry gets selected by the player, they automatically open up a new list menu containing all their children.
	;Single parent with a single child.
	myList[1] = "Option 1"
	myList[2] = "Option 2, child to 1"
	
	;Single parent, multiple children.
	myList[3] = "Option 3"
	myList[4] = "Option 4, child to 3"
	myList[5] = "Option 5, child to 3"
	
	;Single parent containing a child that has also a child.
	myList[6] = "Option 6"
	myList[7] = "Option 7, child to 6"
	myList[8] = "Option 8, child to 7"
	
	;Multiple parents with a single child that will be added in a loop (see below).
	myList[9] = "Option 9"
	myList[10] = "Option 10"
	myList[11] = "Option 11, child to 9"
	myList[12] = "Option 12, child to 10"
	
	;Multiple parents with multiple children added in a loop.
	myList[13] = "Option 13"
	myList[14] = "Option 14"
	myList[15] = "Option 15, child to 13"
	myList[16] = "Option 16, child to 13"
	myList[17] = "Option 17, child to 14"
	myList[18] = "Option 18, child to 14"
	
	;For extensive and/or repetetive lists it's easier to use a while statement to add all the entries.
	;Lists that contain only a few entries should be added one by one, especially if the parents have children irregularly attached.
	;AddEntryItem() is the function to add a string to the list. The first parameter is the string grabbed from the array.
	;The second parameter is the integer entryParent which should be -1 if this specific entry should have no parent.
	;The third parameter (integer entryCallback) is used for remembering the parent.
	;The last parameter is the bool entryHasChildren.
	listmenu.AddEntryItem(myList[0], -1, -1, false)
	
	;We want to create a parent in Option 1 here, so we need to set entryHasChildren to true.
	;The second line will create Option 2, child to 1, so entryParent needs to be 1 here (1 = the index of the parent in the array).
	listmenu.AddEntryItem(myList[1], -1, -1, true)
	listmenu.AddEntryItem(myList[2], 1, -1, false)
	
	;We create two children to Option 3.
	listmenu.AddEntryItem(myList[3], -1, -1, true)
	listmenu.AddEntryItem(myList[4], 3, -1, false)
	listmenu.AddEntryItem(myList[5], 3, -1, false)
	
	;We create a parent that has a child which also has its own child.
	listmenu.AddEntryItem(myList[6], -1, -1, true)
	listmenu.AddEntryItem(myList[7], 6, -1, true)
	listmenu.AddEntryItem(myList[8], 7, -1, false)
	
	;Variables are needed for this specific case, other cases might need less / need more.
	;iLength helps us to count up, iParent keeps track of the parents and iIteration is needed for the last while (see below).
	;iLength is starting at 9 because this spcific list will have its first loop on array index 9.
	Int iLength = 9
	Int iParent = 0
	Int iIteration = 0
	
	;We add the strings from our array above to the list. We need to state from which index we start and where to end.
	While iLength >= 9 && iLength < 13
		;Adding parents in if and children in else in this example
		If iLength < 11
			listmenu.AddEntryItem(myList[iLength], -1, -1, true)
		Else
			iParent = iLength - 2
			;iParent is just used to add the correct parent to its child(ren). How iParent is calculated is up to your entry order in the array. 
			;The bool entryHasChildren needs to be set to false if the child itself holds no more child(ren).
			;Every parent only gets one child in this case but of course one parent can hold up to 128 children.
			listmenu.AddEntryItem(myList[iLength], iParent, -1, false)
		EndIf
		;At the end of each loop we count iLength up.
		iLength += 1
	EndWhile
	;This could also have been done in two loops, one counting up from 9 to 10 and the second one from 11 to 12 for this example. Haven't checked which way it would be faster.
	
	;This while statement adds multiple parents that have multiple children.
	While iLength >= 13 && iLength < myList.Length
		If iLength < 15
			listmenu.AddEntryItem(myList[iLength], -1, -1, true)
		Else
			iParent = 13 + iIteration
			listmenu.AddEntryItem(myList[iLength], iParent, -1, false)
			iLength += 1
			listmenu.AddEntryItem(myList[iLength], iParent, -1, false)
			iIteration += 1
		EndIf
		iLength += 1
	EndWhile
	
	;After everything got injected into the menu, we can finally open it.
	int iListMenu = listmenu.OpenMenu()
	
	;The following works similar to regular message boxes:
	int iListButton = listmenu.GetResultInt()
	
	If iListButton >= 0
		;GetResultString() returns the exact name of the entry that has been selected
		Notification(listMenu.GetResultString())
	EndIf

EndFunction