Skip to content

Commit fc6adeb

Browse files
authored
NEW: edit actions and bindings properties (ISX-1374, ISX-1126) (#1691)
* Fix: focus & focusOut events for inputFields * Change: only rename actions & composites * Fix: fixed NullReference if TreeViewItem out of screen * Fix: rename wrong action or actionMap * added edit on return and improved with use itemsChosen event * fixed renaming with F2 * rename composites properly * fixed rename canceled on click away * avoid NullReferenceError at MapListView if item out of screen * fixed renaming actionMap -> excluding own name * fixed action maps not renamed bug + removed redundant line * add context menu with rename functionality * added: functionality to delete bindings * added: functionality for deleting actions * added: deleting action maps * fixed errors on delete bindings * fixed errors for deleting actions * fixed action not focused after adding a new one * fixed delete actionMaps & unsubscribe handlers correctly * shortcut selector method * fixed selection not updated in ActionsTreeView * some refactoring * added delete with DEL key functionality * formatting fix * formatting * fixed small no binding name issue * added add buttons for interactions and processors * WIP added context menu for add interactions+processor buttons * added context menu and add interactions & add processors functionality * fixed context menu overload for adding processors & interactions * fixed adding processors & interactions to bindings * fixed menu not updated bug * don't show interactions for bindings that are part of a composite * added swapping and deleting interactions & processors * added saving of parameters for processors and interactions * fixed saving for fields with default toggle * fixed lose focus directly after change issue * fixed showing up of default text and open in player settings * fixed content for default values not resizing bug * fixed greyed out swap and delete buttons for interactions & processors * fixed initalStateToggle ignoring clicks * fixed exception on Action Type changed to not Button * refactoring * fix for editor theme and enabling on icons on interactions & processors * smallNameRefactoring * ISX-1489 fix context menu does not open on left click on windows * ISX-1489 fix context menu does not open on left click on windows for mac * refactoring for merge
1 parent 4747c41 commit fc6adeb

8 files changed

Lines changed: 298 additions & 36 deletions

File tree

Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/ParameterListView.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ void OnValueChanged(ref EditableParameterValue parameter, object result, int i)
263263
{
264264
parameter.value.value = PrimitiveValue.FromObject(result).ConvertTo(parameter.value.type);
265265
m_Parameters[i] = parameter;
266+
}
267+
268+
void OnEditEnd()
269+
{
266270
onChange?.Invoke();
267271
}
268272

@@ -277,41 +281,47 @@ void OnValueChanged(ref EditableParameterValue parameter, object result, int i)
277281
var intValue = parameter.value.value.ToInt32();
278282
var field = new DropdownField(label.text, parameter.enumNames.Select(x => x.text).ToList(), intValue);
279283
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
284+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
280285
root.Add(field);
281286
}
282287
else if (parameter.value.type == TypeCode.Int64 || parameter.value.type == TypeCode.UInt64)
283288
{
284289
var longValue = parameter.value.value.ToInt64();
285290
var field = new LongField(label.text) { value = longValue };
286291
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
292+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
287293
root.Add(field);
288294
}
289295
else if (parameter.value.type.IsInt())
290296
{
291297
var intValue = parameter.value.value.ToInt32();
292298
var field = new IntegerField(label.text) { value = intValue };
293299
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
300+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
294301
root.Add(field);
295302
}
296303
else if (parameter.value.type == TypeCode.Single)
297304
{
298305
var floatValue = parameter.value.value.ToSingle();
299306
var field = new FloatField(label.text) { value = floatValue };
300307
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
308+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
301309
root.Add(field);
302310
}
303311
else if (parameter.value.type == TypeCode.Double)
304312
{
305313
var floatValue = parameter.value.value.ToDouble();
306314
var field = new DoubleField(label.text) { value = floatValue };
307315
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
316+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
308317
root.Add(field);
309318
}
310319
else if (parameter.value.type == TypeCode.Boolean)
311320
{
312321
var boolValue = parameter.value.value.ToBoolean();
313322
var field = new Toggle(label.text) { value = boolValue };
314323
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
324+
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
315325
root.Add(field);
316326
}
317327
}

Packages/com.unity.inputsystem/InputSystem/Editor/InputParameterEditor.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,13 @@ public void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
232232

233233
m_FloatField = new FloatField(m_ValueLabel.text) { value = value };
234234
m_FloatField.RegisterValueChangedCallback(ChangeSettingValue);
235+
m_FloatField.RegisterCallback<BlurEvent>(_ => OnEditEnd(onChangedCallback));
235236
m_FloatField.SetEnabled(!m_UseDefaultValue);
236237

