public void Init(Rect buttonRect) { var screenPoint = GUIUtility.GUIToScreenPoint(new Vector2(buttonRect.x, buttonRect.y)); m_ButtonRectScreenPos.x = screenPoint.x; m_ButtonRectScreenPos.y = screenPoint.y; if (m_State == null) { m_State = new AdvancedDropdownState(); } if (m_DataSource == null) { m_DataSource = new MultiLevelDataSource(); } if (m_Gui == null) { m_Gui = new AdvancedDropdownGUI(); } m_Gui.state = m_State; m_Gui.Init(); // Has to be done before calling Show / ShowWithMode screenPoint = GUIUtility.GUIToScreenPoint(new Vector2(buttonRect.x, buttonRect.y)); buttonRect.x = screenPoint.x; buttonRect.y = screenPoint.y; Vector2 requiredDropdownSize; OnDirtyList(); m_CurrentlyRenderedTree = hasSearch ? m_DataSource.searchTree : m_DataSource.mainTree; ShowAsDropDown(buttonRect, CalculateWindowSize(m_ButtonRectScreenPos, out requiredDropdownSize)); // If the dropdown is as height as the screen height, give it some margin if (position.height < requiredDropdownSize.y) { var pos = position; pos.y += 5; pos.height -= 10; position = pos; } if (setInitialSelectionPosition) { m_InitialSelectionPosition = m_Gui.GetSelectionHeight(m_DataSource, buttonRect); } wantsMouseMove = true; SetSelectionFromState(); }
public InputBindingPropertiesView(SerializedProperty bindingProperty, Action onChange, AdvancedDropdownState controlPickerState, InputActionWindowToolbar toolbar, string expectedControlLayout = null) { m_ControlPickerState = controlPickerState; m_BindingProperty = bindingProperty; m_OnChange = onChange; m_InteractionsProperty = bindingProperty.FindPropertyRelative("m_Interactions"); m_ProcessorsProperty = bindingProperty.FindPropertyRelative("m_Processors"); m_GroupsProperty = bindingProperty.FindPropertyRelative("m_Groups"); m_PathProperty = bindingProperty.FindPropertyRelative("m_Path"); m_InteractionsList = new InteractionsReorderableReorderableList(m_InteractionsProperty, OnInteractionsModified); m_ProcessorsList = new ProcessorsReorderableReorderableList(m_ProcessorsProperty, OnProcessorsModified); m_Toolbar = toolbar; if (m_Toolbar != null) { m_ControlSchemes = toolbar.controlSchemes; } m_BindingGroups = m_GroupsProperty.stringValue.Split(InputBinding.kSeparator).ToList(); m_ExpectedControlLayout = expectedControlLayout; }
private void InitializeTrees() { m_ActionMapsTree = ActionMapsTree.CreateFromSerializedObject(Apply, m_ActionAssetManager.serializedObject, ref m_ActionMapsTreeState); m_ActionMapsTree.OnSelectionChanged = OnActionMapSelection; m_ActionMapsTree.OnContextClick = m_ContextMenu.OnActionMapContextClick; m_ActionsTree = ActionsTree.CreateFromSerializedObject(Apply, ref m_ActionsTreeState); m_ActionsTree.OnSelectionChanged = OnActionSelection; m_ActionsTree.OnContextClick = m_ContextMenu.OnActionsContextClick; m_ActionsTree.OnRowGUI = OnActionRowGUI; m_InputActionWindowToolbar.OnSearchChanged = m_ActionsTree.SetNameFilter; m_InputActionWindowToolbar.OnSchemeChanged = a => { if (a == null) { m_ActionsTree.SetSchemeBindingGroupFilter(null); return; } var group = m_ActionAssetManager.m_AssetObjectForEditing.GetControlScheme(a).bindingGroup; m_ActionsTree.SetSchemeBindingGroupFilter(group); }; m_InputActionWindowToolbar.OnDeviceChanged = m_ActionsTree.SetDeviceFilter; m_ActionsTree.SetNameFilter(m_InputActionWindowToolbar.nameFilter); if (m_InputActionWindowToolbar.selectedControlSchemeName != null) { var group = m_ActionAssetManager.m_AssetObjectForEditing.GetControlScheme(m_InputActionWindowToolbar.selectedControlSchemeName).bindingGroup; m_ActionsTree.SetSchemeBindingGroupFilter(group); } m_ActionsTree.SetDeviceFilter(m_InputActionWindowToolbar.selectedDevice); m_CopyPasteUtility = new CopyPasteUtility(Apply, m_ActionMapsTree, m_ActionsTree, m_ActionAssetManager.serializedObject); if (m_PickerTreeViewState == null) { m_PickerTreeViewState = new AdvancedDropdownState(); } }
/// <summary> /// Grab <see cref="InputSystem.settings"/> and set it up for editing. /// </summary> private void InitializeWithCurrentSettings() { // Find the set of available assets in the project. m_AvailableInputSettingsAssets = FindInputSettingsInProject(); // See which is the active one. m_Settings = InputSystem.settings; var currentSettingsPath = AssetDatabase.GetAssetPath(m_Settings); if (string.IsNullOrEmpty(currentSettingsPath)) { // The current settings aren't coming from an asset. These won't be editable // in the UI but we still have to show something. m_CurrentSelectedInputSettingsAsset = ArrayHelpers.Append(ref m_AvailableInputSettingsAssets, "<No Asset>"); EditorBuildSettings.RemoveConfigObject(kEditorBuildSettingsConfigKey); } else { m_CurrentSelectedInputSettingsAsset = ArrayHelpers.IndexOf(m_AvailableInputSettingsAssets, currentSettingsPath); if (m_CurrentSelectedInputSettingsAsset == -1) { // This is odd and shouldn't happen. Solve by just adding the path to the list. m_CurrentSelectedInputSettingsAsset = ArrayHelpers.Append(ref m_AvailableInputSettingsAssets, currentSettingsPath); } ////REVIEW: should we store this by platform? EditorBuildSettings.AddConfigObject(kEditorBuildSettingsConfigKey, m_Settings, true); } // Refresh the list of assets we display in the UI. m_AvailableSettingsAssetsOptions = new GUIContent[m_AvailableInputSettingsAssets.Length]; for (var i = 0; i < m_AvailableInputSettingsAssets.Length; ++i) { var name = m_AvailableInputSettingsAssets[i]; if (name.StartsWith("Assets/")) { name = name.Substring("Assets/".Length); } if (name.EndsWith(".asset")) { name = name.Substring(0, name.Length - ".asset".Length); } if (name.EndsWith(".inputsettings")) { name = name.Substring(0, name.Length - ".inputsettings".Length); } m_AvailableSettingsAssetsOptions[i] = new GUIContent(name); } // Look up properties. m_SettingsObject = new SerializedObject(m_Settings); m_UpdateMode = m_SettingsObject.FindProperty("m_UpdateMode"); m_ActionUpdateMode = m_SettingsObject.FindProperty("m_ActionUpdateMode"); m_TimesliceEvents = m_SettingsObject.FindProperty("m_TimesliceEvents"); m_RunInBackground = m_SettingsObject.FindProperty("m_RunInBackground"); m_CompensateForScreenOrientation = m_SettingsObject.FindProperty("m_CompensateForScreenOrientation"); m_FilterNoiseOnCurrent = m_SettingsObject.FindProperty("m_FilterNoiseOnCurrent"); m_DefaultDeadzoneMin = m_SettingsObject.FindProperty("m_DefaultDeadzoneMin"); m_DefaultDeadzoneMax = m_SettingsObject.FindProperty("m_DefaultDeadzoneMax"); m_DefaultButtonPressPoint = m_SettingsObject.FindProperty("m_DefaultButtonPressPoint"); m_DefaultTapTime = m_SettingsObject.FindProperty("m_DefaultTapTime"); m_DefaultSlowTapTime = m_SettingsObject.FindProperty("m_DefaultSlowTapTime"); m_DefaultHoldTime = m_SettingsObject.FindProperty("m_DefaultHoldTime"); // Initialize ReorderableList for list of supported devices. var supportedDevicesProperty = m_SettingsObject.FindProperty("m_SupportedDevices"); m_SupportedDevices = new ReorderableList(m_SettingsObject, supportedDevicesProperty) { drawHeaderCallback = rect => { EditorGUI.LabelField(rect, m_SupportedDevicesText); }, onChangedCallback = list => { Apply(); }, onAddDropdownCallback = (rect, list) => { var state = new AdvancedDropdownState(); var dropdown = new InputControlPickerDropdown(state, path => { var layoutName = InputControlPath.TryGetDeviceLayout(path) ?? path; var numDevices = supportedDevicesProperty.arraySize; supportedDevicesProperty.InsertArrayElementAtIndex(numDevices); supportedDevicesProperty.GetArrayElementAtIndex(numDevices) .stringValue = layoutName; Apply(); }, InputControlPickerDropdown.Mode.PickDevice); dropdown.Show(rect); }, drawElementCallback = (rect, index, isActive, isFocused) => { var layoutName = m_Settings.supportedDevices[index]; var icon = EditorInputControlLayoutCache.GetIconForLayout(layoutName); if (icon != null) { var iconRect = rect; iconRect.width = 20; rect.x += 20; rect.width -= 20; GUI.Label(iconRect, icon); } EditorGUI.LabelField(rect, m_Settings.supportedDevices[index]); } }; }
public AdvancedDropdown(AdvancedDropdownState state) { m_State = state; }
private void ShowInputControlPicker(Rect rect, SerializedProperty pathProperty, AdvancedDropdownState pickerState, Action <SerializedProperty> onPickCallback) { if (m_InputControlPickerDropdown == null) { m_InputControlPickerDropdown = new InputControlPickerDropdown(pickerState, pathProperty, onPickCallback); } if (m_Toolbar != null) { if (m_Toolbar.selectedDevice != null) { m_InputControlPickerDropdown.SetDeviceFilter(new[] { m_Toolbar.selectedDevice }); } else { m_InputControlPickerDropdown.SetDeviceFilter(m_Toolbar.allDevices); } if (m_ExpectedControlLayout != null) { m_InputControlPickerDropdown.SetExpectedControlLayoutFilter(m_ExpectedControlLayout); } } m_InputControlPickerDropdown.Show(rect); }
////TODO: interactive picker; if more than one control makes it through the filters, present list of //// candidates for user to choose from ////REVIEW: refactor this out of here; this should be a public API that allows anyone to have an inspector field to select a control binding internal void DrawBindingGUI(SerializedProperty pathProperty, ref bool manualPathEditMode, AdvancedDropdownState pickerState, Action <SerializedProperty> onModified) { EditorGUILayout.BeginHorizontal(); var lineRect = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight); var labelRect = lineRect; labelRect.width = 60; EditorGUI.LabelField(labelRect, s_BindingGui); lineRect.x += 65; lineRect.width -= 65; var bindingTextRect = lineRect; var editButtonRect = lineRect; var interactivePickButtonRect = lineRect; bindingTextRect.width -= 42; editButtonRect.x += bindingTextRect.width + 21; editButtonRect.width = 21; editButtonRect.height = 15; interactivePickButtonRect.x += bindingTextRect.width; interactivePickButtonRect.width = 21; interactivePickButtonRect.height = 15; var path = pathProperty.stringValue; ////TODO: this should be cached; generates needless GC churn var displayName = InputControlPath.ToHumanReadableString(path); if (manualPathEditMode || (!string.IsNullOrEmpty(path) && string.IsNullOrEmpty(displayName))) { EditorGUI.BeginChangeCheck(); path = EditorGUI.DelayedTextField(bindingTextRect, path); if (EditorGUI.EndChangeCheck()) { pathProperty.stringValue = path; pathProperty.serializedObject.ApplyModifiedProperties(); onModified(pathProperty); } DrawInteractivePickButton(interactivePickButtonRect, pathProperty, onModified); if (GUI.Button(editButtonRect, "˅")) { bindingTextRect.x += editButtonRect.width; ShowInputControlPicker(bindingTextRect, pathProperty, pickerState, onModified); } } else { // Dropdown that shows binding text and allows opening control picker. if (EditorGUI.DropdownButton(bindingTextRect, new GUIContent(displayName), FocusType.Keyboard)) { ////TODO: pass expectedControlLayout filter on to control picker ////TODO: for bindings that are part of composites, use the layout information from the [InputControl] attribute on the field ShowInputControlPicker(bindingTextRect, pathProperty, pickerState, onModified); } // Button to bind interactively. DrawInteractivePickButton(interactivePickButtonRect, pathProperty, onModified); // Button that switches binding into text edit mode. if (GUI.Button(editButtonRect, "...", EditorStyles.miniButton)) { manualPathEditMode = true; } } EditorGUILayout.EndHorizontal(); }