Instantly share code, notes, and snippets.
Created
September 1, 2021 22:22
-
Star
1
(1)
You must be signed in to star a gist -
Fork
1
(1)
You must be signed in to fork a gist
-
Save nothke/b3020e4373c995711a96e0258e6bf990 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using Nothke.SimpleMenu; | |
using TMPro; | |
public class ExampleMenu : Menu | |
{ | |
int intTest = 10; | |
protected override void Create() | |
{ | |
// A simple option with confirm | |
root.Add(new Option("Confirm Example") | |
{ | |
OnConfirmed = () => Debug.Log("Confirmed!") | |
}); | |
// An option that changes when left or right is pressed | |
root.Add(new Option() // We don't need a label since we'll override it in OnRevealed | |
{ | |
OnValueChanged = (o, i) => intTest += i, | |
OnRevealed = (o) => o.label = "Int: " + intTest, | |
}); | |
// Adds a submenu with 2 options | |
root.Add(new Option("Submenu") | |
{ | |
options = new List<Option>() | |
{ | |
new Option("Suboption 1") { OnConfirmed = () => Debug.Log("Foo!") }, | |
new Option("Suboption 2") { OnConfirmed = () => Debug.Log("Bar!") }, | |
}, | |
}); | |
root.Add(new Option("Quit") | |
{ | |
OnConfirmed = () => Application.Quit() | |
}); | |
} | |
protected override void PlaceTextOnCreation(TMP_Text text, int index) | |
{ | |
text.rectTransform.anchoredPosition = Vector2.down * index * 50; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
using System; | |
using TMPro; | |
namespace Nothke.SimpleMenu | |
{ | |
public enum OptionType { Confirm, Submenu, Suboptions }; | |
public class Option | |
{ | |
public string label; | |
public List<Option> options; | |
public Option parent; | |
public int index; | |
public Action OnConfirmed; | |
public Action OnSelected; | |
public Action OnDeselected; | |
public Action<Option> OnRevealed; | |
public Action<Option, int> OnValueChanged; | |
public int Count => options == null ? 0 : options.Count; | |
public bool IsSubmenu => options != null; | |
public Option() { } | |
public Option(string title) | |
{ | |
this.label = title; | |
} | |
public void Add(Option option) | |
{ | |
if (options == null) | |
options = new List<Option>(); | |
option.parent = this; | |
options.Add(option); | |
} | |
public void SelectChild(int i) | |
{ | |
index = i % Count; | |
if (index < 0) | |
index = Count - 1; | |
options[index].Select(); | |
} | |
public void Deselect() | |
{ | |
if (OnDeselected != null) | |
OnDeselected(); | |
} | |
public void ChangeValue(int by) | |
{ | |
if (OnValueChanged != null) | |
OnValueChanged(this, by); | |
} | |
public void Select() | |
{ | |
if (OnDeselected != null) | |
OnDeselected(); | |
} | |
public void Reveal() | |
{ | |
if (OnRevealed != null) | |
OnRevealed(this); | |
} | |
public void ConfirmChild() | |
{ | |
if (options[index].OnConfirmed != null) | |
options[index].OnConfirmed(); | |
} | |
} | |
public abstract class Menu : MonoBehaviour | |
{ | |
public RectTransform rootTransform; | |
public TMP_Text textPrefab; | |
public Option root; | |
Option current; | |
[NonSerialized] public List<TMP_Text> texts; | |
private void Start() | |
{ | |
root = new Option("") { options = new List<Option>() }; | |
current = root; | |
Create(); | |
GenerateUI(); | |
Repaint(); | |
} | |
protected virtual void GenerateUI() | |
{ | |
texts = new List<TMP_Text>(); | |
for (int i = 0; i < 10; i++) | |
{ | |
var tGO = Instantiate(textPrefab.gameObject); | |
tGO.transform.SetParent(rootTransform); | |
var t = tGO.GetComponent<TMP_Text>(); | |
PlaceTextOnCreation(t, i); | |
texts.Add(t); | |
tGO.SetActive(false); | |
} | |
} | |
protected virtual void PlaceTextOnCreation(TMP_Text text, int index) | |
{ | |
var pos = text.rectTransform.anchoredPosition; | |
pos.y = -50 * index; | |
text.rectTransform.anchoredPosition = pos; | |
} | |
protected abstract void Create(); | |
public void ReturnToRoot() | |
{ | |
current = root; | |
Repaint(); | |
} | |
public void Show() | |
{ | |
rootTransform.gameObject.SetActive(true); | |
} | |
public void Hide() | |
{ | |
rootTransform.gameObject.SetActive(false); | |
} | |
public virtual void Repaint() | |
{ | |
for (int i = texts.Count - 1; i >= 0; i--) | |
{ | |
OnTextDeselected(texts[i]); | |
texts[i].gameObject.SetActive(false); | |
} | |
int len = current.Count; | |
for (int i = 0; i < len; i++) | |
{ | |
texts[i].gameObject.SetActive(true); | |
current.options[i].Reveal(); | |
texts[i].text = current.options[i].label; | |
if (i == current.index) | |
OnTextSelected(texts[i]); | |
} | |
} | |
private void Update() | |
{ | |
GetInput( | |
out bool down, out bool up, | |
out bool left, out bool right, | |
out bool confirm, out bool cancel); | |
if (down) | |
current.SelectChild(current.index + 1); | |
else if (up) | |
current.SelectChild(current.index - 1); | |
var suboption = current.options[current.index]; | |
if (left || right) | |
{ | |
suboption.ChangeValue(right ? 1 : -1); | |
} | |
if (confirm) | |
{ | |
current.ConfirmChild(); | |
if (suboption.options != null) | |
current = suboption; | |
Repaint(); | |
} | |
if (cancel) | |
{ | |
if (current.parent != null) | |
current = current.parent; | |
} | |
if (down || up || left || right || confirm || cancel) | |
Repaint(); | |
} | |
protected virtual void GetInput( | |
out bool down, out bool up, | |
out bool left, out bool right, | |
out bool confirm, out bool cancel) | |
{ | |
left = Input.GetKeyDown(KeyCode.A); | |
right = Input.GetKeyDown(KeyCode.D); | |
down = Input.GetKeyDown(KeyCode.S); | |
up = Input.GetKeyDown(KeyCode.W); | |
confirm = Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter); | |
cancel = Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Backspace); | |
} | |
public virtual void OnTextSelected(TMP_Text text) | |
{ | |
text.transform.localScale = Vector3.one * 1.2f; | |
text.color = Color.yellow; | |
} | |
public virtual void OnTextDeselected(TMP_Text text) | |
{ | |
text.transform.localScale = Vector3.one; | |
text.color = Color.white; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment