using System; using System.Collections.Generic; using UnityEngine; namespace AlicizaX.UI { [DisallowMultipleComponent] [AddComponentMenu("UX/UX Controller")] public sealed class UXController : MonoBehaviour { [Serializable] public class ControllerData { [SerializeField] private string _name = "Controller"; [SerializeField] private int _length = 2; [SerializeField] private string _description = ""; [NonSerialized] private int _currentIndex = 0; public string Name { get => _name; set => _name = value; } public int Length { get => _length; set => _length = Mathf.Max(1, value); } public string Description { get => _description; set => _description = value; } public int CurrentIndex { get => _currentIndex; set => _currentIndex = value; } } [SerializeField] private List _controllers = new List(); [SerializeField] private List _recorders = new List(); private Dictionary _controllerIndexMap; private bool _initialized = false; #region Public API public IReadOnlyList Controllers => _controllers; public int ControllerCount => _controllers.Count; public ControllerHandle GetController(string name) { EnsureInitialized(); if (_controllerIndexMap.TryGetValue(name, out int index)) { return new ControllerHandle(this, index); } return null; } public ControllerHandle GetControllerAt(int index) { if (index < 0 || index >= _controllers.Count) return null; return new ControllerHandle(this, index); } public void SetControllerIndex(string name, int selectedIndex) { EnsureInitialized(); if (_controllerIndexMap.TryGetValue(name, out int controllerIndex)) { SetControllerIndexInternal(controllerIndex, selectedIndex); } } public int GetControllerIndex(string name) { EnsureInitialized(); if (_controllerIndexMap.TryGetValue(name, out int controllerIndex)) { return _controllers[controllerIndex].CurrentIndex; } return 0; } #endregion #region Internal API internal IReadOnlyList Recorders => _recorders; internal void SetControllerIndexInternal(int controllerIndex, int selectedIndex) { if (controllerIndex < 0 || controllerIndex >= _controllers.Count) return; var cd = _controllers[controllerIndex]; selectedIndex = Mathf.Clamp(selectedIndex, 0, cd.Length - 1); if (cd.CurrentIndex == selectedIndex) return; cd.CurrentIndex = selectedIndex; NotifyRecorders(cd.Name, selectedIndex); } internal bool HasRecorder(UXControllerStateRecorder recorder) { if (recorder == null) return false; return _recorders.Exists(r => r != null && r.ID == recorder.ID); } internal void RegisterRecorder(UXControllerStateRecorder recorder) { if (recorder != null && !HasRecorder(recorder)) { _recorders.Add(recorder); } } internal void UnregisterRecorder(UXControllerStateRecorder recorder) { if (recorder != null) { _recorders.RemoveAll(r => r == null || r.ID == recorder.ID); } } #endregion #region Unity Lifecycle private void Awake() { InitializeRuntime(); } private void OnValidate() { BuildControllerIndexMap(); } #endregion #region Private Methods private void EnsureInitialized() { if (!_initialized) { BuildControllerIndexMap(); } } private void BuildControllerIndexMap() { if (_controllerIndexMap == null) { _controllerIndexMap = new Dictionary(); } else { _controllerIndexMap.Clear(); } for (int i = 0; i < _controllers.Count; i++) { var controller = _controllers[i]; if (!string.IsNullOrEmpty(controller.Name)) { _controllerIndexMap[controller.Name] = i; } } _initialized = true; } private void InitializeRuntime() { EnsureInitialized(); for (int i = 0; i < _recorders.Count; i++) { if (_recorders[i] != null) { _recorders[i].Initialize(); } } for (int i = 0; i < _controllers.Count; i++) { SetControllerIndexInternal(i, 0); } } private void NotifyRecorders(string controllerName, int selectedIndex) { for (int i = 0; i < _recorders.Count; i++) { if (_recorders[i] != null) { _recorders[i].OnControllerIndexChanged(controllerName, selectedIndex); } } } #endregion #region Controller Handle public class ControllerHandle { private readonly UXController _owner; private readonly int _controllerIndex; public ControllerHandle(UXController owner, int controllerIndex) { _owner = owner; _controllerIndex = controllerIndex; } public bool IsValid => _owner != null && _controllerIndex >= 0 && _controllerIndex < _owner._controllers.Count; public int SelectedIndex { get { if (!IsValid) return 0; return _owner._controllers[_controllerIndex].CurrentIndex; } set { if (IsValid) { _owner.SetControllerIndexInternal(_controllerIndex, value); } } } public int Length { get { if (!IsValid) return 0; return _owner._controllers[_controllerIndex].Length; } } public string Name { get { if (!IsValid) return null; return _owner._controllers[_controllerIndex].Name; } } public string Description { get { if (!IsValid) return null; return _owner._controllers[_controllerIndex].Description; } } } #endregion } }