Implement the new input config.
This commit is contained in:
135
Assets/Cryville/Crtr/Config/UI/InputDialog.cs
Normal file
135
Assets/Cryville/Crtr/Config/UI/InputDialog.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using Cryville.Crtr.Ruleset;
|
||||
using Cryville.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.Crtr.Config.UI {
|
||||
internal class InputDialog : MonoBehaviour {
|
||||
static InputDialog _instance;
|
||||
[SerializeField] CanvasGroup m_group;
|
||||
[SerializeField] AnimationCurve m_fadeCurve;
|
||||
[SerializeField] TextMeshProUGUI m_msgText;
|
||||
[SerializeField] Transform m_deviceList;
|
||||
[SerializeField] GameObject m_deviceItemPrefab;
|
||||
float _fadeDuration;
|
||||
void Awake() {
|
||||
_instance = this;
|
||||
_fadeDuration = m_fadeCurve[m_fadeCurve.length - 1].time;
|
||||
_consumer = new SimpleInputConsumer(Game.InputManager);
|
||||
_d_HandleInputEvent = HandleInputEvent;
|
||||
}
|
||||
float _timer;
|
||||
bool _active;
|
||||
Action<InputSource?> _callback;
|
||||
|
||||
InputProxy _proxy;
|
||||
int _applicableEntries;
|
||||
int _targetDim;
|
||||
PhysicalDimension? _targetPDim;
|
||||
bool _targetNotNull;
|
||||
readonly Dictionary<InputSource, InputDialogEntry> _recvsrcs = new Dictionary<InputSource, InputDialogEntry>();
|
||||
void ShowInternal(Action<InputSource?> callback, string message, InputDefinition def, InputProxy proxy) {
|
||||
_active = true;
|
||||
_callback = callback;
|
||||
m_group.gameObject.SetActive(true);
|
||||
m_msgText.text = message;
|
||||
_proxy = proxy;
|
||||
|
||||
_targetDim = def.dim;
|
||||
if (def.pdim != null) _targetPDim = ParsePhysicalDimension(def.pdim);
|
||||
else _targetPDim = null;
|
||||
_targetNotNull = def.notnull;
|
||||
|
||||
foreach (Transform i in m_deviceList) Destroy(i.gameObject);
|
||||
_consumer.EnumerateEvents(ev => { });
|
||||
_recvsrcs.Clear();
|
||||
_applicableEntries = 1;
|
||||
AddSourceItem(null).transform.SetSiblingIndex(0);
|
||||
}
|
||||
public static void Show(Action<InputSource?> callback, string message, InputDefinition def, InputProxy proxy) {
|
||||
_instance.ShowInternal(callback, message, def, proxy);
|
||||
}
|
||||
static PhysicalDimension ParsePhysicalDimension(string str) {
|
||||
var comps = str.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
var result = new PhysicalDimension();
|
||||
foreach (var comp in comps) {
|
||||
int dim = 1;
|
||||
if (comp.Length > 1) dim = int.Parse(comp.Substring(1));
|
||||
switch (comp[0]) {
|
||||
case 'T': result.Time += dim; break;
|
||||
case 'L': result.Length += dim; break;
|
||||
case 'M': result.Mass += dim; break;
|
||||
case 'I': result.ElectricCurrent += dim; break;
|
||||
case '\x0398':
|
||||
case 'H': result.ThermodynamicTemperature += dim; break;
|
||||
case 'N': result.AmountOfSubstance += dim; break;
|
||||
case 'J': result.LuminousIntensity += dim; break;
|
||||
default: throw new ArgumentException(string.Format("Invalid dimension symbol {0}", comp[0]));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Update() {
|
||||
if (_active) {
|
||||
_consumer.EnumerateEvents(_d_HandleInputEvent);
|
||||
if (_timer >= _fadeDuration) return;
|
||||
_timer += Time.deltaTime;
|
||||
if (_timer > _fadeDuration) _timer = _fadeDuration;
|
||||
m_group.alpha = m_fadeCurve.Evaluate(_timer);
|
||||
}
|
||||
else {
|
||||
if (_timer <= 0) return;
|
||||
_timer -= Time.deltaTime;
|
||||
if (_timer < 0) {
|
||||
_timer = 0;
|
||||
m_group.gameObject.SetActive(false);
|
||||
}
|
||||
m_group.alpha = m_fadeCurve.Evaluate(_timer);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleInputConsumer _consumer;
|
||||
void OnEnable() { _consumer.Activate(); }
|
||||
void OnDisable() { _consumer.Deactivate(); }
|
||||
|
||||
Action<InputEvent> _d_HandleInputEvent;
|
||||
void HandleInputEvent(InputEvent ev) {
|
||||
InputSource src = ev.Identifier.Source;
|
||||
InputDialogEntry entry;
|
||||
if (!_recvsrcs.TryGetValue(src, out entry)) {
|
||||
_recvsrcs.Add(src, entry = AddSourceItem(src));
|
||||
if (_proxy.IsUsed(src)) {
|
||||
entry.Status |= InputDeviceStatus.Used;
|
||||
}
|
||||
if (src.Handler.Dimension < _targetDim) {
|
||||
entry.Status |= InputDeviceStatus.InsufficientDimension;
|
||||
}
|
||||
if (_targetPDim != null && src.Handler.ReferenceCue.PhysicalDimension != _targetPDim) {
|
||||
entry.Status |= InputDeviceStatus.IncompatiblePhysicalDimension;
|
||||
}
|
||||
if (!_targetNotNull && !src.Handler.IsNullable) {
|
||||
entry.Status |= InputDeviceStatus.IncompatibleNullable;
|
||||
}
|
||||
entry.transform.SetSiblingIndex(entry.Status == InputDeviceStatus.Default ? _applicableEntries++ : m_deviceList.childCount - 1);
|
||||
}
|
||||
entry.OnInputEvent(ev);
|
||||
}
|
||||
InputDialogEntry AddSourceItem(InputSource? src) {
|
||||
var entry = Instantiate(m_deviceItemPrefab, m_deviceList, false).GetComponent<InputDialogEntry>();
|
||||
entry.Init(src);
|
||||
entry.Clicked += () => OnItemSelected(src);
|
||||
return entry;
|
||||
}
|
||||
void OnItemSelected(InputSource? src) {
|
||||
if (!_active) return;
|
||||
_active = false;
|
||||
_callback(src);
|
||||
}
|
||||
public void Close() {
|
||||
_active = false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user