A game about forced loneliness, made by TACStudios
at master 10 kB view raw
1#if UNITY_INPUT_SYSTEM_ENABLE_UI && UNITY_EDITOR 2using System; 3using System.Linq; 4using UnityEditor; 5using UnityEditor.EventSystems; 6using UnityEngine.InputSystem.Editor; 7 8////TODO: add button to automatically set up gamepad mouse cursor support 9 10namespace UnityEngine.InputSystem.UI.Editor 11{ 12 [CustomEditor(typeof(InputSystemUIInputModule))] 13 [InitializeOnLoad] 14 internal class InputSystemUIInputModuleEditor : UnityEditor.Editor 15 { 16 static InputSystemUIInputModuleEditor() 17 { 18#if UNITY_6000_0_OR_NEWER && ENABLE_INPUT_SYSTEM 19 InputModuleComponentFactory.SetInputModuleComponentOverride( 20 go => ObjectFactory.AddComponent<InputSystemUIInputModule>(go)); 21#endif 22 } 23 24 private static InputActionReference GetActionReferenceFromAssets(InputActionReference[] actions, params string[] actionNames) 25 { 26 foreach (var actionName in actionNames) 27 { 28 foreach (var action in actions) 29 { 30 if (action.action != null && string.Compare(action.action.name, actionName, StringComparison.InvariantCultureIgnoreCase) == 0) 31 return action; 32 } 33 } 34 return null; 35 } 36 37 private static InputActionReference[] GetAllAssetReferencesFromAssetDatabase(InputActionAsset actions) 38 { 39 if (actions == null) 40 return null; 41 42 var path = AssetDatabase.GetAssetPath(actions); 43 var assets = AssetDatabase.LoadAllAssetsAtPath(path); 44 return assets.Where(asset => asset is InputActionReference) 45 .Cast<InputActionReference>() 46 .OrderBy(x => x.name) 47 .ToArray(); 48 } 49 50 private static readonly string[] s_ActionNames = 51 { 52 "Point", 53 "LeftClick", 54 "MiddleClick", 55 "RightClick", 56 "ScrollWheel", 57 "Move", 58 "Submit", 59 "Cancel", 60 "TrackedDevicePosition", 61 "TrackedDeviceOrientation" 62 }; 63 64 private static readonly string[] s_ActionNiceNames = 65 { 66 "Point", 67 "Left Click", 68 "Middle Click", 69 "Right Click", 70 "Scroll Wheel", 71 "Move", 72 "Submit", 73 "Cancel", 74 "Tracked Position", 75 "Tracked Orientation" 76 }; 77 78 private SerializedProperty[] m_ReferenceProperties; 79 private SerializedProperty m_ActionsAsset; 80 private InputActionReference[] m_AvailableActionReferencesInAssetDatabase; 81 private string[] m_AvailableActionsInAssetNames; 82 private bool m_AdvancedFoldoutState; 83 84 private string MakeActionReferenceNameUsableInGenericMenu(string name) 85 { 86 // Ugly hack: GenericMenu interprets "/" as a submenu path. But luckily, "/" is not the only slash we have in Unicode. 87 return name.Replace("/", "\uFF0F"); 88 } 89 90 public void OnEnable() 91 { 92 var numActions = s_ActionNames.Length; 93 m_ReferenceProperties = new SerializedProperty[numActions]; 94 for (var i = 0; i < numActions; i++) 95 m_ReferenceProperties[i] = serializedObject.FindProperty($"m_{s_ActionNames[i]}Action"); 96 97 m_ActionsAsset = serializedObject.FindProperty("m_ActionsAsset"); 98 m_AvailableActionReferencesInAssetDatabase = GetAllAssetReferencesFromAssetDatabase(m_ActionsAsset.objectReferenceValue as InputActionAsset); 99 m_AvailableActionsInAssetNames = new[] { "None" } 100 .Concat(m_AvailableActionReferencesInAssetDatabase?.Select(x => MakeActionReferenceNameUsableInGenericMenu(x.name)) ?? new string[0]).ToArray(); 101 } 102 103 public void OnDisable() 104 { 105 new InputComponentEditorAnalytic(InputSystemComponent.InputSystemUIInputModule).Send(); 106 } 107 108 public static void ReassignActions(InputSystemUIInputModule module, InputActionAsset action) 109 { 110 module.actionsAsset = action; 111 var assets = GetAllAssetReferencesFromAssetDatabase(action); 112 if (assets != null) 113 { 114 module.point = GetActionReferenceFromAssets(assets, module.point?.action?.name, "Point", "MousePosition", "Mouse Position"); 115 module.leftClick = GetActionReferenceFromAssets(assets, module.leftClick?.action?.name, "Click", "LeftClick", "Left Click"); 116 module.rightClick = GetActionReferenceFromAssets(assets, module.rightClick?.action?.name, "RightClick", "Right Click", "ContextClick", "Context Click", "ContextMenu", "Context Menu"); 117 module.middleClick = GetActionReferenceFromAssets(assets, module.middleClick?.action?.name, "MiddleClick", "Middle Click"); 118 module.scrollWheel = GetActionReferenceFromAssets(assets, module.scrollWheel?.action?.name, "ScrollWheel", "Scroll Wheel", "Scroll", "Wheel"); 119 module.move = GetActionReferenceFromAssets(assets, module.move?.action?.name, "Navigate", "Move"); 120 module.submit = GetActionReferenceFromAssets(assets, module.submit?.action?.name, "Submit"); 121 module.cancel = GetActionReferenceFromAssets(assets, module.cancel?.action?.name, "Cancel", "Esc", "Escape"); 122 module.trackedDevicePosition = GetActionReferenceFromAssets(assets, module.trackedDevicePosition?.action?.name, "TrackedDevicePosition", "Position"); 123 module.trackedDeviceOrientation = GetActionReferenceFromAssets(assets, module.trackedDeviceOrientation?.action?.name, "TrackedDeviceOrientation", "Orientation"); 124 } 125 } 126 127 public override void OnInspectorGUI() 128 { 129 base.OnInspectorGUI(); 130 131 EditorGUI.BeginChangeCheck(); 132 EditorGUILayout.PropertyField(m_ActionsAsset); 133 if (EditorGUI.EndChangeCheck()) 134 { 135 var actions = m_ActionsAsset.objectReferenceValue as InputActionAsset; 136 if (actions != null) 137 { 138 serializedObject.ApplyModifiedProperties(); 139 140 ReassignActions(target as InputSystemUIInputModule, actions); 141 142 serializedObject.Update(); 143 } 144 145 // reinitialize action types 146 OnEnable(); 147 } 148 149 var numActions = s_ActionNames.Length; 150 if ((m_AvailableActionReferencesInAssetDatabase != null && m_AvailableActionReferencesInAssetDatabase.Length > 0) || m_ActionsAsset.objectReferenceValue == null) 151 { 152 for (var i = 0; i < numActions; i++) 153 { 154 // find the input action reference from the asset that matches the input action reference from the 155 // InputSystemUIInputModule that is currently selected. Note we can't use reference equality of the 156 // two InputActionReference objects here because in ReassignActions above, we create new instances 157 // every time it runs. 158 var index = IndexOfInputActionInAsset( 159 ((InputActionReference)m_ReferenceProperties[i]?.objectReferenceValue)?.action); 160 161 EditorGUI.BeginChangeCheck(); 162 index = EditorGUILayout.Popup(s_ActionNiceNames[i], index, m_AvailableActionsInAssetNames); 163 164 if (EditorGUI.EndChangeCheck()) 165 m_ReferenceProperties[i].objectReferenceValue = 166 index > 0 ? m_AvailableActionReferencesInAssetDatabase[index - 1] : null; 167 } 168 } 169 else 170 { 171 // Somehow we have an asset but no asset references from the database, pull out references manually and show them in read only UI 172 EditorGUILayout.HelpBox("Showing fields as read-only because current action asset seems to be created by a script and assigned programmatically.", MessageType.Info); 173 174 EditorGUI.BeginDisabledGroup(true); 175 for (var i = 0; i < numActions; i++) 176 { 177 var retrievedName = "None"; 178 if (m_ReferenceProperties[i].objectReferenceValue != null && 179 (m_ReferenceProperties[i].objectReferenceValue is InputActionReference reference)) 180 retrievedName = MakeActionReferenceNameUsableInGenericMenu(reference.ToDisplayName()); 181 182 EditorGUILayout.Popup(s_ActionNiceNames[i], 0, new[] {retrievedName}); 183 } 184 EditorGUI.EndDisabledGroup(); 185 } 186 187 m_AdvancedFoldoutState = EditorGUILayout.Foldout(m_AdvancedFoldoutState, new GUIContent("Advanced"), true); 188 if (m_AdvancedFoldoutState) 189 EditorGUILayout.PropertyField(serializedObject.FindProperty("m_CursorLockBehavior"), 190 EditorGUIUtility.TrTextContent("Cursor Lock Behavior", 191 $"Controls the origin point of UI raycasts when the cursor is locked. {InputSystemUIInputModule.CursorLockBehavior.OutsideScreen} " + 192 $"is the default behavior and will force the raycast to miss all objects. {InputSystemUIInputModule.CursorLockBehavior.ScreenCenter} " + 193 $"will cast the ray from the center of the screen.")); 194 195 if (GUI.changed) 196 serializedObject.ApplyModifiedProperties(); 197 } 198 199 private int IndexOfInputActionInAsset(InputAction inputAction) 200 { 201 // return 0 instead of -1 here because the zero-th index refers to the 'None' binding. 202 if (inputAction == null) 203 return 0; 204 if (m_AvailableActionReferencesInAssetDatabase == null) 205 return 0; 206 207 var index = 0; 208 for (var j = 0; j < m_AvailableActionReferencesInAssetDatabase.Length; j++) 209 { 210 if (m_AvailableActionReferencesInAssetDatabase[j].action != null && 211 m_AvailableActionReferencesInAssetDatabase[j].action == inputAction) 212 { 213 index = j + 1; 214 break; 215 } 216 } 217 218 return index; 219 } 220 } 221} 222#endif