135 lines
4.4 KiB
C#
135 lines
4.4 KiB
C#
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();
|
|
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[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;
|
|
if (!_recvsrcs.TryGetValue(src, out InputDialogEntry 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;
|
|
}
|
|
}
|
|
}
|