Skip to content

Instantly share code, notes, and snippets.

@phosphoer
Last active June 10, 2024 23:20
Show Gist options
  • Select an option

  • Save phosphoer/87f87fe5f99c4331bd15d4b762e1a572 to your computer and use it in GitHub Desktop.

Select an option

Save phosphoer/87f87fe5f99c4331bd15d4b762e1a572 to your computer and use it in GitHub Desktop.
Rewired Glyph Mappings
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "new-controller-icon-mapping", menuName = "Controller Icon Mapping", order = (int)MenuItemOrder.Misc)]
public class ControllerIconMapDefinition : ScriptableObject
{
[SerializeField]
private InputIconMapDefinition gamepadMap = null;
[SerializeField]
private InputIconMapDefinition keyboardMap = null;
[SerializeField]
private InputIconMapDefinition mouseMap = null;
private List<Rewired.ControllerTemplateElementTarget> _elementTargets = new List<Rewired.ControllerTemplateElementTarget>();
public bool GetIconsForAction(int actionId, Rewired.Player player, List<InputIcon> inputIcons)
{
Rewired.Controller lastController = player.controllers.GetLastActiveController();
if (lastController.type == Rewired.ControllerType.Joystick)
{
FillInputIcons(inputIcons, gamepadMap, player, lastController, actionId);
}
else
{
FillInputIcons(inputIcons, keyboardMap, player, Rewired.ReInput.controllers.Keyboard, actionId);
FillInputIcons(inputIcons, mouseMap, player, Rewired.ReInput.controllers.Mouse, actionId);
}
return inputIcons.Count > 0;
}
private void FillInputIcons(List<InputIcon> inputIcons, InputIconMapDefinition iconMap, Rewired.Player player, Rewired.Controller controller, int actionId)
{
foreach (var elementMap in player.controllers.maps.ElementMapsWithAction(controller, actionId, skipDisabledMaps: false))
{
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;
}
var inputIcon = iconMap.GetInputIcon(inputId);
inputIcons.Add(inputIcon);
}
}
}
using UnityEngine;
using UnityEngine.UI;
[System.Serializable]
public struct InputIcon
{
// A comment to identify this input icon in inspector
public string Comment;
// The input ID that this icon represents, maps to Rewired's 'elementIdentifierId'
public int InputId;
// The sprite for this icon
public Sprite IconSprite;
// An optional label to display on the sprite
public string IconLabel;
// Offset from icon center for the label
public Vector3 IconLabelOffset;
// Whether to flip the icon horizontally
public bool FlipX;
}
[CreateAssetMenu(fileName = "new-input-icon-mapping", menuName = "Input Icon Mapping", order = (int)MenuItemOrder.Misc)]
public class InputIconMapDefinition : ScriptableObject
{
[SerializeField]
private InputIcon[] inputIcons = null;
public InputIcon GetInputIcon(int inputId)
{
foreach (InputIcon inputIcon in inputIcons)
{
if (inputIcon.InputId == inputId)
{
return inputIcon;
}
}
return default(InputIcon);
}
}
@phosphoer
Copy link
Copy Markdown
Author

phosphoer commented Apr 12, 2019

This requires the Unity Asset: Rewired.

I use these assets to define glyphs for the different input devices my game supports. It works by storing a mapping of hardware input ID -> icon. You ask for an icon for a given Rewired action, I then find all the inputs mapped for it and return the set of icons. This approach means that even when controls are remapped by the user, or you change the mappings during development, the correct icons will be returned. If the input device has a template, I use the template input IDs rather than the hardware IDs, so my gamepad icon mapping applies to all gamepads that Rewired supports generically. You can see the hardware/template IDs by expanding the Debug menu in the inspector for the Rewired Input Manager at runtime.

I didn't include the code to display the icons, as that is pretty specific to my game's architecture, but pretty much you just need to display the graphic the returned InputIcon structure contains in some fashion. You could easily modify this to use some other type of visual for the icon instead of a Sprite, or even just use the name of the input and display the string.

@chaosmonger
Copy link
Copy Markdown

This requires the Unity Asset: Rewired.

I use these assets to define glyphs for the different input devices my game supports. It works by storing a mapping of hardware input ID -> icon. You ask for an icon for a given Rewired action, I then find all the inputs mapped for it and return the set of icons. This approach means that even when controls are remapped by the user, or you change the mappings during development, the correct icons will be returned. If the input device has a template, I use the template input IDs rather than the hardware IDs, so my gamepad icon mapping applies to all gamepads that Rewired supports generically. You can see the hardware/template IDs by expanding the Debug menu in the inspector for the Rewired Input Manager at runtime.

I didn't include the code to display the icons, as that is pretty specific to my game's architecture, but pretty much you just need to display the graphic the returned InputIcon structure contains in some fashion. You could easily modify this to use some other type of visual for the icon instead of a Sprite, or even just use the name of the input and display the string.