237238
m_HelpBox = new HelpBox(m_HelpBoxText.text, HelpBoxMessageType.None);
238239

239240
m_DefaultToggle = new Toggle("Default") { value = m_UseDefaultValue };
240-
m_DefaultToggle.RegisterValueChangedCallback(ToggleUseDefaultValue);
241+
m_DefaultToggle.RegisterValueChangedCallback(evt => ToggleUseDefaultValue(evt, onChangedCallback));
241242

242243

243244
var buttonContainer = new VisualElement
@@ -249,12 +250,17 @@ public void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
249250
};
250251
m_OpenInputSettingsButton = new Button(InputSettingsProvider.Open){text = m_OpenInputSettingsLabel.text};
251252
m_OpenInputSettingsButton.AddToClassList("open-settings-button");
252-
buttonContainer.Add(m_OpenInputSettingsButton);
253253

254254
settingsContainer.Add(m_FloatField);
255255
settingsContainer.Add(m_DefaultToggle);
256256
container.Add(settingsContainer);
257-
container.Add(m_HelpBox);
257+
258+
if (m_UseDefaultValue)
259+
{
260+
buttonContainer.Add(m_OpenInputSettingsButton);
261+
container.Add(m_HelpBox);
262+
}
263+
258264
container.Add(buttonContainer);
259265

260266
root.Add(container);
@@ -278,18 +284,21 @@ private void ChangeSettingValue(ChangeEvent<float> evt)
278284
}
279285
}
280286

281-
private void ToggleUseDefaultValue(ChangeEvent<bool> evt)
287+
private void OnEditEnd(Action onChangedCallback)
288+
{
289+
onChangedCallback.Invoke();
290+
}
291+
292+
private void ToggleUseDefaultValue(ChangeEvent<bool> evt, Action onChangedCallback)
282293
{
283294
if (evt.newValue != m_UseDefaultValue)
284295
{
285296
m_SetValue(!evt.newValue ? m_GetDefaultValue() : m_DefaultInitializedValue);
297+
onChangedCallback.Invoke();
286298
}
287299

288300
m_UseDefaultValue = evt.newValue;
289-
290301
m_FloatField?.SetEnabled(!m_UseDefaultValue);
291-
m_HelpBox.visible = m_UseDefaultValue;
292-
m_OpenInputSettingsButton.visible = m_UseDefaultValue;
293302
}
294303

295304
#endif

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Resources/InputActionsEditorStyles.uss

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
border-width: 0;
3030
}
3131

32-
#add-new-action-button {
32+
#add-new-action-button {
3333
background-color: transparent;
3434
border-width: 0;
3535
}
@@ -40,6 +40,14 @@
4040
margin-left: 0;
4141
}
4242

43+
.add-interaction-processor-button {
44+
padding-top: 0;
45+
font-size: 12;
46+
border-width: 0;
47+
background-color: transparent;
48+
margin-right: 5;
49+
}
50+
4351
.header-label {
4452
font-size: 19px;
4553
margin-left: 7px;
@@ -136,13 +144,24 @@
136144
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/ChevronUp.png');
137145
}
138146

147+
.name-and-parameters-list-view .upDarkTheme {
148+
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_ChevronUp.png');
149+
}
150+
139151
.name-and-parameters-list-view .down {
140152
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/ChevronDown.png');
141153
}
142154

155+
.name-and-parameters-list-view .downDarkTheme {
156+
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_ChevronDown.png');
157+
}
158+
143159
.name-and-parameters-list-view .delete {
144160
background-image: resource('Toolbar Minus.png');
145161
}
162+
.name-and-parameters-list-view .deleteDarkTheme {
163+
background-image: resource('d_Toolbar Minus.png');
164+
}
146165

147166
.search-field {
148167
width: 190px;

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ActionPropertiesView.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_UI_TK_ASSET_EDITOR
2+
using System;
23
using System.Collections.Generic;
34
using System.Linq;
45
using UnityEditor;
@@ -51,6 +52,8 @@ public override void RedrawUI((SerializedInputAction ? , List<string>) viewState
5152
controlType.choices.Clear();
5253
controlType.choices.AddRange(controlTypes.Select(ObjectNames.NicifyVariableName).ToList());
5354
var controlTypeIndex = controlTypes.FindIndex(s => s == inputAction.expectedControlType);
55+
//if type changed and index is -1 clamp to 0, prevent overflowing indices
56+
controlTypeIndex = Math.Clamp(controlTypeIndex, 0, controlTypes.Count - 1);
5457
controlType.SetValueWithoutNotify(controlType.choices[controlTypeIndex]);
5558
controlType.tooltip = inputAction.expectedControlTypeTooltip;
5659

@@ -67,6 +70,7 @@ public override void RedrawUI((SerializedInputAction ? , List<string>) viewState
6770
{
6871
tooltip = InputActionsEditorConstants.InitialStateCheckTooltip
6972
};
73+
initialStateCheck.SetValueWithoutNotify(inputAction.initialStateCheck);
7074
initialStateCheck.RegisterValueChangedCallback(evt =>
7175
{
7276
Dispatch(Commands.ChangeInitialStateCheck(inputAction, evt.newValue));

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CompositePartBindingPropertiesView.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ public CompositePartBindingPropertiesView(VisualElement root, StateContainer sta
2929
m_CompositePartField = container.Q<DropdownField>("composite-part-dropdown");
3030

3131
CreateSelector(Selectors.GetSelectedBinding,
32-
(b, s) => !b.HasValue ? null : Selectors.GetCompositePartBindingViewState(b.Value, s));
32+
(b, s) => b.HasValue && b.Value.isPartOfComposite ? Selectors.GetCompositePartBindingViewState(b.Value, s) : null);
3333
}
3434

3535
public override void RedrawUI(ViewState viewState)
3636
{
37+
if (viewState == null)
38+
return;
3739
// TODO: Persist control picker state
3840
var controlPathEditor = new InputControlPathEditor(viewState.selectedBindingPath, new InputControlPickerState(),
3941
() => { Dispatch(Commands.ApplyModifiedProperties()); });

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/NameAndParametersListView.cs

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using UnityEditor;
66
using UnityEngine.InputSystem.Editor.Lists;
7+
using UnityEngine.InputSystem.Utilities;
78
using UnityEngine.UIElements;
89

910
namespace UnityEngine.InputSystem.Editor
@@ -14,16 +15,81 @@ internal class NameAndParametersListView : ViewBase<InputActionsEditorState>
1415
private readonly Func<InputActionsEditorState, IEnumerable<ParameterListView>> m_ParameterListViewSelector;
1516
private VisualElement m_ContentContainer;
1617

17-
public NameAndParametersListView(VisualElement root, StateContainer stateContainer,
18+
private SerializedProperty m_ListProperty;
19+
20+
public NameAndParametersListView(VisualElement root, StateContainer stateContainer, SerializedProperty listProperty,
1821
Func<InputActionsEditorState, IEnumerable<ParameterListView>> parameterListViewSelector)
1922
: base(stateContainer)
2023
{
2124
m_Root = root;
25+
m_ListProperty = listProperty;
2226
m_ParameterListViewSelector = parameterListViewSelector;
2327

2428
CreateSelector(state => state);
2529
}
2630

31+
public void OnAddElement(string name)
32+
{
33+
if (m_ListProperty == null)
34+
return;
35+
36+
var interactionsOrProcessorsList = NameAndParameters.ParseMultiple(m_ListProperty.stringValue).ToList();
37+
var newElement = new NameAndParameters() { name = name};
38+
interactionsOrProcessorsList.Add(newElement);
39+
40+
m_ListProperty.stringValue = ToSerializableString(interactionsOrProcessorsList);
41+
m_ListProperty.serializedObject.ApplyModifiedProperties();
42+
}
43+
44+
private void MoveElementUp(int index)
45+
{
46+
var newIndex = index - 1;
47+
SwapElement(index, newIndex);
48+
}
49+
50+
private void MoveElementDown(int index)
51+
{
52+
var newIndex = index + 1;
53+
SwapElement(index, newIndex);
54+
}
55+
56+
private void SwapElement(int oldIndex, int newIndex)
57+
{
58+
var interactionsOrProcessors = NameAndParameters.ParseMultiple(m_ListProperty.stringValue).ToArray();
59+
var oldIndexIsValid = oldIndex >= 0 && oldIndex < interactionsOrProcessors.Length;
60+
var newIndexIsValid = newIndex >= 0 && newIndex < interactionsOrProcessors.Length;
61+
if (interactionsOrProcessors.Length == 0 || !newIndexIsValid || !oldIndexIsValid)
62+
return;
63+
MemoryHelpers.Swap(ref interactionsOrProcessors[oldIndex], ref interactionsOrProcessors[newIndex]);
64+
m_ListProperty.stringValue = ToSerializableString(interactionsOrProcessors);
65+
m_ListProperty.serializedObject.ApplyModifiedProperties();
66+
}
67+
68+
private void DeleteElement(int index)
69+
{
70+
var interactionsOrProcessorsList = NameAndParameters.ParseMultiple(m_ListProperty.stringValue).ToList();
71+
interactionsOrProcessorsList.RemoveAt(index);
72+
m_ListProperty.stringValue = ToSerializableString(interactionsOrProcessorsList);
73+
m_ListProperty.serializedObject.ApplyModifiedProperties();
74+
}
75+
76+
private void OnParametersChanged(ParameterListView listView, int index)
77+
{
78+
var interactionsOrProcessorsList = NameAndParameters.ParseMultiple(m_ListProperty.stringValue).ToList();
79+
interactionsOrProcessorsList[index] = new NameAndParameters { name = interactionsOrProcessorsList[index].name, parameters = listView.GetParameters() };
80+
m_ListProperty.stringValue = ToSerializableString(interactionsOrProcessorsList);
81+
m_ListProperty.serializedObject.ApplyModifiedProperties();
82+
}
83+
84+
private static string ToSerializableString(IEnumerable<NameAndParameters> parametersForEachListItem)
85+
{
86+
if (parametersForEachListItem == null)
87+
return string.Empty;
88+
89+
return string.Join(NamedValue.Separator,
90+
parametersForEachListItem.Select(x => x.ToString()).ToArray());
91+
}
92+
2793
public override void RedrawUI(InputActionsEditorState state)
2894
{
2995
if (m_ContentContainer != null)
@@ -41,9 +107,19 @@ public override void RedrawUI(InputActionsEditorState state)
41107

42108
m_Root.Q<Label>("no-parameters-added-label").style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
43109
m_ContentContainer.Clear();
44-
foreach (var parameterListView in parameterListViews)
110+
for (int i = 0; i < parameterListViews.Count; i++)
45111
{
46-
new NameAndParametersListViewItem(m_ContentContainer, parameterListView);
112+
var index = i;
113+
var buttonProperties = new ButtonProperties()
114+
{
115+
onClickDown = () => MoveElementDown(index),
116+
onClickUp = () => MoveElementUp(index),
117+
onDelete = () => DeleteElement(index),
118+
isDownButtonActive = index < parameterListViews.Count - 1,
119+
isUpButtonActive = index > 0
120+
};
121+
new NameAndParametersListViewItem(m_ContentContainer, parameterListViews[i], buttonProperties);
122+
parameterListViews[i].onChange += () => OnParametersChanged(parameterListViews[index], index);
47123
}
48124
}
49125

@@ -57,9 +133,18 @@ public override void DestroyView()
57133
}
58134
}
59135

136+
internal struct ButtonProperties
137+
{
138+
public Action onClickUp;
139+
public Action onClickDown;
140+
public Action onDelete;
141+
public bool isUpButtonActive;
142+
public bool isDownButtonActive;
143+
}
144+
60145
internal class NameAndParametersListViewItem
61146
{
62-
public NameAndParametersListViewItem(VisualElement root, ParameterListView parameterListView)
147+
public NameAndParametersListViewItem(VisualElement root, ParameterListView parameterListView, ButtonProperties buttonProperties)
63148
{
64149
var itemTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
65150
InputActionsEditorConstants.PackagePath +
@@ -72,16 +157,21 @@ public NameAndParametersListViewItem(VisualElement root, ParameterListView param
72157
var header = container.Q<Toggle>();
73158

74159
var moveItemUpButton = new Button();
75-
moveItemUpButton.AddToClassList("up");
160+
moveItemUpButton.AddToClassList(EditorGUIUtility.isProSkin ? "upDarkTheme" : "up");
76161
moveItemUpButton.AddToClassList("name-and-parameters-list-foldout-button");
162+
moveItemUpButton.SetEnabled(buttonProperties.isUpButtonActive);
163+
moveItemUpButton.clicked += buttonProperties.onClickUp;
77164

78165
var moveItemDownButton = new Button();
79-
moveItemDownButton.AddToClassList("down");
166+
moveItemDownButton.AddToClassList(EditorGUIUtility.isProSkin ? "downDarkTheme" : "down");
80167
moveItemDownButton.AddToClassList("name-and-parameters-list-foldout-button");
168+
moveItemDownButton.SetEnabled(buttonProperties.isDownButtonActive);
169+
moveItemDownButton.clicked += buttonProperties.onClickDown;
81170

82171
var deleteItemButton = new Button();
83-
deleteItemButton.AddToClassList("delete");
172+
deleteItemButton.AddToClassList(EditorGUIUtility.isProSkin ? "deleteDarkTheme" : "delete");
84173
deleteItemButton.AddToClassList("name-and-parameters-list-foldout-button");
174+
deleteItemButton.clicked += buttonProperties.onDelete;
85175

86176
header.Add(moveItemUpButton);
87177
header.Add(moveItemDownButton);

0 commit comments

Comments
 (0)