Skip to content

Instantly share code, notes, and snippets.

@phosphoer
Last active June 10, 2024 23:20
Show Gist options
  • Save phosphoer/87f87fe5f99c4331bd15d4b762e1a572 to your computer and use it in GitHub Desktop.
Save phosphoer/87f87fe5f99c4331bd15d4b762e1a572 to your computer and use it in GitHub Desktop.
Rewired Glyph Mappings
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "new-controller-icon-mapping", menuName = "Controller Icon Mapping")]
public class ControllerIconMapDefinition : ScriptableObject
{
[SerializeField]
private InputIconMapDefinition gamepadMap = null;
[SerializeField]
private InputIconMapDefinition keyboardMap = null;
[SerializeField]
private InputIconMapDefinition mouseMap = null;
[SerializeField]
private ControllerMapPair[] controllerMaps = null;
[System.Serializable]
private class ControllerMapPair
{
public string Name = string.Empty;
public string ControllerGuid = string.Empty;
public InputIconMapDefinition IconMap = null;
}
private Dictionary<string, InputIconMapDefinition> _controllerIdMap;
public static void GetElementMapsForAction(int actionId, Rewired.Player player, List<Rewired.ActionElementMap> elementMaps)
{
Rewired.Controller lastController = player.controllers.GetLastActiveController();
foreach (var elementMap in player.controllers.maps.ElementMapsWithAction(lastController, actionId, skipDisabledMaps: false))
{
elementMaps.Add(elementMap);
}
}
public InputIconMapDefinition GetMapForHardware(Rewired.Controller controller)
{
EnsureControllerMaps();
string hardwareTypeGuid = controller.hardwareTypeGuid.ToString();
if (_controllerIdMap.TryGetValue(hardwareTypeGuid, out InputIconMapDefinition hardwareMap))
{
return hardwareMap;
}
if (controller.type == Rewired.ControllerType.Joystick)
return gamepadMap;
else if (controller == Rewired.ReInput.controllers.Keyboard)
return keyboardMap;
else if (controller == Rewired.ReInput.controllers.Mouse)
return mouseMap;
return null;
}
// Find icons for an input action, based on whatever the current detected controller type is
public bool GetIconsForAction(int actionId, Rewired.Player player, List<InputIcon> inputIcons)
{
// Find out the last controller used
EnsureControllerMaps();
Rewired.Controller lastController = player.controllers.GetLastActiveController();
if (lastController == null)
lastController = GetPlatformDefaultController();
// Store previous icon count so we can determine whether we successfully found more
int prevCount = inputIcons.Count;
var iconMap = GetMapForHardware(lastController);
if (iconMap == mouseMap || iconMap == keyboardMap)
{
FillInputIcons(inputIcons, mouseMap, player, Rewired.ReInput.controllers.Mouse, actionId);
FillInputIcons(inputIcons, keyboardMap, player, Rewired.ReInput.controllers.Keyboard, actionId);
}
else
{
FillInputIcons(inputIcons, iconMap, player, lastController, actionId);
}
return inputIcons.Count > prevCount;
}
// Find an icon for a specific input mapping, which is already associated with a controller
public InputIcon GetIconForInput(Rewired.ActionElementMap elementMap)
{
// This is an unassigned action, and therefore can't have any icon
if (elementMap.controllerMap == null)
return null;
// Get info about the input action
EnsureControllerMaps();
Rewired.Controller controller = elementMap.controllerMap.controller;
// Get the icon map for this hardware
InputIconMapDefinition iconMap = GetMapForHardware(controller);
if (iconMap != null)
{
return iconMap.GetInputIcon(elementMap, controller);
}
return null;
}
private Rewired.Controller GetPlatformDefaultController()
{
// If there's any connected gamepad, use that
if (Rewired.ReInput.controllers.Joysticks.Count > 0)
{
return Rewired.ReInput.controllers.Joysticks[0];
}
// Default to the keyboard (this does not affect console)
return Rewired.ReInput.controllers.Keyboard;
}
private void EnsureControllerMaps()
{
if (_controllerIdMap == null)
{
_controllerIdMap = new Dictionary<string, InputIconMapDefinition>();
for (int i = 0; i < controllerMaps.Length; ++i)
{
ControllerMapPair pair = controllerMaps[i];
_controllerIdMap[pair.ControllerGuid.ToString()] = pair.IconMap;
}
}
}
// Fill input icons using the player and a controller
private void FillInputIcons(List<InputIcon> inputIcons, InputIconMapDefinition iconMap, Rewired.Player player, Rewired.Controller controller, int actionId)
{
Rewired.InputAction action = Rewired.ReInput.mapping.GetAction(actionId);
foreach (var elementMap in player.controllers.maps.ElementMapsWithAction(controller, actionId, skipDisabledMaps: false))
{
var inputIcon = iconMap.GetInputIcon(elementMap, controller);
if (inputIcon != null)
inputIcons.Add(inputIcon);
else
Debug.LogWarning($"Failed to get input icon for action {action.name} with input id {elementMap.elementIdentifierId}");
}
}
// Fill input icons using just a controller map and an action, with no controller object
// This uses the default rewired gamepad template which most gamepads implement
// NOTE: Using this will bypass any player-specific mappings!
private void FillInputIcons(List<InputIcon> inputIcons, ControllerMapPair controllerIconMap, int actionId)
{
// Debug.Log($"Getting input icon for action {actionId} and controllerMap {controllerMap.Name}");
// Apply layout rule sets based on controller type, kind of a hack?
// This allows Switch to properly show the correct mapped buttons while no controller is connected
int layoutId = 0;
var ruleSets = Rewired.ReInput.players.GetPlayer(0).controllers.maps.layoutManager.ruleSets;
foreach (var ruleSet in ruleSets)
{
foreach (var rule in ruleSet)
{
// Debug.Log($"Comparing rule with hardware id {rule.controllerSetSelector.hardwareTypeGuid.ToString()} to {controllerMap.ControllerGuid}");
if (rule.controllerSetSelector.hardwareTypeGuid.ToString() == controllerIconMap.ControllerGuid)
{
layoutId = rule.layoutId;
break;
}
}
}
// Now get the mapping for this controller template and layout
Rewired.InputAction action = Rewired.ReInput.mapping.GetAction(actionId);
Rewired.ControllerIdentifier controllerIdentifier = new Rewired.ControllerIdentifier();
controllerIdentifier.hardwareTypeGuid = new System.Guid(controllerIconMap.ControllerGuid);
controllerIdentifier.controllerType = Rewired.ControllerType.Joystick;
foreach (var mapCategory in Rewired.ReInput.mapping.MapCategories)
{
if (controllerIconMap.IconMap.UseTemplateIds)
{
var mapInstance = Rewired.ReInput.mapping.GetControllerTemplateMapInstance(Rewired.GamepadTemplate.typeGuid, mapCategory.id, layoutId);
if (mapInstance != null)
{
foreach (var actionElement in mapInstance.ElementMaps)
{
if (actionElement.actionId == actionId)
{
var inputIcon = controllerIconMap.IconMap.GetInputIcon(actionElement.elementIdentifierId, actionElement.actionId);
if (inputIcon != null)
{
inputIcons.Add(inputIcon);
}
}
}
}
}
else
{
var controllerMap = Rewired.ReInput.mapping.GetControllerMapInstance(controllerIdentifier, mapCategory.id, layoutId);
if (controllerMap != null)
{
foreach (var actionElement in controllerMap.AllMaps)
{
if (actionElement.actionId == actionId)
{
var inputIcon = controllerIconMap.IconMap.GetInputIcon(actionElement.elementIdentifierId, actionElement.actionId);
if (inputIcon != null)
{
inputIcons.Add(inputIcon);
}
}
}
}
}
}
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
[System.Serializable]
public class InputIcon
{
public string Comment;
public int InputId;
public Sprite IconSprite;
public Color IconColor = Color.white;
public string IconLabel;
public Sprite IconLabelSprite;
public Color IconLabelColor = Color.white;
public Vector3 IconLabelOffset;
public bool FlipX;
public bool DisableMapping;
}
[CreateAssetMenu(fileName = "new-input-icon-mapping", menuName = "Input Icon Mapping")]
public class InputIconMapDefinition : ScriptableObject
{
public bool UseTemplateIds = true;
public InputIcon TiltIcon => _tiltIcon;
[SerializeField, UnityEngine.Serialization.FormerlySerializedAs("inputIcons")]
private InputIcon[] _inputIcons = null;
[SerializeField]
private ActionIconOverride[] _actionIconOverrides = null;
[SerializeField]
private InputIcon _tiltIcon = null;
#pragma warning disable CS0414
[SerializeField]
private Rewired.Data.Mapping.HardwareJoystickMap _hardwareMap = null;
#pragma warning restore CS0414
private static List<Rewired.ControllerTemplateElementTarget> _elementTargets = new List<Rewired.ControllerTemplateElementTarget>();
[System.Serializable]
private struct ActionIconOverride
{
[Rewired.ActionIdProperty(typeof(RewiredConsts.Action))]
public int ActionId;
public InputIcon InputIcon;
}
// Get the id of the corresponding input element from the controller's template definition, if it exists
public static int GetTemplatedInputId(Rewired.ActionElementMap elementMap)
{
Rewired.Controller controller = elementMap.controllerMap.controller;
int inputId = elementMap.elementIdentifierId;
if (controller.templateCount > 0)
{
_elementTargets.Clear();
controller.Templates[0].GetElementTargets(elementMap, _elementTargets);
if (_elementTargets.Count > 0)
{
inputId = _elementTargets[0].element.id;
}
}
return inputId;
}
public InputIcon GetInputIcon(Rewired.ActionElementMap elementMap, Rewired.Controller controller)
{
int inputId = UseTemplateIds ? GetTemplatedInputId(elementMap) : elementMap.elementIdentifierId;
return GetInputIcon(inputId, elementMap.actionId);
}
public InputIcon GetInputIcon(int inputId, int actionId)
{
if (_actionIconOverrides != null)
{
for (int i = 0; i < _actionIconOverrides.Length; ++i)
{
if (_actionIconOverrides[i].ActionId == actionId)
{
return _actionIconOverrides[i].InputIcon;
}
}
}
return GetInputIcon(inputId);
}
public InputIcon GetInputIcon(int inputId)
{
foreach (InputIcon inputIcon in _inputIcons)
{
if (inputIcon.InputId == inputId)
{
return inputIcon;
}
}
return null;
}
#if UNITY_EDITOR
[ContextMenu("Load From Hardware Map")]
private void LoadFromHardwareMap()
{
var oldInputIcons = _inputIcons;
UnityEditor.Undo.RecordObject(this, "Load from hardware map");
int index = 0;
_inputIcons = new InputIcon[_hardwareMap.elementIdentifierCount];
foreach (var elementIdentifier in _hardwareMap.ElementIdentifiers)
{
var icon = new InputIcon();
icon.InputId = elementIdentifier.id;
icon.Comment = elementIdentifier.name;
icon.IconColor = Color.white;
icon.IconLabelColor = Color.white;
_inputIcons[index] = icon;
++index;
}
for (int i = 0; i < oldInputIcons.Length && i < _inputIcons.Length; ++i)
{
if (oldInputIcons[i].InputId == _inputIcons[i].InputId)
{
_inputIcons[i].IconSprite = oldInputIcons[i].IconSprite;
_inputIcons[i].IconLabel = oldInputIcons[i].IconLabel;
_inputIcons[i].IconLabelSprite = oldInputIcons[i].IconLabelSprite;
}
}
UnityEditor.EditorUtility.SetDirty(this);
}
#endif
[ContextMenu("Generate Keyboard Map")]
private void GenerateKeyboardMap()
{
Rewired.Keyboard keyboard = Rewired.ReInput.controllers.Keyboard;
InputIcon firstIcon = _inputIcons[0];
_inputIcons = new InputIcon[keyboard.ElementIdentifiers.Count];
for (int i = 0; i < keyboard.ElementIdentifiers.Count; ++i)
{
var keyElement = keyboard.ElementIdentifiers[i];
InputIcon keyIcon = new InputIcon();
keyIcon.IconSprite = firstIcon.IconSprite;
keyIcon.IconColor = firstIcon.IconColor;
keyIcon.IconLabelColor = firstIcon.IconLabelColor;
keyIcon.Comment = keyElement.name.ToString();
keyIcon.IconLabel = keyElement.name;
keyIcon.InputId = keyElement.id;
_inputIcons[i] = keyIcon;
}
}
[ContextMenu("Apply Item 0 Icon Color")]
private void DebugAdjustColors()
{
for (int i = 1; i < _inputIcons.Length; ++i)
{
_inputIcons[i].IconColor = _inputIcons[0].IconColor;
}
}
[ContextMenu("Apply Item 0 Icon")]
private void DebugAdjustIcons()
{
for (int i = 1; i < _inputIcons.Length; ++i)
{
_inputIcons[i].IconSprite = _inputIcons[0].IconSprite;
}
}
}
@BlooBaba
Copy link

Hey thank you for making this. Really made my life a lot easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment