Implement the new input config.

This commit is contained in:
2023-12-01 16:52:21 +08:00
parent 4d05d0d135
commit 5c38245e23
16 changed files with 2400 additions and 165 deletions

View File

@@ -4,155 +4,51 @@ using Cryville.Input;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Cryville.Crtr.Config.UI {
public class InputConfigPanel : MonoBehaviour {
[SerializeField]
ConfigPanelMaster m_configScene;
[SerializeField]
GameObject m_inputDialog;
[SerializeField]
Transform m_deviceList;
[SerializeField]
GameObject m_prefabListItem;
internal class InputConfigPanel : MonoBehaviour {
[SerializeField]
Transform m_entryList;
[SerializeField]
GameObject m_prefabInputConfigEntry;
SimpleInputConsumer _consumer;
public InputProxy proxy;
PdtRuleset _ruleset;
InputProxy _proxy;
readonly Dictionary<Identifier, InputConfigPanelEntry> _entries = new Dictionary<Identifier, InputConfigPanelEntry>();
int _applicableEntries;
Identifier _sel;
int _targetDim;
PhysicalDimension? _targetPDim;
bool _targetNotNull;
public void OpenDialog(Identifier entry) {
_sel = entry;
var def = m_configScene.ruleset.Root.inputs[_sel];
_targetDim = def.dim;
if (def.pdim != null) _targetPDim = ParsePhysicalDimension(def.pdim);
else _targetPDim = null;
_targetNotNull = def.notnull;
m_inputDialog.SetActive(true);
foreach (Transform i in m_deviceList) Destroy(i.gameObject);
_consumer.EnumerateEvents(ev => { });
_recvsrcs.Clear();
_applicableEntries = 1;
AddSourceItem(null);
}
public void Load(PdtRuleset ruleset, RulesetConfig rulesetConfig) {
_ruleset = ruleset;
_proxy = new InputProxy(ruleset, null, new Vector2(Screen.width, Screen.height));
_proxy.LoadFrom(rulesetConfig.inputs);
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;
}
public void CloseDialog() {
m_inputDialog.SetActive(false);
}
public void CloseDialog(InputSource? src) {
proxy.Set(new InputProxyEntry {
Target = _sel,
Source = src,
});
CloseDialog();
}
public void OnConfigEnable() {
foreach (Transform i in m_entryList) Destroy(i.gameObject);
_entries.Clear();
_consumer = new SimpleInputConsumer(Game.InputManager);
_consumer.Activate();
foreach (var i in m_configScene.ruleset.Root.inputs) {
var e = Instantiate(m_prefabInputConfigEntry, m_entryList.transform).GetComponent<InputConfigPanelEntry>();
foreach (var i in ruleset.inputs) {
var e = Instantiate(m_prefabInputConfigEntry, m_entryList.transform, false).GetComponent<InputConfigPanelEntry>();
_entries.Add(i.Key, e);
e.SetKey(this, i.Key);
OnProxyChanged(this, proxy[i.Key]);
OnProxyChanged(this, _proxy[i.Key]);
}
proxy.ProxyChanged += OnProxyChanged;
_proxy.ProxyChanged += OnProxyChanged;
}
public void OnConfigDisable() {
_consumer.Deactivate();
Identifier _selectedEntry;
public void OpenDialog(Identifier entry) {
_selectedEntry = entry;
InputDialog.Show(OnDialogClosed, "Please input and select a device", _ruleset.inputs[entry], _proxy);
}
public void OnDialogClosed(InputSource? src) {
_proxy.Set(new InputProxyEntry {
Target = _selectedEntry,
Source = src,
});
}
void OnProxyChanged(object sender, ProxyChangedEventArgs e) {
_entries[e.Name].OnProxyChanged(e);
}
void Start() {
_d_HandleInputEvent = HandleInputEvent;
}
readonly List<InputSource?> _recvsrcs = new List<InputSource?>();
void Update() {
if (m_inputDialog.activeSelf) {
_consumer.EnumerateEvents(_d_HandleInputEvent);
}
}
Action<InputEvent> _d_HandleInputEvent;
void HandleInputEvent(InputEvent ev) {
AddSourceItem(ev.Identifier.Source);
}
void AddSourceItem(InputSource? src) {
if (_recvsrcs.Contains(src)) return;
_recvsrcs.Add(src);
var obj = Instantiate(m_prefabListItem, m_deviceList);
var text = obj.transform.Find("Text").GetComponent<Text>();
text.text = src == null ? "(None)" : src.Value.Handler.GetTypeName(src.Value.Type);
var btn = obj.GetComponent<Button>();
if (src != null) {
var tsrc = src.Value;
bool flag = false;
if (proxy.IsUsed(tsrc)) {
text.text += " <size=9>(Used)</size>";
}
else if (tsrc.Handler.Dimension < _targetDim) {
text.text += " <size=9>(Not Applicable)</size>";
}
else if (_targetPDim != null && tsrc.Handler.ReferenceCue.PhysicalDimension != _targetPDim) {
text.text += " <size=9>(Not Applicable)</size>";
}
else if (!_targetNotNull && !tsrc.Handler.IsNullable) {
text.text += " <size=9>(Not Applicable)</size>";
}
else flag = true;
btn.interactable = flag;
obj.transform.SetSiblingIndex(flag ? _applicableEntries++ : m_deviceList.childCount - 1);
}
else {
obj.transform.SetSiblingIndex(0);
}
btn.onClick.AddListener(() => {
CloseDialog(src);
});
public void SaveTo(Dictionary<string, RulesetConfig.InputEntry> inputs) {
_proxy.SaveTo(inputs);
}
}
}