A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR
2using System;
3using System.Linq;
4using UnityEditor;
5using UnityEditorInternal;
6using UnityEngine.InputSystem.Utilities;
7using UnityEngine.UIElements;
8
9////TODO: detect if new input backends are enabled and put UI in here to enable them if needed
10
11////TODO: keywords (2019.1+)
12#pragma warning disable CS0414
13namespace UnityEngine.InputSystem.Editor
14{
15 internal static class InputSettingsPath
16 {
17 public const string kSettingsRootPath = "Project/Input System Package";
18 }
19
20 internal class InputSettingsProvider : SettingsProvider, IDisposable
21 {
22 public const string kEditorBuildSettingsConfigKey = "com.unity.input.settings";
23
24 #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
25 // When Project Wide Actions are enabled we place this as a child node to main settings node.
26 public const string kSettingsPath = InputSettingsPath.kSettingsRootPath + "/Settings";
27 #else
28 // When Project Wide Actions are not enabled we let this be the main settings node.
29 public const string kSettingsPath = "Project/Input System Package";
30 #endif
31
32 public static void Open()
33 {
34 SettingsService.OpenProjectSettings(kSettingsPath);
35 }
36
37 [SettingsProvider]
38 public static SettingsProvider CreateInputSettingsProvider()
39 {
40 return new InputSettingsProvider(kSettingsPath, SettingsScope.Project)
41 {
42 #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
43 // We put this in a child node called "Settings" when Project-wide Actions is enabled.
44 // When not enabled it sits on the main package Settings node.
45 label = "Settings"
46 #endif
47 };
48 }
49
50 private InputSettingsProvider(string path, SettingsScope scopes)
51 : base(path, scopes)
52 {
53 label = "Input System Package";
54 s_Instance = this;
55 }
56
57 public override void OnActivate(string searchContext, VisualElement rootElement)
58 {
59 base.OnActivate(searchContext, rootElement);
60 InputSystem.onSettingsChange += OnSettingsChange;
61 Undo.undoRedoPerformed += OnUndoRedo;
62 }
63
64 public override void OnDeactivate()
65 {
66 base.OnDeactivate();
67 InputSystem.onSettingsChange -= OnSettingsChange;
68 Undo.undoRedoPerformed -= OnUndoRedo;
69 }
70
71 public void Dispose()
72 {
73 m_SettingsObject?.Dispose();
74 }
75
76 public override void OnTitleBarGUI()
77 {
78 if (EditorGUILayout.DropdownButton(EditorGUIUtility.IconContent("_Popup"), FocusType.Passive, EditorStyles.label))
79 {
80 var menu = new GenericMenu();
81 menu.AddDisabledItem(new GUIContent("Available Settings Assets:"));
82 menu.AddSeparator("");
83 for (var i = 0; i < m_AvailableSettingsAssetsOptions.Length; i++)
84 menu.AddItem(new GUIContent(m_AvailableSettingsAssetsOptions[i]), m_CurrentSelectedInputSettingsAsset == i, (path) => {
85 InputSystem.settings = AssetDatabase.LoadAssetAtPath<InputSettings>((string)path);
86 }, m_AvailableInputSettingsAssets[i]);
87 menu.AddSeparator("");
88 menu.AddItem(new GUIContent("New Settings Asset…"), false, CreateNewSettingsAsset);
89 menu.ShowAsContext();
90 Event.current.Use();
91 }
92 }
93
94 public override void OnGUI(string searchContext)
95 {
96 InitializeWithCurrentSettingsIfNecessary();
97
98 if (m_AvailableInputSettingsAssets.Length == 0)
99 {
100 EditorGUILayout.HelpBox(
101 "Settings for the new input system are stored in an asset. Click the button below to create a settings asset you can edit.",
102 MessageType.Info);
103 if (GUILayout.Button("Create settings asset", GUILayout.Height(30)))
104 CreateNewSettingsAsset("Assets/InputSystem.inputsettings.asset");
105 GUILayout.Space(20);
106 }
107
108 using (new EditorGUI.DisabledScope(m_AvailableInputSettingsAssets.Length == 0))
109 {
110 EditorGUILayout.Space();
111 EditorGUILayout.Separator();
112 EditorGUILayout.Space();
113
114 Debug.Assert(m_Settings != null);
115
116 EditorGUI.BeginChangeCheck();
117
118 EditorGUILayout.PropertyField(m_UpdateMode, m_UpdateModeContent);
119 var runInBackground = Application.runInBackground;
120 using (new EditorGUI.DisabledScope(!runInBackground))
121 EditorGUILayout.PropertyField(m_BackgroundBehavior, m_BackgroundBehaviorContent);
122 if (!runInBackground)
123 EditorGUILayout.HelpBox("Focus change behavior can only be changed if 'Run In Background' is enabled in Player Settings.", MessageType.Info);
124
125#if UNITY_INPUT_SYSTEM_PLATFORM_SCROLL_DELTA
126 EditorGUILayout.PropertyField(m_ScrollDeltaBehavior, m_ScrollDeltaBehaviorContent);
127#endif
128
129 EditorGUILayout.Space();
130 EditorGUILayout.PropertyField(m_CompensateForScreenOrientation, m_CompensateForScreenOrientationContent);
131
132 // NOTE: We do NOT make showing this one conditional on whether runInBackground is actually set in the
133 // player settings as regardless of whether it's on or not, Unity will force it on in standalone
134 // development players.
135
136 EditorGUILayout.Space();
137 EditorGUILayout.Separator();
138 EditorGUILayout.Space();
139
140 EditorGUILayout.PropertyField(m_DefaultDeadzoneMin, m_DefaultDeadzoneMinContent);
141 EditorGUILayout.PropertyField(m_DefaultDeadzoneMax, m_DefaultDeadzoneMaxContent);
142 EditorGUILayout.PropertyField(m_DefaultButtonPressPoint, m_DefaultButtonPressPointContent);
143 EditorGUILayout.PropertyField(m_ButtonReleaseThreshold, m_ButtonReleaseThresholdContent);
144 EditorGUILayout.PropertyField(m_DefaultTapTime, m_DefaultTapTimeContent);
145 EditorGUILayout.PropertyField(m_DefaultSlowTapTime, m_DefaultSlowTapTimeContent);
146 EditorGUILayout.PropertyField(m_DefaultHoldTime, m_DefaultHoldTimeContent);
147 EditorGUILayout.PropertyField(m_TapRadius, m_TapRadiusContent);
148 EditorGUILayout.PropertyField(m_MultiTapDelayTime, m_MultiTapDelayTimeContent);
149
150 EditorGUILayout.Space();
151 EditorGUILayout.Separator();
152 EditorGUILayout.Space();
153
154 EditorGUILayout.HelpBox("Leave 'Supported Devices' empty if you want the input system to support all input devices it can recognize. If, however, "
155 + "you are only interested in a certain set of devices, adding them here will narrow the scope of what's presented in the editor "
156 + "and avoid picking up input from devices not relevant to the project. When you add devices here, any device that will not be classified "
157 + "as supported will appear under 'Unsupported Devices' in the input debugger.", MessageType.None);
158
159 m_SupportedDevices.DoLayoutList();
160
161 EditorGUILayout.LabelField("iOS", EditorStyles.boldLabel);
162 EditorGUILayout.Space();
163 m_iOSProvider.OnGUI();
164
165 EditorGUILayout.Space();
166 EditorGUILayout.LabelField("Editor", EditorStyles.boldLabel);
167 EditorGUILayout.Space();
168 EditorGUILayout.PropertyField(m_EditorInputBehaviorInPlayMode, m_EditorInputBehaviorInPlayModeContent);
169
170 EditorGUILayout.Space();
171 EditorGUILayout.LabelField("Improved Shortcut Support", EditorStyles.boldLabel);
172 EditorGUILayout.Space();
173 EditorGUILayout.PropertyField(m_ShortcutKeysConsumeInputs, m_ShortcutKeysConsumeInputsContent);
174 if (m_ShortcutKeysConsumeInputs.boolValue)
175 EditorGUILayout.HelpBox("Please note that enabling Improved Shortcut Support will cause actions with composite bindings to consume input and block any other actions which are enabled and sharing the same controls. "
176 + "Input consumption is performed in priority order, with the action containing the greatest number of bindings checked first. "
177 + "Therefore actions requiring fewer keypresses will not be triggered if an action using more keypresses is triggered and has overlapping controls. "
178 + "This works for shortcut keys, however in other cases this might not give the desired result, especially where there are actions with the exact same number of composite controls, in which case it is non-deterministic which action will be triggered. "
179 + "These conflicts may occur even between actions which belong to different Action Maps e.g. if using an UIInputModule with the Arrow Keys bound to the Navigate Action in the UI Action Map, this would interfere with other Action Maps using those keys. "
180 + "However conflicts would not occur between actions which belong to different Action Assets. "
181 + "Since event consumption only occurs for enabled actions, you can resolve unexpected issues by ensuring that only those Actions or Action Maps that are relevant to your game's current context are enabled. Enabling or disabling actions as your game or application moves between different contexts. "
182 , MessageType.None);
183
184 if (EditorGUI.EndChangeCheck())
185 Apply();
186 }
187 }
188
189 private static void ShowPlatformSettings()
190 {
191 // Would be nice to get BuildTargetDiscovery.GetBuildTargetInfoList since that contains information about icons etc
192 }
193
194 private static void CreateNewSettingsAsset(string relativePath)
195 {
196 // Create and install the settings. This will lead to an InputSystem.onSettingsChange event which in turn
197 // will cause us to re-initialize.
198 InputSystem.settings = InputAssetEditorUtils.CreateAsset(ScriptableObject.CreateInstance<InputSettings>(), relativePath);
199 }
200
201 private static void CreateNewSettingsAsset()
202 {
203 var result = InputAssetEditorUtils.PromptUserForAsset(
204 friendlyName: "Input Settings",
205 suggestedAssetFilePathWithoutExtension: InputAssetEditorUtils.MakeProjectFileName("inputsettings"),
206 assetFileExtension: "asset");
207 if (result.result == InputAssetEditorUtils.DialogResult.Valid)
208 CreateNewSettingsAsset(result.relativePath);
209 }
210
211 private void InitializeWithCurrentSettingsIfNecessary()
212 {
213 if (InputSystem.settings == m_Settings && m_Settings != null && m_SettingsDirtyCount == EditorUtility.GetDirtyCount(m_Settings))
214 return;
215
216 InitializeWithCurrentSettings();
217 }
218
219 /// <summary>
220 /// Grab <see cref="InputSystem.settings"/> and set it up for editing.
221 /// </summary>
222 private void InitializeWithCurrentSettings()
223 {
224 // Find the set of available assets in the project.
225 m_AvailableInputSettingsAssets = FindInputSettingsInProject();
226
227 // See which is the active one.
228 m_Settings = InputSystem.settings;
229 m_SettingsDirtyCount = EditorUtility.GetDirtyCount(m_Settings);
230 var currentSettingsPath = AssetDatabase.GetAssetPath(m_Settings);
231 if (string.IsNullOrEmpty(currentSettingsPath))
232 {
233 if (m_AvailableInputSettingsAssets.Length != 0)
234 {
235 m_CurrentSelectedInputSettingsAsset = 0;
236 m_Settings = AssetDatabase.LoadAssetAtPath<InputSettings>(m_AvailableInputSettingsAssets[0]);
237 InputSystem.settings = m_Settings;
238 }
239 }
240 else
241 {
242 m_CurrentSelectedInputSettingsAsset = ArrayHelpers.IndexOf(m_AvailableInputSettingsAssets, currentSettingsPath);
243 if (m_CurrentSelectedInputSettingsAsset == -1)
244 {
245 // This is odd and shouldn't happen. Solve by just adding the path to the list.
246 m_CurrentSelectedInputSettingsAsset =
247 ArrayHelpers.Append(ref m_AvailableInputSettingsAssets, currentSettingsPath);
248 }
249
250 ////REVIEW: should we store this by platform?
251 EditorBuildSettings.AddConfigObject(kEditorBuildSettingsConfigKey, m_Settings, true);
252 }
253
254 // Refresh the list of assets we display in the UI.
255 m_AvailableSettingsAssetsOptions = new GUIContent[m_AvailableInputSettingsAssets.Length];
256 for (var i = 0; i < m_AvailableInputSettingsAssets.Length; ++i)
257 {
258 var name = m_AvailableInputSettingsAssets[i];
259 if (name.StartsWith("Assets/"))
260 name = name.Substring("Assets/".Length);
261 if (name.EndsWith(".asset"))
262 name = name.Substring(0, name.Length - ".asset".Length);
263 if (name.EndsWith(".inputsettings"))
264 name = name.Substring(0, name.Length - ".inputsettings".Length);
265
266 // Ugly hack: GenericMenu interprets "/" as a submenu path. But luckily, "/" is not the only slash we have in Unicode.
267 m_AvailableSettingsAssetsOptions[i] = new GUIContent(name.Replace("/", "\u29f8"));
268 }
269
270 // Look up properties.
271 m_SettingsObject = new SerializedObject(m_Settings);
272 m_UpdateMode = m_SettingsObject.FindProperty("m_UpdateMode");
273 m_ScrollDeltaBehavior = m_SettingsObject.FindProperty("m_ScrollDeltaBehavior");
274 m_CompensateForScreenOrientation = m_SettingsObject.FindProperty("m_CompensateForScreenOrientation");
275 m_BackgroundBehavior = m_SettingsObject.FindProperty("m_BackgroundBehavior");
276 m_EditorInputBehaviorInPlayMode = m_SettingsObject.FindProperty("m_EditorInputBehaviorInPlayMode");
277 m_DefaultDeadzoneMin = m_SettingsObject.FindProperty("m_DefaultDeadzoneMin");
278 m_DefaultDeadzoneMax = m_SettingsObject.FindProperty("m_DefaultDeadzoneMax");
279 m_DefaultButtonPressPoint = m_SettingsObject.FindProperty("m_DefaultButtonPressPoint");
280 m_ButtonReleaseThreshold = m_SettingsObject.FindProperty("m_ButtonReleaseThreshold");
281 m_DefaultTapTime = m_SettingsObject.FindProperty("m_DefaultTapTime");
282 m_DefaultSlowTapTime = m_SettingsObject.FindProperty("m_DefaultSlowTapTime");
283 m_DefaultHoldTime = m_SettingsObject.FindProperty("m_DefaultHoldTime");
284 m_TapRadius = m_SettingsObject.FindProperty("m_TapRadius");
285 m_MultiTapDelayTime = m_SettingsObject.FindProperty("m_MultiTapDelayTime");
286 m_ShortcutKeysConsumeInputs = m_SettingsObject.FindProperty("m_ShortcutKeysConsumeInputs");
287
288 m_UpdateModeContent = new GUIContent("Update Mode", "When should the Input System be updated?");
289#if UNITY_INPUT_SYSTEM_PLATFORM_SCROLL_DELTA
290 m_ScrollDeltaBehaviorContent = new GUIContent("Scroll Delta Behavior", "Controls whether the value returned by the Scroll Wheel Delta is normalized (to be uniform across all platforms), or returns the non-normalized platform-specific range which can vary between platforms.");
291#endif
292 m_CompensateForScreenOrientationContent = new GUIContent("Compensate Orientation", "Whether sensor input on mobile devices should be transformed to be relative to the current device orientation.");
293 m_BackgroundBehaviorContent = new GUIContent("Background Behavior", "If runInBackground is true (and in standalone *development* players and the editor), "
294 + "determines what happens to InputDevices and events when the application moves in and out of running in the foreground.\n\n"
295 + "'Reset And Disable Non-Background Devices' soft-resets and disables devices that cannot run in the background while the application does not have focus. Devices "
296 + "that can run in the background remain enabled and will keep receiving input.\n"
297 + "'Reset And Disable All Devices' soft-resets and disables *all* devices while the application does not have focus. No device will receive input while the application "
298 + "is running in the background.\n"
299 + "'Ignore Focus' leaves all devices untouched when application focus changes. While running in the background, all input that is received is processed as if "
300 + "running in the foreground.");
301 m_EditorInputBehaviorInPlayModeContent = new GUIContent("Play Mode Input Behavior", "When in play mode, determines how focus of the Game View is handled with respect to input.\n\n"
302 + "'Pointers And Keyboards Respect Game View Focus' requires Game View focus only for pointers (mice, touch, etc.) and keyboards. Other devices will feed input to the game regardless "
303 + "of whether the Game View is focused or not. Note that this means that input on these devices is not visible in other EditorWindows.\n"
304 + "'All Devices Respect Game View Focus' requires Game View focus for all input devices. While focus is not on the Game View, all input on InputDevices will go to the editor and not "
305 + "the game.\n"
306 + "'All Device Input Always Goes To Game View' causes input to treat 'Background Behavior' exactly as in the player including devices potentially being disabled entirely while the Game View "
307 + "does not have focus. In this setting, no input from the Input System will be visible to EditorWindows.");
308 m_DefaultDeadzoneMinContent = new GUIContent("Default Deadzone Min", "Default 'min' value for Stick Deadzone and Axis Deadzone processors.");
309 m_DefaultDeadzoneMaxContent = new GUIContent("Default Deadzone Max", "Default 'max' value for Stick Deadzone and Axis Deadzone processors.");
310 m_DefaultButtonPressPointContent = new GUIContent("Default Button Press Point", "The default press point used for Button controls as well as for various interactions. For button controls which have analog physical inputs, this configures how far they need to be held down to be considered 'pressed'.");
311 m_ButtonReleaseThresholdContent = new GUIContent("Button Release Threshold", "Percent of press point at which a Button is considered released again. At 1, release points are identical to press points. At 0, a Button must be fully released before it can be pressed again.");
312 m_DefaultTapTimeContent = new GUIContent("Default Tap Time", "Default duration to be used for Tap and MultiTap interactions. Also used by by Touch screen devices to distinguish taps from to new touches.");
313 m_DefaultSlowTapTimeContent = new GUIContent("Default Slow Tap Time", "Default duration to be used for SlowTap interactions.");
314 m_DefaultHoldTimeContent = new GUIContent("Default Hold Time", "Default duration to be used for Hold interactions.");
315 m_TapRadiusContent = new GUIContent("Tap Radius", "Maximum distance between two finger taps on a touch screen device allowed for the system to consider this a tap of the same touch (as opposed to a new touch).");
316 m_MultiTapDelayTimeContent = new GUIContent("MultiTap Delay Time", "Default delay to be allowed between taps for MultiTap interactions. Also used by by touch devices to count multi taps.");
317 m_ShortcutKeysConsumeInputsContent = new GUIContent("Enable Input Consumption", "Actions are exclusively triggered and will consume/block other actions sharing the same input. E.g. when pressing the 'Shift+B' keys, the associated action would trigger but any action bound to just the 'B' key would be prevented from triggering at the same time.");
318
319 // Initialize ReorderableList for list of supported devices.
320 var supportedDevicesProperty = m_SettingsObject.FindProperty("m_SupportedDevices");
321 m_SupportedDevices = new ReorderableList(m_SettingsObject, supportedDevicesProperty)
322 {
323 drawHeaderCallback =
324 rect => { EditorGUI.LabelField(rect, m_SupportedDevicesText); },
325 onChangedCallback =
326 list => { Apply(); },
327 onAddDropdownCallback =
328 (rect, list) =>
329 {
330 var dropdown = new InputControlPickerDropdown(
331 new InputControlPickerState(),
332 path =>
333 {
334 ////REVIEW: Why are we converting from a layout into a plain string here instead of just using path strings in supportedDevices?
335 //// Why not just have InputSettings.supportedDevices be a list of paths?
336 var layoutName = InputControlPath.TryGetDeviceLayout(path) ?? path;
337 var existingIndex = m_Settings.supportedDevices.IndexOf(x => x == layoutName);
338 if (existingIndex != -1)
339 {
340 m_SupportedDevices.index = existingIndex;
341 return;
342 }
343 var numDevices = supportedDevicesProperty.arraySize;
344 supportedDevicesProperty.InsertArrayElementAtIndex(numDevices);
345 supportedDevicesProperty.GetArrayElementAtIndex(numDevices)
346 .stringValue = layoutName;
347 m_SupportedDevices.index = numDevices;
348 Apply();
349 },
350 mode: InputControlPicker.Mode.PickDevice);
351 dropdown.Show(rect);
352 },
353 drawElementCallback =
354 (rect, index, isActive, isFocused) =>
355 {
356 var layoutName = m_Settings.supportedDevices[index];
357 var icon = EditorInputControlLayoutCache.GetIconForLayout(layoutName);
358 if (icon != null)
359 {
360 var iconRect = rect;
361 iconRect.width = 20;
362 rect.x += 20;
363 rect.width -= 20;
364
365 GUI.Label(iconRect, icon);
366 }
367
368 EditorGUI.LabelField(rect, layoutName);
369 }
370 };
371
372 m_iOSProvider = new InputSettingsiOSProvider(m_SettingsObject);
373 }
374
375 private void Apply()
376 {
377 Debug.Assert(m_Settings != null);
378
379 m_SettingsObject.ApplyModifiedProperties();
380 m_SettingsObject.Update();
381 m_Settings.OnChange();
382 }
383
384 private void OnUndoRedo()
385 {
386 if (m_Settings != null && EditorUtility.GetDirtyCount(m_Settings) != m_SettingsDirtyCount)
387 m_Settings.OnChange();
388 InitializeWithCurrentSettingsIfNecessary();
389 }
390
391 private void OnSettingsChange()
392 {
393 InitializeWithCurrentSettingsIfNecessary();
394
395 ////REVIEW: leads to double-repaint when the settings change is initiated by us; problem?
396 Repaint();
397 }
398
399 /// <summary>
400 /// Find all <see cref="InputSettings"/> stored in assets in the current project.
401 /// </summary>
402 /// <returns>List of input settings in project.</returns>
403 private static string[] FindInputSettingsInProject()
404 {
405 var guids = AssetDatabase.FindAssets("t:InputSettings");
406 return guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).ToArray();
407 }
408
409 [SerializeField] private InputSettings m_Settings;
410 [SerializeField] private bool m_SettingsIsNotAnAsset;
411
412 [NonSerialized] private int m_SettingsDirtyCount;
413 [NonSerialized] private SerializedObject m_SettingsObject;
414 [NonSerialized] private SerializedProperty m_UpdateMode;
415 [NonSerialized] private SerializedProperty m_ScrollDeltaBehavior;
416 [NonSerialized] private SerializedProperty m_CompensateForScreenOrientation;
417 [NonSerialized] private SerializedProperty m_BackgroundBehavior;
418 [NonSerialized] private SerializedProperty m_EditorInputBehaviorInPlayMode;
419 [NonSerialized] private SerializedProperty m_DefaultDeadzoneMin;
420 [NonSerialized] private SerializedProperty m_DefaultDeadzoneMax;
421 [NonSerialized] private SerializedProperty m_DefaultButtonPressPoint;
422 [NonSerialized] private SerializedProperty m_ButtonReleaseThreshold;
423 [NonSerialized] private SerializedProperty m_DefaultTapTime;
424 [NonSerialized] private SerializedProperty m_DefaultSlowTapTime;
425 [NonSerialized] private SerializedProperty m_DefaultHoldTime;
426 [NonSerialized] private SerializedProperty m_TapRadius;
427 [NonSerialized] private SerializedProperty m_MultiTapDelayTime;
428 [NonSerialized] private SerializedProperty m_ShortcutKeysConsumeInputs;
429
430 [NonSerialized] private ReorderableList m_SupportedDevices;
431 [NonSerialized] private string[] m_AvailableInputSettingsAssets;
432 [NonSerialized] private GUIContent[] m_AvailableSettingsAssetsOptions;
433 [NonSerialized] private int m_CurrentSelectedInputSettingsAsset;
434
435 [NonSerialized] private GUIContent m_SupportedDevicesText = EditorGUIUtility.TrTextContent("Supported Devices");
436 [NonSerialized] private GUIStyle m_NewAssetButtonStyle;
437
438 private GUIContent m_UpdateModeContent;
439#if UNITY_INPUT_SYSTEM_PLATFORM_SCROLL_DELTA
440 private GUIContent m_ScrollDeltaBehaviorContent;
441#endif
442 private GUIContent m_CompensateForScreenOrientationContent;
443 private GUIContent m_BackgroundBehaviorContent;
444 private GUIContent m_EditorInputBehaviorInPlayModeContent;
445 private GUIContent m_DefaultDeadzoneMinContent;
446 private GUIContent m_DefaultDeadzoneMaxContent;
447 private GUIContent m_DefaultButtonPressPointContent;
448 private GUIContent m_ButtonReleaseThresholdContent;
449 private GUIContent m_DefaultTapTimeContent;
450 private GUIContent m_DefaultSlowTapTimeContent;
451 private GUIContent m_DefaultHoldTimeContent;
452 private GUIContent m_TapRadiusContent;
453 private GUIContent m_MultiTapDelayTimeContent;
454 private GUIContent m_ShortcutKeysConsumeInputsContent;
455
456 [NonSerialized] private InputSettingsiOSProvider m_iOSProvider;
457
458 private static InputSettingsProvider s_Instance;
459
460 internal static void ForceReload()
461 {
462 if (s_Instance != null)
463 {
464 // Force next OnGUI() to re-initialize.
465 s_Instance.m_Settings = null;
466
467 // Request repaint.
468 SettingsService.NotifySettingsProviderChanged();
469 }
470 }
471 }
472
473 [CustomEditor(typeof(InputSettings))]
474 internal class InputSettingsEditor : UnityEditor.Editor
475 {
476 public override void OnInspectorGUI()
477 {
478 EditorGUILayout.Space();
479
480 if (GUILayout.Button("Open Input Settings Window", GUILayout.Height(30)))
481 InputSettingsProvider.Open();
482
483 EditorGUILayout.Space();
484
485 InputAssetEditorUtils.DrawMakeActiveGui(InputSystem.settings, target as InputSettings,
486 target.name, "settings", (value) => InputSystem.settings = value);
487 }
488
489 protected override bool ShouldHideOpenButton()
490 {
491 return true;
492 }
493 }
494}
495#endif // UNITY_EDITOR