A game about forced loneliness, made by TACStudios
at master 305 lines 15 kB view raw
1#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS 2using System; 3using System.Collections.Generic; 4using System.Linq; 5using UnityEditor; 6using UnityEngine.InputSystem.Utilities; 7 8namespace UnityEngine.InputSystem.Editor 9{ 10 internal static class ControlSchemeCommands 11 { 12 private const string kAllControlSchemesName = "All Control Schemes"; 13 private const string kNewControlSchemeName = "New Control Scheme"; 14 15 public static Command AddNewControlScheme() 16 { 17 return (in InputActionsEditorState state) => 18 { 19 state.m_Analytics?.RegisterControlSchemeEdit(); 20 return state.With(selectedControlScheme: new InputControlScheme( 21 MakeUniqueControlSchemeName(state, kNewControlSchemeName))); 22 }; 23 } 24 25 public static Command AddDeviceRequirement(InputControlScheme.DeviceRequirement requirement) 26 { 27 return (in InputActionsEditorState state) => 28 { 29 state.m_Analytics?.RegisterControlSchemeEdit(); 30 return state.With(selectedControlScheme: new InputControlScheme(state.selectedControlScheme.name, 31 state.selectedControlScheme.deviceRequirements.Append(requirement))); 32 }; 33 } 34 35 public static Command RemoveDeviceRequirement(int selectedDeviceIndex) 36 { 37 return (in InputActionsEditorState state) => 38 { 39 state.m_Analytics?.RegisterControlSchemeEdit(); 40 41 var newDeviceIndex = 42 Mathf.Clamp( 43 selectedDeviceIndex <= state.selectedDeviceRequirementIndex 44 ? state.selectedDeviceRequirementIndex - 1 45 : state.selectedDeviceRequirementIndex, -1, state.selectedDeviceRequirementIndex); 46 return state.With(selectedControlScheme: new InputControlScheme(state.selectedControlScheme.name, 47 state.selectedControlScheme.deviceRequirements.Where((r, i) => i != selectedDeviceIndex)), selectedDeviceRequirementIndex: newDeviceIndex); 48 }; 49 } 50 51 public static Command SaveControlScheme(string newControlSchemeName = "", bool updateExisting = false) 52 { 53 return (in InputActionsEditorState state) => 54 { 55 var controlSchemeName = state.selectedControlScheme.name; 56 57 var controlSchemesArray = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes)); 58 var controlScheme = controlSchemesArray 59 .FirstOrDefault(sp => sp.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue == controlSchemeName); 60 61 var actionMaps = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ActionMaps)); 62 63 // If the control scheme is null, we're saving a new control scheme, otherwise editing an existing one 64 if (controlScheme == null && updateExisting) 65 throw new InvalidOperationException("Tried to update a non-existent control scheme."); 66 67 if (updateExisting == false) 68 { 69 controlSchemeName = MakeUniqueControlSchemeName(state, controlSchemeName); 70 controlSchemesArray.InsertArrayElementAtIndex(controlSchemesArray.arraySize); 71 controlScheme = controlSchemesArray.GetArrayElementAtIndex(controlSchemesArray.arraySize - 1); 72 } 73 // If we're renaming a control scheme, we need to update the bindings that use it and make a unique name 74 if (!string.IsNullOrEmpty(newControlSchemeName)) 75 { 76 newControlSchemeName = MakeUniqueControlSchemeName(state, newControlSchemeName); 77 RenameBindingsControlSchemeHelper(controlScheme, actionMaps, controlSchemeName, newControlSchemeName); 78 } 79 80 controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue = string.IsNullOrWhiteSpace(newControlSchemeName) ? controlSchemeName : newControlSchemeName; 81 controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_BindingGroup)).stringValue = string.IsNullOrWhiteSpace(newControlSchemeName) ? controlSchemeName : newControlSchemeName; 82 83 var serializedDeviceRequirements = controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_DeviceRequirements)); 84 serializedDeviceRequirements.ClearArray(); 85 for (var i = 0; i < state.selectedControlScheme.deviceRequirements.Count; i++) 86 { 87 var deviceRequirement = state.selectedControlScheme.deviceRequirements[i]; 88 serializedDeviceRequirements.InsertArrayElementAtIndex(i); 89 90 var serializedRequirement = serializedDeviceRequirements.GetArrayElementAtIndex(i); 91 serializedRequirement 92 .FindPropertyRelative(nameof(InputControlScheme.DeviceRequirement.m_ControlPath)) 93 .stringValue = deviceRequirement.controlPath; 94 serializedRequirement.FindPropertyRelative(nameof(InputControlScheme.DeviceRequirement.m_Flags)) 95 .enumValueFlag = (int)deviceRequirement.m_Flags; 96 } 97 98 state.serializedObject.ApplyModifiedProperties(); 99 return state.With( 100 selectedControlScheme: new InputControlScheme(controlScheme), 101 // Select the control scheme updated, otherwise select the new one it was added 102 selectedControlSchemeIndex: updateExisting? state.selectedControlSchemeIndex: controlSchemesArray.arraySize - 1); 103 }; 104 } 105 106 static void RenameBindingsControlSchemeHelper(SerializedProperty controlScheme, SerializedProperty actionMaps, string controlSchemeName, string newName) 107 { 108 foreach (SerializedProperty actionMap in actionMaps) 109 { 110 var bindings = actionMap 111 .FindPropertyRelative(nameof(InputActionMap.m_Bindings)) 112 .Select(sp => new SerializedInputBinding(sp)) 113 .ToList(); 114 115 var bindingsToRename = bindings.Where(b => b.controlSchemes.Contains(controlSchemeName)).ToList(); 116 117 foreach (var binding in bindingsToRename) 118 { 119 var bindingGroups = binding.controlSchemes.ToList(); 120 bindingGroups.Remove(controlSchemeName); 121 bindingGroups.Add(newName); 122 binding.wrappedProperty.FindPropertyRelative(nameof(InputBinding.m_Groups)).stringValue = bindingGroups.Join(InputBinding.kSeparatorString); 123 } 124 } 125 } 126 127 public static Command SelectControlScheme(int controlSchemeIndex) 128 { 129 return (in InputActionsEditorState state) => 130 { 131 if (controlSchemeIndex == -1) 132 return state.With(selectedControlSchemeIndex: controlSchemeIndex, selectedControlScheme: new InputControlScheme()); 133 134 var controlSchemeSerializedProperty = state.serializedObject 135 .FindProperty(nameof(InputActionAsset.m_ControlSchemes)) 136 .GetArrayElementAtIndex(controlSchemeIndex); 137 138 return state.With( 139 selectedControlSchemeIndex: controlSchemeIndex, 140 selectedControlScheme: new InputControlScheme(controlSchemeSerializedProperty)); 141 }; 142 } 143 144 public static Command ResetSelectedControlScheme() 145 { 146 return (in InputActionsEditorState state) => 147 { 148 var controlSchemeSerializedProperty = state.selectedControlSchemeIndex == -1 ? null : 149 state.serializedObject 150 .FindProperty(nameof(InputActionAsset.m_ControlSchemes)) 151 .GetArrayElementAtIndex(state.selectedControlSchemeIndex); 152 153 if (controlSchemeSerializedProperty == null) 154 { 155 return state.With( 156 selectedControlSchemeIndex: -1, 157 selectedControlScheme: new InputControlScheme()); 158 } 159 160 return state.With( 161 selectedControlScheme: new InputControlScheme(controlSchemeSerializedProperty)); 162 }; 163 } 164 165 public static Command SelectDeviceRequirement(int deviceRequirementIndex) 166 { 167 return (in InputActionsEditorState state) => state.With(selectedDeviceRequirementIndex: deviceRequirementIndex); 168 } 169 170 /// <summary> 171 /// Duplicate creates a new instance of the selected control scheme and places it in the selected 172 /// control scheme property of the state but doesn't persist anything. 173 /// </summary> 174 public static Command DuplicateSelectedControlScheme() 175 { 176 return (in InputActionsEditorState state) => 177 { 178 state.m_Analytics?.RegisterControlSchemeEdit(); 179 180 return state.With(selectedControlScheme: new InputControlScheme( 181 MakeUniqueControlSchemeName(state, state.selectedControlScheme.name), 182 state.selectedControlScheme.deviceRequirements)); 183 }; 184 } 185 186 public static Command DeleteSelectedControlScheme() 187 { 188 return (in InputActionsEditorState state) => 189 { 190 var selectedControlSchemeName = state.selectedControlScheme.name; 191 192 var serializedArray = InputActionSerializationHelpers.GetControlSchemesArray(state.serializedObject); 193 var indexOfArrayElement = InputActionSerializationHelpers.IndexOfControlScheme(serializedArray, selectedControlSchemeName); 194 if (indexOfArrayElement < 0) 195 throw new InvalidOperationException("Control scheme doesn't exist in collection."); 196 197 // Ask for confirmation. 198 if (Dialog.Result.Cancel == Dialog.ControlScheme.ShowDeleteControlScheme(selectedControlSchemeName)) 199 return state; 200 201 serializedArray.DeleteArrayElementAtIndex(indexOfArrayElement); 202 state.serializedObject.ApplyModifiedProperties(); 203 204 if (serializedArray.arraySize == 0) 205 return state.With( 206 selectedControlSchemeIndex: -1, 207 selectedControlScheme: new InputControlScheme(), 208 selectedDeviceRequirementIndex: -1); 209 210 if (indexOfArrayElement > serializedArray.arraySize - 1) 211 return state.With( 212 selectedControlSchemeIndex: serializedArray.arraySize - 1, 213 selectedControlScheme: new InputControlScheme(serializedArray.GetArrayElementAtIndex(serializedArray.arraySize - 1)), selectedDeviceRequirementIndex: -1); 214 215 state.m_Analytics?.RegisterControlSchemeEdit(); 216 217 return state.With( 218 selectedControlSchemeIndex: indexOfArrayElement, 219 selectedControlScheme: new InputControlScheme(serializedArray.GetArrayElementAtIndex(indexOfArrayElement)), selectedDeviceRequirementIndex: -1); 220 }; 221 } 222 223 internal static string MakeUniqueControlSchemeName(InputActionsEditorState state, string name) 224 { 225 var controlSchemes = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes)); 226 227 IEnumerable<string> controlSchemeNames = Array.Empty<string>(); 228 if (controlSchemes != null) 229 controlSchemeNames = 230 controlSchemes.Select(sp => sp.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue); 231 232 return StringHelpers.MakeUniqueName(name, controlSchemeNames.Append(kAllControlSchemesName), x => x); 233 } 234 235 public static Command ChangeDeviceRequirement(int deviceRequirementIndex, bool isRequired) 236 { 237 return (in InputActionsEditorState state) => 238 { 239 var deviceRequirements = state.selectedControlScheme.deviceRequirements.ToList(); 240 var requirement = deviceRequirements[deviceRequirementIndex]; 241 requirement.isOptional = !isRequired; 242 deviceRequirements[deviceRequirementIndex] = requirement; 243 244 state.m_Analytics?.RegisterControlSchemeEdit(); 245 246 return state.With(selectedControlScheme: new InputControlScheme( 247 state.selectedControlScheme.name, 248 deviceRequirements, 249 state.selectedControlScheme.bindingGroup)); 250 }; 251 } 252 253 public static Command ReorderDeviceRequirements(int oldPosition, int newPosition) 254 { 255 return (in InputActionsEditorState state) => 256 { 257 var deviceRequirements = state.selectedControlScheme.deviceRequirements.ToList(); 258 var requirement = deviceRequirements[oldPosition]; 259 deviceRequirements.RemoveAt(oldPosition); 260 deviceRequirements.Insert(newPosition, requirement); 261 262 state.m_Analytics?.RegisterControlSchemeEdit(); 263 264 return state.With(selectedControlScheme: new InputControlScheme( 265 state.selectedControlScheme.name, 266 deviceRequirements, 267 state.selectedControlScheme.bindingGroup)); 268 }; 269 } 270 271 public static Command ChangeSelectedBindingsControlSchemes(string controlScheme, bool add) 272 { 273 return (in InputActionsEditorState state) => 274 { 275 var actionMapSO = state.serializedObject 276 ?.FindProperty(nameof(InputActionAsset.m_ActionMaps)) 277 ?.GetArrayElementAtIndex(state.selectedActionMapIndex); 278 var serializedProperty = actionMapSO?.FindPropertyRelative(nameof(InputActionMap.m_Bindings)) 279 ?.GetArrayElementAtIndex(state.selectedBindingIndex); 280 281 var groupsProperty = serializedProperty.FindPropertyRelative(nameof(InputBinding.m_Groups)); 282 var groups = groupsProperty.stringValue; 283 284 if (add) 285 groupsProperty.stringValue = groups 286 .Split(InputBinding.kSeparatorString) 287 .Append(controlScheme) 288 .Distinct() 289 .Join(InputBinding.kSeparatorString); 290 else 291 groupsProperty.stringValue = groups 292 .Split(InputBinding.kSeparatorString) 293 .Where(s => s != controlScheme) 294 .Join(InputBinding.kSeparatorString); 295 296 state.m_Analytics?.RegisterBindingEdit(); 297 298 state.serializedObject.ApplyModifiedProperties(); 299 return state; 300 }; 301 } 302 } 303} 304 305#endif