A game about forced loneliness, made by TACStudios
at master 185 lines 8.0 kB view raw
1#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS 2using System.Linq; 3using UnityEditor; 4using UnityEngine.UIElements; 5using UnityEngine.InputSystem.Layouts; 6using UnityEngine.InputSystem.Utilities; 7using System.Collections.Generic; 8 9namespace UnityEngine.InputSystem.Editor 10{ 11 internal class BindingPropertiesView : ViewBase<BindingPropertiesView.ViewState> 12 { 13 private readonly Foldout m_ParentFoldout; 14 private CompositeBindingPropertiesView m_CompositeBindingPropertiesView; 15 private CompositePartBindingPropertiesView m_CompositePartBindingPropertiesView; 16 17 public BindingPropertiesView(VisualElement root, Foldout foldout, StateContainer stateContainer) 18 : base(root, stateContainer) 19 { 20 m_ParentFoldout = foldout; 21 22 CreateSelector(state => state.selectedBindingIndex, 23 s => new ViewStateCollection<InputControlScheme>(Selectors.GetControlSchemes(s)), 24 (_, controlSchemes, s) => new ViewState 25 { 26 controlSchemes = controlSchemes, 27 currentControlScheme = s.selectedControlScheme, 28 selectedBinding = Selectors.GetSelectedBinding(s), 29 selectedBindingIndex = s.selectedBindingIndex, 30 selectedBindingPath = Selectors.GetSelectedBindingPath(s), 31 selectedInputAction = Selectors.GetSelectedAction(s) 32 }); 33 } 34 35 public override void RedrawUI(ViewState viewState) 36 { 37 var selectedBindingIndex = viewState.selectedBindingIndex; 38 if (selectedBindingIndex == -1) 39 return; 40 41 rootElement.Clear(); 42 43 var binding = viewState.selectedBinding; 44 if (!binding.HasValue) 45 return; 46 47 m_ParentFoldout.text = "Binding"; 48 if (binding.Value.isComposite) 49 { 50 m_ParentFoldout.text = "Composite"; 51 m_CompositeBindingPropertiesView = CreateChildView(new CompositeBindingPropertiesView(rootElement, stateContainer)); 52 } 53 else if (binding.Value.isPartOfComposite) 54 { 55 m_CompositePartBindingPropertiesView = CreateChildView(new CompositePartBindingPropertiesView(rootElement, stateContainer)); 56 DrawMatchingControlPaths(viewState); 57 DrawControlSchemeToggles(viewState, binding.Value); 58 } 59 else 60 { 61 var controlPathEditor = new InputControlPathEditor(viewState.selectedBindingPath, new InputControlPickerState(), 62 () => { Dispatch(Commands.ApplyModifiedProperties()); }); 63 controlPathEditor.SetControlPathsToMatch(viewState.currentControlScheme.deviceRequirements.Select(x => x.controlPath)); 64 65 var inputAction = viewState.selectedInputAction; 66 controlPathEditor.SetExpectedControlLayout(inputAction?.expectedControlType ?? ""); 67 68 var controlPathContainer = new IMGUIContainer(controlPathEditor.OnGUI); 69 rootElement.Add(controlPathContainer); 70 71 DrawMatchingControlPaths(viewState); 72 DrawControlSchemeToggles(viewState, binding.Value); 73 } 74 } 75 76 static bool s_showMatchingLayouts = false; 77 internal void DrawMatchingControlPaths(ViewState viewState) 78 { 79 bool controlPathUsagePresent = false; 80 bool showPaths = s_showMatchingLayouts; 81 List<MatchingControlPath> matchingControlPaths = MatchingControlPath.CollectMatchingControlPaths(viewState.selectedBindingPath.stringValue, showPaths, ref controlPathUsagePresent); 82 83 var parentElement = rootElement; 84 if (matchingControlPaths == null || matchingControlPaths.Count != 0) 85 { 86 var controllingElement = new Foldout() 87 { 88 text = $"Show Derived Bindings", 89 value = showPaths 90 }; 91 rootElement.Add(controllingElement); 92 93 controllingElement.RegisterValueChangedCallback(changeEvent => 94 { 95 if (changeEvent.target == controllingElement) // only react to foldout and not tree elements 96 s_showMatchingLayouts = changeEvent.newValue; 97 }); 98 99 parentElement = controllingElement; 100 } 101 102 if (matchingControlPaths == null) 103 { 104 var messageString = controlPathUsagePresent ? "No registered controls match this current binding. Some controls are only registered at runtime." : 105 "No other registered controls match this current binding. Some controls are only registered at runtime."; 106 107 var helpBox = new HelpBox(messageString, HelpBoxMessageType.Warning); 108 helpBox.AddToClassList("matching-controls"); 109 parentElement.Add(helpBox); 110 } 111 else if (matchingControlPaths.Count > 0) 112 { 113 List<TreeViewItemData<MatchingControlPath>> treeViewMatchingControlPaths = MatchingControlPath.BuildMatchingControlPathsTreeData(matchingControlPaths); 114 115 var treeView = new TreeView(); 116 parentElement.Add(treeView); 117 treeView.selectionType = UIElements.SelectionType.None; 118 treeView.AddToClassList("matching-controls"); 119 treeView.fixedItemHeight = 20; 120 treeView.SetRootItems(treeViewMatchingControlPaths); 121 122 // Set TreeView.makeItem to initialize each node in the tree. 123 treeView.makeItem = () => 124 { 125 var label = new Label(); 126 label.AddToClassList("matching-controls-labels"); 127 return label; 128 }; 129 130 // Set TreeView.bindItem to bind an initialized node to a data item. 131 treeView.bindItem = (VisualElement element, int index) => 132 { 133 var label = (element as Label); 134 var matchingControlPath = treeView.GetItemDataForIndex<MatchingControlPath>(index); 135 label.text = $"{matchingControlPath.deviceName} > {matchingControlPath.controlName}"; 136 }; 137 138 treeView.ExpandRootItems(); 139 } 140 } 141 142 public override void DestroyView() 143 { 144 m_CompositeBindingPropertiesView?.DestroyView(); 145 m_CompositePartBindingPropertiesView?.DestroyView(); 146 } 147 148 private void DrawControlSchemeToggles(ViewState viewState, SerializedInputBinding binding) 149 { 150 if (!viewState.controlSchemes.Any()) return; 151 152 var useInControlSchemeLabel = new Label("Use in control scheme") 153 { 154 name = "control-scheme-usage-title" 155 }; 156 157 rootElement.Add(useInControlSchemeLabel); 158 159 foreach (var controlScheme in viewState.controlSchemes) 160 { 161 var checkbox = new Toggle(controlScheme.name) 162 { 163 value = binding.controlSchemes.Any(scheme => controlScheme.name == scheme) 164 }; 165 rootElement.Add(checkbox); 166 checkbox.RegisterValueChangedCallback(changeEvent => 167 { 168 Dispatch(ControlSchemeCommands.ChangeSelectedBindingsControlSchemes(controlScheme.name, changeEvent.newValue)); 169 }); 170 } 171 } 172 173 internal class ViewState 174 { 175 public int selectedBindingIndex; 176 public SerializedInputBinding? selectedBinding; 177 public ViewStateCollection<InputControlScheme> controlSchemes; 178 public InputControlScheme currentControlScheme; 179 public SerializedProperty selectedBindingPath; 180 public SerializedInputAction? selectedInputAction; 181 } 182 } 183} 184 185#endif