Skip to content

Instantly share code, notes, and snippets.

@noio
Created September 6, 2022 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noio/5209550ebcb049da763f521027ec50f5 to your computer and use it in GitHub Desktop.
Save noio/5209550ebcb049da763f521027ec50f5 to your computer and use it in GitHub Desktop.
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Localization.SmartFormat.Core.Extensions;
using UnityEngine.Localization.SmartFormat.PersistentVariables;
namespace InputHints
{
internal struct InputActionVariable : IVariableValueChanged
{
public event Action<IVariable> ValueChanged;
readonly InputAction _action;
readonly InputHintsSpriteMapping _source;
public InputActionVariable(
InputAction action,
InputHintsSpriteMapping source)
{
_action = action;
_source = source;
ValueChanged = null;
}
public override string ToString()
{
return $"InputActionVariable({_action.name}, {_action.GetBindingDisplayString()})";
}
public object GetSourceValue(ISelectorInfo selector)
{
return _source.GetSprite(_action);
}
public void OnValueChanged()
{
Debug.Log($"F{Time.frameCount} Sending OnValueChanged to {this} Has Listeners: {ValueChanged != null}");
ValueChanged?.Invoke(this);
}
}
}
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Localization.SmartFormat.PersistentVariables;
using Utils;
namespace InputHints
{
public class InputActionVariableGroup : IVariableGroup
{
readonly InputActionAsset _actionsAsset;
readonly InputHintsSpriteMapping _spriteMapping;
readonly Dictionary<string, InputActionVariable> _cachedVariables;
public InputActionVariableGroup(InputActionAsset actionsAsset, InputHintsSpriteMapping spriteMapping)
{
_actionsAsset = actionsAsset;
_spriteMapping = spriteMapping;
_cachedVariables = new Dictionary<string, InputActionVariable>();
InputHints.UsedDeviceChanged += HandleUsedDeviceChanged;
}
#region INTERFACE IMPLEMENTATIONS
public bool TryGetValue(string key, out IVariable value)
{
Debug.Log(
$"INPUT HINT CACHE: {_cachedVariables.Select(p => $"{p.Key}: {p.Value.ToString()}").StringJoin()}");
if (_cachedVariables.TryGetValue(key, out var cachedVariable))
{
value = cachedVariable;
return true;
}
var action = _actionsAsset.FindAction(key);
if (action != null)
{
value = _cachedVariables[key] = new InputActionVariable(action, _spriteMapping);
return true;
}
/*
* Try to find action by replacing underscores or dashes with spaces:
* (In case the action name has spaces in it..)
* We first try the exact match above in case the action
* ACTUALLY has a dash or underscore in the name.
*/
key = key.Replace("-", " ");
key = key.Replace("_", " ");
action = _actionsAsset.FindAction(key);
if (action != null)
{
value = _cachedVariables[key] = new InputActionVariable(action, _spriteMapping);
return true;
}
value = default;
return false;
}
#endregion
void HandleUsedDeviceChanged()
{
foreach (var pair in _cachedVariables)
{
pair.Value.OnValueChanged();
}
}
}
}
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Localization.SmartFormat.Core.Extensions;
using UnityEngine.Localization.SmartFormat.PersistentVariables;
namespace InputHints
{
[Serializable]
public class InputHintsLocalizationSource : ISource
{
#region PUBLIC AND SERIALIZED FIELDS
[SerializeField] string _prefix = "input";
[SerializeField] InputHintsSpriteMapping _mapping;
[SerializeField] InputActionAsset _actionsAsset;
#endregion
InputActionVariableGroup _variableGroup;
#region INTERFACE IMPLEMENTATIONS
public bool TryEvaluateSelector(ISelectorInfo selectorInfo)
{
/*
* INITIALIZE THIS SOURCE, IF THAT FAILS, ALWAYS
* RETURN FALSE (i.e. we can't use this source)
* maybe it's bad that there's no warning for this?
*/
Init();
if (_variableGroup == null)
{
return false;
}
/*
* Do this the same way PersistentVariablesSource handles it:
* check if the CurrentValue is ALREADY the nested mapping, then drill down and
* get the value from the given text.
*/
if (selectorInfo.CurrentValue is InputActionVariableGroup group &&
group.TryGetValue(selectorInfo.SelectorText, out var variable))
{
var cache = selectorInfo.FormatDetails.FormatCache;
if (cache != null && variable is IVariableValueChanged valueChanged)
{
if (cache.VariableTriggers.Contains(valueChanged) == false)
{
cache.VariableTriggers.Add(valueChanged);
}
}
selectorInfo.Result = variable.GetSourceValue(selectorInfo);
return true;
}
/*
* If we're at the first part of the selector, see if the
* prefix matches the prefix we set here, then return the mapping as result.
*/
if (selectorInfo.SelectorOperator == "" &&
selectorInfo.SelectorText == _prefix &&
_variableGroup != null)
{
selectorInfo.Result = _variableGroup;
return true;
}
return false;
}
#endregion
void Init()
{
if (_variableGroup == null && _mapping != null && _actionsAsset != null)
{
_variableGroup = new InputActionVariableGroup(_actionsAsset, _mapping);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment