public static SerializedProperty AddBindingToBindingArray(SerializedProperty bindingsArrayProperty, int bindingIndex = -1, string actionName = "", string groups = "", string path = "", string name = "", string interactions = "", string processors = "", InputBinding.Flags flags = InputBinding.Flags.None) { Debug.Assert(bindingsArrayProperty != null); Debug.Assert(bindingsArrayProperty.isArray, "SerializedProperty is not an array of bindings"); Debug.Assert(bindingIndex == -1 || (bindingIndex >= 0 && bindingIndex <= bindingsArrayProperty.arraySize)); if (bindingIndex == -1) { bindingIndex = bindingsArrayProperty.arraySize; } bindingsArrayProperty.InsertArrayElementAtIndex(bindingIndex); var newBindingProperty = bindingsArrayProperty.GetArrayElementAtIndex(bindingIndex); newBindingProperty.FindPropertyRelative("m_Path").stringValue = path; newBindingProperty.FindPropertyRelative("m_Groups").stringValue = groups; newBindingProperty.FindPropertyRelative("m_Interactions").stringValue = interactions; newBindingProperty.FindPropertyRelative("m_Processors").stringValue = processors; newBindingProperty.FindPropertyRelative("m_Flags").intValue = (int)flags; newBindingProperty.FindPropertyRelative("m_Action").stringValue = actionName; newBindingProperty.FindPropertyRelative("m_Name").stringValue = name; newBindingProperty.FindPropertyRelative("m_Id").stringValue = Guid.NewGuid().ToString(); ////FIXME: this likely leaves m_Bindings in the map for singleton actions unsync'd in some cases return(newBindingProperty); }
////TODO: move this out into a general routine that can take a path and construct a display name private GUIContent GetContentForPath(string path, string modifiers, InputBinding.Flags flags) { if (s_UsageRegex == null) { s_UsageRegex = new Regex("\\*/{([A-Za-z0-9]+)}"); } if (s_ControlRegex == null) { s_ControlRegex = new Regex("<([A-Za-z0-9]+)>/([A-Za-z0-9]+(/[A-Za-z0-9]+)*)"); } var text = path; ////TODO: make this less GC heavy ////TODO: prettify control names (e.g. "rightTrigger" should read "Right Trigger"); have explicit display names? ////REVIEW: This stuff here should really be based on general display functionality for controls //// which should be available to game code in just the same way for on-screen display //// purposes var usageMatch = s_UsageRegex.Match(path); if (usageMatch.Success) { text = usageMatch.Groups[1].Value; } else { var controlMatch = s_ControlRegex.Match(path); if (controlMatch.Success) { var device = controlMatch.Groups[1].Value; var control = controlMatch.Groups[2].Value; ////TODO: would be nice to include template name to print something like "Gamepad A Button" instead of "Gamepad A" (or whatever) text = string.Format("{0} {1}", device, control); } } ////REVIEW: would be nice to have icons for these // Show modifiers. if (!string.IsNullOrEmpty(modifiers)) { var modifierList = InputTemplate.ParseNameAndParameterList(modifiers); var modifierString = string.Join(" OR ", modifierList.Select(x => x.name).ToArray()); text = string.Format("{0} {1}", modifierString, text); } ////TODO: this looks ugly and not very obvious; find a better way // Show if linked with previous binding. if ((flags & InputBinding.Flags.ThisAndPreviousCombine) == InputBinding.Flags.ThisAndPreviousCombine) { text = "AND " + text; } return(new GUIContent(text)); }
// Equivalent to InputAction.AddBinding(). public static SerializedProperty AddBinding(SerializedProperty actionProperty, SerializedProperty actionMapProperty = null, SerializedProperty afterBinding = null, string groups = "", string path = "", string name = "", string interactions = "", string processors = "", InputBinding.Flags flags = InputBinding.Flags.None) { var bindingsArrayProperty = actionMapProperty != null ? actionMapProperty.FindPropertyRelative("m_Bindings") : actionProperty.FindPropertyRelative("m_SingletonActionBindings"); var bindingsCount = bindingsArrayProperty.arraySize; var actionName = actionProperty.FindPropertyRelative("m_Name").stringValue; int bindingIndex; if (afterBinding != null) { // If we're supposed to put the binding right after another binding, find the // binding's index. Also, if it's a composite, skip past all its parts. bindingIndex = GetIndex(bindingsArrayProperty, afterBinding); if (IsCompositeBinding(afterBinding)) { bindingIndex += GetCompositePartCount(bindingsArrayProperty, bindingIndex); } ++bindingIndex; // Put it *after* the binding. } else { // Find the index of the last binding for the action in the array. var indexOfLastBindingForAction = -1; for (var i = 0; i < bindingsCount; ++i) { var bindingProperty = bindingsArrayProperty.GetArrayElementAtIndex(i); var bindingActionName = bindingProperty.FindPropertyRelative("m_Action").stringValue; if (actionName.Equals(bindingActionName, StringComparison.InvariantCultureIgnoreCase)) { indexOfLastBindingForAction = i; } } // Insert after last binding or at end of array. bindingIndex = indexOfLastBindingForAction != -1 ? indexOfLastBindingForAction + 1 : bindingsCount; } ////TODO: bind using {id} rather than action name return(AddBindingToBindingArray(bindingsArrayProperty, bindingIndex: bindingIndex, actionName: actionName, groups: groups, path: path, name: name, interactions: interactions, processors: processors, flags: flags)); }
////TODO: close with escape public override void OnGUI(Rect rect) { m_ScrollPosition = GUI.BeginScrollView(rect, m_ScrollPosition, rect); // Interactions section. var interactionListRect = rect; interactionListRect.x += kPaddingLeftRight; interactionListRect.y += kPaddingTop; interactionListRect.width -= kPaddingLeftRight * 2; interactionListRect.height = m_InteractionListView.GetHeight(); m_InteractionListView.DoList(interactionListRect); ////TODO: draw box around following section // Chaining toggle. var chainingToggleRect = interactionListRect; chainingToggleRect.y += interactionListRect.height + 5; chainingToggleRect.height = kCombineToggleHeight; ////TODO: disable toggle if property is first in list (bit tricky to find out from the SerializedProperty) var currentCombineSetting = (m_Flags & InputBinding.Flags.ThisAndPreviousCombine) == InputBinding.Flags.ThisAndPreviousCombine; var newCombineSetting = EditorGUI.ToggleLeft(chainingToggleRect, Contents.chain, currentCombineSetting); if (currentCombineSetting != newCombineSetting) { if (newCombineSetting) { m_Flags |= InputBinding.Flags.ThisAndPreviousCombine; } else { m_Flags &= ~InputBinding.Flags.ThisAndPreviousCombine; } m_FlagsProperty.intValue = (int)m_Flags; m_FlagsProperty.serializedObject.ApplyModifiedProperties(); if (onApplyCallback != null) { onApplyCallback(m_FlagsProperty); } } GUI.EndScrollView(); }
public ModifyPopupWindow(SerializedProperty bindingProperty) { m_FlagsProperty = bindingProperty.FindPropertyRelative("flags"); m_ModifiersProperty = bindingProperty.FindPropertyRelative("modifiers"); m_Flags = (InputBinding.Flags)m_FlagsProperty.intValue; var modifiers = InputSystem.ListModifiers().ToList(); modifiers.Sort(); m_ModifierChoices = modifiers.Select(x => new GUIContent(x)).ToArray(); var modifierString = m_ModifiersProperty.stringValue; if (!string.IsNullOrEmpty(modifierString)) { m_Modifiers = InputTemplate.ParseNameAndParameterList(modifierString); } else { m_Modifiers = new InputTemplate.NameAndParameters[0]; //Array.Empty<InputTemplate.NameAndParameters>(); } InitializeModifierListView(); }
// Equivalent to InputAction.AddBinding(). public static SerializedProperty AddBinding(SerializedProperty actionProperty, SerializedProperty actionMapProperty = null, string groups = "", string path = "", string name = "", string interactions = "", string processors = "", InputBinding.Flags flags = InputBinding.Flags.None) { var bindingsArrayProperty = actionMapProperty != null ? actionMapProperty.FindPropertyRelative("m_Bindings") : actionProperty.FindPropertyRelative("m_SingletonActionBindings"); var bindingsCount = bindingsArrayProperty.arraySize; // Find the index of the last binding for the action in the array. var actionName = actionProperty.FindPropertyRelative("m_Name").stringValue; var indexOfLastBindingForAction = -1; for (var i = 0; i < bindingsCount; ++i) { var bindingProperty = bindingsArrayProperty.GetArrayElementAtIndex(i); var bindingActionName = bindingProperty.FindPropertyRelative("m_Action").stringValue; if (string.Compare(actionName, bindingActionName, StringComparison.InvariantCultureIgnoreCase) == 0) { indexOfLastBindingForAction = i; } } // Insert after last binding or at end of array. var bindingIndex = indexOfLastBindingForAction != -1 ? indexOfLastBindingForAction + 1 : bindingsCount; return(AddBindingToBindingArray(bindingsArrayProperty, bindingIndex, actionName: actionName, groups: groups, path: path, name: name, interactions: interactions, processors: processors, flags: flags)); }
public ModifyPopupWindow(SerializedProperty bindingProperty) { m_FlagsProperty = bindingProperty.FindPropertyRelative("m_Flags"); m_InteractionsProperty = bindingProperty.FindPropertyRelative("m_Interactions"); m_Flags = (InputBinding.Flags)m_FlagsProperty.intValue; var interactions = InputSystem.ListInteractions().ToList(); interactions.Sort(); m_InteractionChoices = interactions.Select(x => new GUIContent(x)).ToArray(); var interactionString = m_InteractionsProperty.stringValue; if (!string.IsNullOrEmpty(interactionString)) { m_Interactions = InputControlLayout.ParseNameAndParameterList(interactionString); } else { m_Interactions = new InputControlLayout.NameAndParameters[0]; } InitializeInteractionListView(); }
////TODO: move this out into a general routine that can take a path and construct a display name private static GUIContent GetContentForPath(string path, string interactions, InputBinding.Flags flags) { const int kUsageNameGroup = 1; const int kDeviceNameGroup = 1; const int kDeviceUsageGroup = 3; const int kControlPathGroup = 4; ////TODO: nuke the regex stuff in here if (s_UsageRegex == null) { s_UsageRegex = new Regex("\\*/{([A-Za-z0-9]+)}"); } if (s_ControlRegex == null) { s_ControlRegex = new Regex("<([A-Za-z0-9:\\-]+)>({([A-Za-z0-9]+)})?/([A-Za-z0-9]+(/[A-Za-z0-9]+)*)"); } var text = path; var usageMatch = s_UsageRegex.Match(path); if (usageMatch.Success) { text = usageMatch.Groups[kUsageNameGroup].Value; } else { var controlMatch = s_ControlRegex.Match(path); if (controlMatch.Success) { var device = controlMatch.Groups[kDeviceNameGroup].Value; var deviceUsage = controlMatch.Groups[kDeviceUsageGroup].Value; var control = controlMatch.Groups[kControlPathGroup].Value; ////TODO: would be nice to include layout name to print something like "Gamepad A Button" instead of "Gamepad A" (or whatever) if (!string.IsNullOrEmpty(deviceUsage)) { text = string.Format("{0} {1} {2}", deviceUsage, device, control); } else { text = string.Format("{0} {1}", device, control); } } } ////REVIEW: would be nice to have icons for these // Show interactions. if (!string.IsNullOrEmpty(interactions)) { var interactionList = InputControlLayout.ParseNameAndParameterList(interactions); var interactionString = string.Join(" OR ", interactionList.Select(x => x.name).ToArray()); text = string.Format("{0} {1}", interactionString, text); } ////TODO: this looks ugly and not very obvious; find a better way // Show if linked with previous binding. if ((flags & InputBinding.Flags.ThisAndPreviousCombine) == InputBinding.Flags.ThisAndPreviousCombine) { text = "AND " + text; } return(new GUIContent(text)); }