-
Notifications
You must be signed in to change notification settings - Fork 329
CHANGE: ISX-2377: Rebinding sample improvements (Mouse sensitivity + Swap sticks) (Validation week) #2241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ekcoh
wants to merge
24
commits into
develop
Choose a base branch
from
rebinding-sample-extension
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,404
−406
Open
CHANGE: ISX-2377: Rebinding sample improvements (Mouse sensitivity + Swap sticks) (Validation week) #2241
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
bb38389
Added "swap controls" button to rebinding sample to allow swapping le…
ekcoh a66c819
Fixed a problem with previous swap bindings preventing multiple swaps…
ekcoh ba19e19
Improved RebindSaveLoad to allow reuse, added embryo of RebindBinding…
ekcoh c0720c1
Made load/save configurable on RebindSaveLoad component.
ekcoh 76649d6
Refactoring of editor code, adding look sensitivity slider, added par…
ekcoh 90f0b53
Simplified look sensitivity code
ekcoh 8178b94
Generalized RebindActionParameterUI to make it possible to select par…
ekcoh 0962b73
Removed hardcoded parameter names
ekcoh a579bfa
Fixed a problem which would cause mobile rebind sample build to run i…
ekcoh 07161d9
Added rough on screen control that do not depend on UI
ekcoh b854395
Additional work on on screen controls including UI visualisation
ekcoh 1bc2c53
Minor changes to on screen controls.
ekcoh 96b7c1e
Fixed an issue where drag gesture wouldn't trigger directly when thre…
ekcoh d6ce1a0
Code cleanup
ekcoh 54ccf57
Added inline doc
ekcoh 59778c6
More work on onscreen controls.
ekcoh df6a2b8
Removed files that will be routed via other PRs
ekcoh e0a8e1e
Removed undesirable object from scene
ekcoh ccfd328
Removed meta file
ekcoh 9276825
Undo changes not related to rebind sample extension.
ekcoh dd83145
Merge branch 'develop' into rebinding-sample-extension
ekcoh 0bd8359
Updated changelog
ekcoh d1e17bb
Merge branch 'rebinding-sample-extension' of github.com:Unity-Technol…
ekcoh 403e7d0
Slight improvements to README file
ekcoh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
|
||
namespace UnityEngine.InputSystem.Samples.RebindUI | ||
{ | ||
/// <summary> | ||
/// Extension methods to reduce code bloat of this example. | ||
/// </summary> | ||
public static class InputActionExtensions | ||
{ | ||
/// <summary> | ||
/// Attempts to find an action binding using its binding ID (GUID). | ||
/// </summary> | ||
/// <param name="action">The action instance, may be null.</param> | ||
/// <param name="bindingId">The binding ID (GUID) represented by a string.</param> | ||
/// <returns>Zero-based index of the binding or -1 if not found.</returns> | ||
public static int FindBindingById(this InputAction action, string bindingId) | ||
{ | ||
if (action == null || string.IsNullOrEmpty(bindingId)) | ||
return -1; | ||
var id = new Guid(bindingId); | ||
return action.bindings.IndexOf(x => x.id == id); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,31 @@ | ||
This sample demonstrates how to use the Input System APIs to set up a rebinding UI. The main file is [RebindActionUI](./RebindActionUI.cs) which, aside from serving as an example, contains a reusable `MonoBehaviour` component for composing rebinding UIs. The [RebindUIPrefab](./RebindUIPrefab.prefab) contains a ready-made prefab that can be used as a simple drop-in setup for rebinding an individual action. | ||
This sample demonstrates how to use the Input System APIs to set up a rebinding UI. The main file is | ||
[RebindActionUI](./RebindActionUI.cs) which, aside from serving as an example, contains a reusable `MonoBehaviour` | ||
component for composing rebinding UIs. The [RebindUIPrefab](./RebindUIPrefab.prefab) contains a ready-made prefab that | ||
can be used as a simple drop-in setup for rebinding an individual action. | ||
|
||
To demonstrate how to use images instead of textual display strings, take a look at [GamepadIconsExample](./GamepadIconsExample.cs). | ||
To demonstrate how to use images instead of textual display strings, take a look at | ||
[GamepadIconsExample](./GamepadIconsExample.cs). | ||
|
||
To demonstrate how to show dynamic texts based on input action bindings, see [ActionLabel](./ActionLabel.cs). | ||
To demonstrate how to show dynamic UI texts based on input action bindings, see [ActionLabel](./ActionLabel.cs). | ||
|
||
Finally, the [RebindSaveLoad](./RebindSaveLoad.cs) script demonstrates how to persist user rebinds in `PlayerPrefs` and how to restore them from there. | ||
[InputActionIndicator](./InputActionIndicator.cs) and [InputActionIndicator.prefab](./InputActionIndicator.prefab) | ||
shows how to make a simple UI indicator that shows whether an associated input action is enabled, disabled or | ||
performed. This behavior has been added to this sample to add observability of actions triggered within gameplay, | ||
menu and rebind contexts. | ||
|
||
The icons used in the sample are taken from [Free Prompts Pack v4.0](https://opengameart.org/content/free-keyboard-and-controllers-prompts-pack) created by, and made available to public domain by Nicolae Berbece. | ||
Icons are licensed under [Creative Commons CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
The [RebindSaveLoad](./RebindSaveLoad.cs) script demonstrates how to persist user rebinds in `PlayerPrefs` and how | ||
to restore them. | ||
|
||
In this sample, keyboard bindings for "Move" (default WASD) is rebound as a single composite. This means that | ||
indivudual parts will get assigned one after the other. Another way of doing this is to set it up as four individual | ||
button bindings and assign them individually as four partial bindings. | ||
|
||
In this sample it is possible to directly rebind gamepad sticks in the gamepad control scheme. In practice, you | ||
probably don't want to set up rebinding the sticks like this but rather have a "swap sticks" kind of toggle instead. | ||
In this sample we have both variants for demonstration purposes. See [RebindActionUI.SwapBinding](./RebindActionUI.cs) | ||
for a method that swaps two bindings of similar type. | ||
|
||
The icons used in the sample are taken from | ||
[Free Prompts Pack v4.0](https://opengameart.org/content/free-keyboard-and-controllers-prompts-pack) created by, | ||
and made available to public domain by Nicolae Berbece. | ||
Icons are licensed under [Creative Commons CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#if UNITY_EDITOR | ||
|
||
using System; | ||
using System.Linq; | ||
using UnityEditor; | ||
|
||
namespace UnityEngine.InputSystem.Samples.RebindUI | ||
{ | ||
/// <summary> | ||
/// Common binding UI helper to allow editor composition. | ||
/// </summary> | ||
internal class BindingUI | ||
{ | ||
private readonly SerializedProperty m_ActionProperty; | ||
private readonly SerializedProperty m_BindingIdProperty; | ||
private readonly SerializedProperty m_DisplayStringOptionsProperty; | ||
|
||
public BindingUI(SerializedObject serializedObject) | ||
: this(serializedObject.FindProperty("m_Action"), serializedObject.FindProperty("m_BindingId"), | ||
serializedObject.FindProperty("m_DisplayStringOptions")) | ||
{} | ||
|
||
public BindingUI(SerializedProperty actionProperty, SerializedProperty bindingIdProperty, | ||
SerializedProperty displayStringOptionsProperty = null) | ||
{ | ||
m_ActionProperty = actionProperty; | ||
m_BindingIdProperty = bindingIdProperty; | ||
m_DisplayStringOptionsProperty = displayStringOptionsProperty; | ||
|
||
Reset(); | ||
Refresh(); | ||
} | ||
|
||
private void Reset() | ||
{ | ||
bindingOptions = Array.Empty<GUIContent>(); | ||
bindingOptionValues = Array.Empty<string>(); | ||
selectedBindingIndex = -1; | ||
} | ||
|
||
public void Draw() | ||
{ | ||
// Binding section. | ||
EditorGUILayout.LabelField(m_BindingLabel); | ||
using (new EditorGUI.IndentLevelScope()) | ||
{ | ||
EditorGUILayout.PropertyField(m_ActionProperty); | ||
|
||
var newSelectedBinding = EditorGUILayout.Popup(m_BindingLabel, selectedBindingIndex, bindingOptions); | ||
if (newSelectedBinding != selectedBindingIndex) | ||
{ | ||
var bindingId = bindingOptionValues[newSelectedBinding]; | ||
m_BindingIdProperty.stringValue = bindingId; | ||
selectedBindingIndex = newSelectedBinding; | ||
} | ||
|
||
if (m_DisplayStringOptionsProperty != null) | ||
{ | ||
var optionsOld = (InputBinding.DisplayStringOptions)m_DisplayStringOptionsProperty.intValue; | ||
var optionsNew = (InputBinding.DisplayStringOptions)EditorGUILayout.EnumFlagsField(m_DisplayOptionsLabel, optionsOld); | ||
if (optionsOld != optionsNew) | ||
m_DisplayStringOptionsProperty.intValue = (int)optionsNew; | ||
} | ||
} | ||
} | ||
|
||
public bool Refresh() | ||
{ | ||
if (action == null) | ||
{ | ||
Reset(); | ||
return false; | ||
} | ||
|
||
var bindings = action.bindings; | ||
var bindingCount = bindings.Count; | ||
|
||
bindingOptions = new GUIContent[bindingCount]; | ||
bindingOptionValues = new string[bindingCount]; | ||
selectedBindingIndex = -1; | ||
|
||
var currentBindingId = m_BindingIdProperty.stringValue; | ||
for (var i = 0; i < bindingCount; ++i) | ||
{ | ||
var binding = bindings[i]; | ||
var bindingId = binding.id.ToString(); | ||
var haveBindingGroups = !string.IsNullOrEmpty(binding.groups); | ||
|
||
// If we don't have a binding groups (control schemes), show the device that if there are, for example, | ||
// there are two bindings with the display string "A", the user can see that one is for the keyboard | ||
// and the other for the gamepad. | ||
var displayOptions = | ||
InputBinding.DisplayStringOptions.DontUseShortDisplayNames | InputBinding.DisplayStringOptions.IgnoreBindingOverrides; | ||
if (!haveBindingGroups) | ||
displayOptions |= InputBinding.DisplayStringOptions.DontOmitDevice; | ||
|
||
// Create display string. | ||
var displayString = action.GetBindingDisplayString(i, displayOptions); | ||
|
||
// If binding is part of a composite, include the part name. | ||
if (binding.isPartOfComposite) | ||
displayString = $"{ObjectNames.NicifyVariableName(binding.name)}: {displayString}"; | ||
|
||
// Some composites use '/' as a separator. When used in popup, this will lead to to submenus. Prevent | ||
// by instead using a backlash. | ||
displayString = displayString.Replace('/', '\\'); | ||
|
||
// If the binding is part of control schemes, mention them. | ||
if (haveBindingGroups) | ||
{ | ||
var asset = action.actionMap?.asset; | ||
if (asset != null) | ||
{ | ||
var controlSchemes = string.Join(", ", | ||
binding.groups.Split(InputBinding.Separator) | ||
.Select(x => asset.controlSchemes.FirstOrDefault(c => c.bindingGroup == x).name)); | ||
|
||
displayString = $"{displayString} ({controlSchemes})"; | ||
} | ||
} | ||
|
||
bindingOptions[i] = new GUIContent(displayString); | ||
bindingOptionValues[i] = bindingId; | ||
|
||
if (currentBindingId == bindingId) | ||
selectedBindingIndex = i; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public string bindingId => m_BindingIdProperty.stringValue; | ||
public int bindingIndex => action.FindBindingById(m_BindingIdProperty.stringValue); | ||
|
||
public InputAction action => ((InputActionReference)m_ActionProperty.objectReferenceValue)?.action; | ||
|
||
private GUIContent[] bindingOptions { get; set; } | ||
private string[] bindingOptionValues { get; set; } | ||
private int selectedBindingIndex { get; set; } | ||
|
||
private readonly GUIContent m_BindingLabel = new GUIContent("Binding"); | ||
private readonly GUIContent m_DisplayOptionsLabel = new GUIContent("Display Options"); | ||
} | ||
} | ||
|
||
#endif // UNITY_EDITOR |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't constantly named with file and should be renamed.