274 lines
7.4 KiB
C#
274 lines
7.4 KiB
C#
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<ControllerData> _controllers = new List<ControllerData>();
|
|
[SerializeField] private List<UXControllerStateRecorder> _recorders = new List<UXControllerStateRecorder>();
|
|
|
|
private Dictionary<string, int> _controllerIndexMap;
|
|
private bool _initialized = false;
|
|
|
|
#region Public API
|
|
|
|
public IReadOnlyList<ControllerData> 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<UXControllerStateRecorder> 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<string, int>();
|
|
}
|
|
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
|
|
}
|
|
}
|