Last active
October 20, 2021 14:47
-
-
Save krummja/a869e5d5cfbe65fa8f971870c1e13421 to your computer and use it in GitHub Desktop.
This file contains 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; | |
using System.Reflection; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
using UnityEngine.Events; | |
using UnityEngine.EventSystems; | |
/// <summary> | |
/// A base class to add to objects that contain Button objects. | |
/// For each UI screen that has interactive buttons, add an implementation | |
/// to the root GameObject with children bearing Button components. | |
/// | |
/// In the implementation, make methods with the pattern | |
/// <c>ContainingObjectName_ButtonName<c>. These will automatically be | |
/// registered in in the component's button registry as a delegate that | |
/// will map the buttons to their methods based on their names in the | |
/// object hierarchy. | |
/// </summary> | |
/// <example> | |
/// | |
/// Unity object hierarchy: | |
/// | |
/// MenuRoot [has MenuRootScreen component] | |
/// ├── Menu | |
/// | ├── GroupA | |
/// | | ├── ButtonA | |
/// | | ├── ButtonB | |
/// | | └── ButtonC | |
/// | |
/// <code> | |
/// public class MenuRootScreen : BaseScreen | |
/// { | |
/// public void GroupA_ButtonA() | |
/// { | |
/// // Code to execute when Button A is pressed. | |
/// } | |
/// } | |
/// </code> | |
/// </example> | |
public abstract class BaseScreen : MonoBehaviour | |
{ | |
public List<GameObject> ButtonGroupObjects = new List<GameObject>(); | |
private List<ButtonGroup> _buttonGroups = new List<ButtonGroup>(); | |
private Dictionary<string, Dictionary<string, Delegate>> _cache = | |
new Dictionary<string, Dictionary<string, Delegate>>(); | |
private void RegisterGroup(GameObject element) | |
{ | |
ButtonGroup _group = new ButtonGroup(element); | |
_buttonGroups.Add(_group); | |
foreach ( ButtonGroup group in _buttonGroups ) | |
{ | |
foreach ( KeyValuePair<string, Button> button in group.Buttons ) | |
{ | |
button.Value.onClick.AddListener( | |
ConfigureButtonDelegate<UnityAction>(group.GroupName, button.Key, DoNothing) | |
); | |
} | |
} | |
} | |
private T ConfigureButtonDelegate<T>(string groupName, string methodRoot, T Default) where T : class | |
{ | |
Dictionary<string, Delegate> lookup; | |
if ( !_cache.TryGetValue(groupName, out lookup) ) | |
{ | |
_cache[groupName] = lookup = new Dictionary<string, Delegate>(); | |
} | |
Delegate returnValue; | |
if ( !lookup.TryGetValue(methodRoot, out returnValue) ) | |
{ | |
MethodInfo mtd = GetType().GetMethod( | |
name: groupName + "_" + methodRoot, | |
bindingAttr: BindingFlags.Instance | | |
BindingFlags.Public | | |
BindingFlags.NonPublic | | |
BindingFlags.InvokeMethod | |
); | |
if ( mtd != null ) | |
{ | |
returnValue = Delegate.CreateDelegate(typeof(T), this, mtd); | |
} | |
else | |
{ | |
returnValue = Default as Delegate; | |
} | |
} | |
return returnValue as T; | |
} | |
private void DoNothing() | |
{ | |
throw new NotImplementedException("Button has no matching function."); | |
} | |
private void Start() | |
{ | |
foreach ( GameObject groupObj in ButtonGroupObjects ) | |
{ | |
RegisterGroup(groupObj); | |
} | |
} | |
} | |
public struct ButtonGroup | |
{ | |
public string GroupName; | |
public GameObject GroupObject; | |
public Dictionary<string, Button> Buttons; | |
public ButtonGroup(GameObject groupObject) | |
{ | |
GroupName = groupObject.name; | |
GroupObject = groupObject; | |
Buttons = new Dictionary<string, Button>(); | |
MapButtons(groupObject.transform); | |
} | |
private void MapButtons(Transform groupTransform) | |
{ | |
foreach ( Transform child in groupTransform ) | |
{ | |
if ( child.GetComponent<Button>() ) | |
{ | |
Buttons.Add(child.gameObject.name, child.GetComponent<Button>()); | |
if ( child.childCount != 0 ) MapButtons(child); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment