#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.UIElements; using UnityEngine.UIElements; namespace UnityEngine.InputSystem.Editor { internal class ActionPropertiesView : ViewBase<(SerializedInputAction?, List<string>)> { private readonly Foldout m_ParentFoldout; private readonly int m_DropdownLabelWidth = 90; public ActionPropertiesView(VisualElement root, Foldout foldout, StateContainer stateContainer) : base(root, stateContainer) { m_ParentFoldout = foldout; // TODO: Consider IEquatable<T> and how to compare selector data CreateSelector(Selectors.GetSelectedAction, (inputAction, _) => { if (!inputAction.HasValue) return (null, new List<string>()); return (inputAction.Value, Selectors.BuildControlTypeList(inputAction.Value.type).ToList()); }); } public override void RedrawUI((SerializedInputAction ? , List<string>) viewState) { if (!viewState.Item1.HasValue) return; m_ParentFoldout.text = "Action"; var inputAction = viewState.Item1.Value; rootElement.Clear(); var actionType = new EnumField("Action Type", inputAction.type) { tooltip = inputAction.actionTypeTooltip }; // Tighten up the gap between the label and dropdown so the latter is more readable when the parent pane is at min width. var actionLabel = actionType.Q<Label>(); actionLabel.style.minWidth = m_DropdownLabelWidth; actionLabel.style.width = m_DropdownLabelWidth; actionType.RegisterValueChangedCallback(evt => { Dispatch(Commands.ChangeActionType(inputAction, (InputActionType)evt.newValue)); }); rootElement.Add(actionType); if (inputAction.type != InputActionType.Button) { var controlTypes = viewState.Item2; var controlType = new DropdownField("Control Type"); // Tighten up the gap between the label and dropdown so the latter is more readable when the parent pane is at min width. var controlLabel = controlType.Q<Label>(); controlLabel.style.minWidth = m_DropdownLabelWidth; controlLabel.style.width = m_DropdownLabelWidth; controlType.choices.Clear(); controlType.choices.AddRange(controlTypes.Select(ObjectNames.NicifyVariableName).ToList()); var controlTypeIndex = controlTypes.FindIndex(s => s == inputAction.expectedControlType); //if type changed and index is -1 clamp to 0, prevent overflowing indices controlTypeIndex = Math.Clamp(controlTypeIndex, 0, controlTypes.Count - 1); controlType.SetValueWithoutNotify(controlType.choices[controlTypeIndex]); controlType.tooltip = inputAction.expectedControlTypeTooltip; controlType.RegisterValueChangedCallback(evt => { Dispatch(Commands.ChangeActionControlType(inputAction, controlType.index)); }); // ISX-1916 - When changing ActionType to a non-Button type, we must also update the ControlType // to the currently selected value; the ValueChangedCallback is not fired in this scenario. Dispatch(Commands.ChangeActionControlType(inputAction, controlType.index)); rootElement.Add(controlType); } else { // ISX-1916 - When changing ActionType to a Button, we must also reset the ControlType Dispatch(Commands.ChangeActionControlType(inputAction, 0)); } if (inputAction.type != InputActionType.Value) { var initialStateCheck = new Toggle("Initial State Check") { tooltip = InputActionsEditorConstants.InitialStateCheckTooltip }; initialStateCheck.SetValueWithoutNotify(inputAction.initialStateCheck); initialStateCheck.RegisterValueChangedCallback(evt => { Dispatch(Commands.ChangeInitialStateCheck(inputAction, evt.newValue)); }); rootElement.Add(initialStateCheck); } } } } #endif