Currently, I use just a generic set of icons for all types of gamepads, as you can see by the single InputIconMapDefinition entry for gamepad. It would be pretty easy to make overrides for specific gamepads by storing a mapping of rewired controller/template IDs to InputIconMapDefinitions and falling back to the generic template when necessary.

Hi, I'm approaching this and I've a couple of questions...
1: How can I create the icon set for Keyboard? What's the elementID of a keyboard key?
2: How can I display only positive/negative icons? For instance, if I want to show the right direction button (which could be "D" icon on keyboard, and "stick-to-the-right" icon on gamepad? Considering axis like Horizontal/Vertical relies on positive/negative values.
3: I'm not sure I understand how can you link different gamepads... Let's say I want to create 5 icons sets: Xbox360, XboxOne, SonyDualShock4, SteamController, UnknownController(Default), how can I change your scripts to fit those?

Thanks a lot and sorry if some of the questions might sound noob...

@phosphoer
Copy link
Copy Markdown
Author

Hi @chaosmonger, sorry for the late reply I didn't see this notification till now. I've also updated the gist with my latest code (minus some project specific stuff), which may answer some of your questions.

1: How can I create the icon set for Keyboard? What's the elementID of a keyboard key?

Check out the helper function I added to the InputIconMapDefinition, basically I iterated over the Rewired keyboard controller elements and created all the entries programmatically. I then had to manually go in and fill in the icons and edit names where appropriate.

2: How can I display only positive/negative icons? For instance, if I want to show the right direction button (which could be "D" icon on keyboard, and "stick-to-the-right" icon on gamepad? Considering axis like Horizontal/Vertical relies on positive/negative values.

I think this may be easier in the new version of the code, but I think I didn't have a need for that case so it's explicitly exposed. You could probably add extra override methods for GetIconForInput that takes a direction and then use that to filter the results?

3: I'm not sure I understand how can you link different gamepads... Let's say I want to create 5 icons sets: Xbox360, XboxOne, SonyDualShock4, SteamController, UnknownController(Default), how can I change your scripts to fit those?

This is something I added in the newest version, as I mentioned above I just had a single generic gamepad entry before. Now I have a map of hardware IDs to controller maps. You can find out the GUID of the controller by digging through rewired's data files.

@Zilk
Copy link
Copy Markdown

Zilk commented Mar 13, 2023

I've just gotten into this script trying to add glyphs to the remapping we are adding. Keyboard is working great but all controller maps seem to get the wrong sprite assigned. I created the bases from the data available in Rewired to be able to assign the different sprites to Xbox/PS/Switch controllers etc but it seems like it gets the ids mixed up. If I assign a Triangle it gets the Circle for instance. Could it be that I have the hardware ids and the script uses the elementalIds? Anyway to translate these?

@phosphoer
Copy link
Copy Markdown
Author

I've just gotten into this script trying to add glyphs to the remapping we are adding. Keyboard is working great but all controller maps seem to get the wrong sprite assigned. I created the bases from the data available in Rewired to be able to assign the different sprites to Xbox/PS/Switch controllers etc but it seems like it gets the ids mixed up. If I assign a Triangle it gets the Circle for instance. Could it be that I have the hardware ids and the script uses the elementalIds? Anyway to translate these?

Check out the new version I just posted, I ran into a similar problem eventually and ended up having the input icon assets define whether they are using template IDs or hardware IDs. The old script always used template IDs if available, with the new one you can uncheck that box to always use hardware IDs.

@Zilk
Copy link
Copy Markdown

Zilk commented Mar 14, 2023

Thanks! I was kind of suspecting something like that was the issue, got it working by just using the hardware id but then keyboard started acting out instead. This will solve it, thanks again!

@spireggs
Copy link
Copy Markdown

Hey, thanks for the script! I was wondering how you handled Unknown controllers with these scriptable objects. Any tips?

@phosphoer
Copy link
Copy Markdown
Author

Hey, thanks for the script! I was wondering how you handled Unknown controllers with these scriptable objects. Any tips?

Currently, I do not handle them at all which hasn't yet been a problem (afaik) with a shipped game. I did just updated the gist with a small refactor that should make adding this easier though.

I'm guessing you are talking about the case where the controller is completely unknown to Rewired and how to show icons for it? I think I'd approach that by making an InputIconMapDefinition asset with generic icons for up to N buttons (e.g., 'Button1', 'Button2'), and then adding a special case in ControllerIconMapDefinition.cs in GetMapForHardware() which returns that asset when the Rewired.Controller is of an unknown type.

Hope that helps!

@Zilk
Copy link
Copy Markdown

Zilk commented Jun 8, 2023

Bumped into another issue with this on iOS. Seems like on iOS it returns odd sprites but on Android it works as intended. Could it be because of the iOS MFI? Got any ideas?

@BlooBaba
Copy link
Copy Markdown

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