Skip to content

Instantly share code, notes, and snippets.

@dylanwolf
Created April 11, 2023 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dylanwolf/603980854435b22c50c6c3833c87099e to your computer and use it in GitHub Desktop.
Save dylanwolf/603980854435b22c50c6c3833c87099e to your computer and use it in GitHub Desktop.
Unity UI Submenu
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Submenu : MonoBehaviour {
[System.NonSerialized]
public SubmenuItem SelectedItem;
Selectable firstAvailable;
public SubmenuItem[] Items;
GameObject[] objects;
public Selectable Previous;
public Selectable Next;
public Sprite InactiveFrame;
public Sprite ClearFrame;
EventSystem evt;
public enum ButtonDirection
{
Horizontal,
Vertical
}
public ButtonDirection Direction;
private void Start()
{
InitChildren();
}
bool hasInit = false;
public void InitChildren()
{
if (!hasInit)
{
for (int i = 0; i < Items.Length; i++)
{
InitChild(Items[i]);
}
RewireControls();
hasInit = true;
}
}
void InitChild(SubmenuItem child)
{
Debug.Log("Setting " + child.name + " to " + this.name);
child.Container = this;
child.Selectable.SetNavigationType(Navigation.Mode.Explicit);
}
void SetNextAndPrevious(Selectable sel, Selectable previous, Selectable nxt)
{
if (Direction == ButtonDirection.Horizontal)
sel.SetLeftAndRight(previous, nxt);
else
sel.SetUpAndDown(previous, nxt);
}
void SetPrevious(Selectable sel, Selectable prev)
{
if (Direction == ButtonDirection.Horizontal)
sel.SetLeft(prev);
else
sel.SetUp(prev);
}
void SetNext(Selectable sel, Selectable nxt)
{
if (Direction == ButtonDirection.Horizontal)
sel.SetRight(nxt);
else
sel.SetDown(nxt);
}
public void RewireControls()
{
firstAvailable = null;
int? lastIndex = null;
for (int i = 0; i < Items.Length; i++)
{
// Set enter/exit navigation
if (Direction == ButtonDirection.Horizontal)
Items[i].Selectable.SetUpAndDown(Previous, Next);
else
Items[i].Selectable.SetLeftAndRight(Previous, Next);
// Interactable: set this in order
if (Items[i].Selectable.IsInteractable())
{
// Is first enabled item in the list
if (!lastIndex.HasValue)
{
// Clear all the navigation
SetNextAndPrevious(Items[i].Selectable, null, null);
firstAvailable = Items[i].Selectable;
}
else
{
// Set the previous item to the last enabled item
SetNextAndPrevious(Items[i].Selectable, Items[lastIndex.Value].Selectable, null);
// Reverse the wiring
SetNext(Items[lastIndex.Value].Selectable, Items[i].Selectable);
}
lastIndex = i;
}
// Not interactable: remove this from the order
else
{
// Clear all the navigation
SetNextAndPrevious(Items[i].Selectable, null, null);
}
}
RewireNextAndPrevious();
}
public void SelectItem(SubmenuItem selected)
{
SelectedItem = selected;
RewireNextAndPrevious();
}
public void ForceSelection(SubmenuItem selected)
{
if (evt == null)
evt = EventSystem.current;
evt.SetSelectedGameObject(null);
evt.SetSelectedGameObject(selected.gameObject);
RewireNextAndPrevious();
}
Selectable SelectedOrFirst
{
get
{
return (SelectedItem != null && SelectedItem.Selectable != null) ? SelectedItem.Selectable : firstAvailable;
}
}
public void RewireNextAndPrevious()
{
if (Direction == ButtonDirection.Horizontal)
{
if (Previous != null)
Previous.SetDown(SelectedOrFirst);
if (Next != null)
Next.SetUp(SelectedOrFirst);
}
else
{
if (Previous != null)
Previous.SetRight(SelectedOrFirst);
if (Next != null)
Next.SetLeft(SelectedOrFirst);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment