/// <summary> /// Shows the controller pop out window using the provided profile and serialized interaction mapping property /// </summary> /// <param name="profile"></param> /// <param name="interactionMappingProfiles"></param> public static void Show(MixedRealityControllerMappingProfile profile, SerializedProperty interactionMappingProfiles) { var handednessTitleText = profile.Handedness != Handedness.None ? $"{profile.Handedness} Hand " : string.Empty; if (window != null) { window.Close(); } if (profile.ControllerType?.Type == null) { Debug.LogError($"No controller type defined for {profile.name}"); return; } window = (ControllerPopupWindow)CreateInstance(typeof(ControllerPopupWindow)); window.currentControllerName = profile.ControllerType?.Type?.Name; window.currentControllerName = profile.ControllerType?.Type?.Name; window.titleContent = new GUIContent($"{window.currentControllerName} {handednessTitleText}Input Action Assignment"); window.controllerDataProviderProfile = profile; window.currentInteractionProfiles = interactionMappingProfiles; window.currentControllerTexture = ControllerMappingLibrary.GetControllerTexture(profile); isMouseInRects = new bool[interactionMappingProfiles.arraySize]; var asset = AssetDatabase.LoadAssetAtPath <TextAsset>(EditorWindowOptionsPath); if (asset.IsNull()) { var empty = new ControllerInputActionOptions { Controllers = new List <ControllerInputActionOption> { new ControllerInputActionOption { Controller = null, Handedness = Handedness.None, InputLabelPositions = new[] { new Vector2(0, 0) }, IsLabelFlipped = new [] { false } } } }; File.WriteAllText(Path.GetFullPath(EditorWindowOptionsPath), JsonUtility.ToJson(empty, true)); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); } else { controllerInputActionOptions = JsonUtility.FromJson <ControllerInputActionOptions>(asset.text); // if the controller option doesn't exist, then make a new one. if (!controllerInputActionOptions.Controllers.Any(option => option.Controller == window.currentControllerName && option.Handedness == window.Handedness)) { var newOption = new ControllerInputActionOption { Controller = window.currentControllerName, Handedness = window.Handedness, InputLabelPositions = new Vector2[interactionMappingProfiles.arraySize], IsLabelFlipped = new bool[interactionMappingProfiles.arraySize] }; controllerInputActionOptions.Controllers.Add(newOption); } window.currentControllerOption = controllerInputActionOptions.Controllers.FirstOrDefault(option => option.Controller == window.currentControllerName && option.Handedness == window.Handedness); if (window.currentControllerOption.IsLabelFlipped == null) { window.currentControllerOption.IsLabelFlipped = new bool[interactionMappingProfiles.arraySize]; } if (window.currentControllerOption.InputLabelPositions == null) { window.currentControllerOption.InputLabelPositions = new Vector2[interactionMappingProfiles.arraySize]; } } var windowSize = new Vector2(window.IsCustomController || window.currentControllerTexture == null ? 896f : 768f, 512f); window.ShowUtility(); window.maxSize = windowSize; window.minSize = windowSize; window.CenterOnMainWin(); }
private void RenderInteractionList(SerializedProperty interactionList, bool useCustomInteractionMapping) { GUI.enabled = !isLocked; if (interactionList == null) { Debug.LogError("No interaction list found!"); Close(); return; } bool noInteractions = interactionList.arraySize == 0; if (!useCustomInteractionMapping) { if (currentControllerOption.IsLabelFlipped == null || currentControllerOption.IsLabelFlipped.Length != interactionList.arraySize) { var newArray = new bool[interactionList.arraySize]; for (int i = 0; i < currentControllerOption.IsLabelFlipped?.Length; i++) { newArray[i] = currentControllerOption.IsLabelFlipped[i]; } currentControllerOption.IsLabelFlipped = newArray; } if (currentControllerOption.InputLabelPositions == null || currentControllerOption.InputLabelPositions.Length != interactionList.arraySize) { var newArray = new Vector2[interactionList.arraySize].InitialiseArray(new Vector2(0, 25)); for (int i = 0; i < currentControllerOption.InputLabelPositions?.Length; i++) { newArray[i] = currentControllerOption.InputLabelPositions[i]; } currentControllerOption.InputLabelPositions = newArray; } } GUILayout.BeginVertical(); if (useCustomInteractionMapping) { useCustomInteractionMapping = !(currentControllerType == SupportedControllerType.WindowsMixedReality && currentHandedness == Handedness.None); } if (useCustomInteractionMapping) { horizontalScrollPosition = EditorGUILayout.BeginScrollView(horizontalScrollPosition, false, false, GUILayout.ExpandWidth(true), GUILayout.ExpandWidth(true)); } if (useCustomInteractionMapping) { if (GUILayout.Button(InteractionAddButtonContent)) { interactionList.arraySize += 1; var interaction = interactionList.GetArrayElementAtIndex(interactionList.arraySize - 1); var axisType = interaction.FindPropertyRelative("axisType"); axisType.enumValueIndex = 0; var inputType = interaction.FindPropertyRelative("inputType"); inputType.enumValueIndex = 0; var action = interaction.FindPropertyRelative("inputAction"); var actionId = action.FindPropertyRelative("id"); var actionDescription = action.FindPropertyRelative("description"); actionDescription.stringValue = "None"; actionId.intValue = 0; } if (noInteractions) { EditorGUILayout.HelpBox("Create an Interaction Mapping.", MessageType.Warning); EditorGUILayout.EndScrollView(); GUILayout.EndVertical(); return; } } else if (EnableWysiwyg) { EditorGUI.BeginChangeCheck(); editInputActionPositions = EditorGUILayout.Toggle("Edit Input Action Positions", editInputActionPositions); if (EditorGUI.EndChangeCheck()) { if (!editInputActionPositions) { File.WriteAllText(Path.GetFullPath(EditorWindowOptionsPath), JsonUtility.ToJson(controllerInputActionOptions, true)); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); } else { if (!controllerInputActionOptions.Controllers.Any(option => option.Controller == currentControllerType && option.Handedness == currentHandedness)) { currentControllerOption = new ControllerInputActionOption { Controller = currentControllerType, Handedness = currentHandedness, InputLabelPositions = new Vector2[currentInteractionList.arraySize], IsLabelFlipped = new bool[currentInteractionList.arraySize] }; controllerInputActionOptions.Controllers.Add(currentControllerOption); isMouseInRects = new bool[currentInteractionList.arraySize]; if (controllerInputActionOptions.Controllers.Any(option => option.Controller == SupportedControllerType.None)) { controllerInputActionOptions.Controllers.Remove( controllerInputActionOptions.Controllers.Find(option => option.Controller == SupportedControllerType.None)); } AssetDatabase.DeleteAsset(EditorWindowOptionsPath); File.WriteAllText(Path.GetFullPath(EditorWindowOptionsPath), JsonUtility.ToJson(controllerInputActionOptions, true)); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); } } } } GUILayout.BeginHorizontal(); if (useCustomInteractionMapping) { EditorGUILayout.LabelField("Id", GUILayout.Width(32f)); EditorGUIUtility.labelWidth = 24f; EditorGUIUtility.fieldWidth = 24f; EditorGUILayout.LabelField(ControllerInputTypeContent, GUILayout.Width(InputActionLabelWidth)); EditorGUILayout.LabelField(AxisTypeContent, GUILayout.Width(InputActionLabelWidth)); EditorGUILayout.LabelField(ActionContent, GUILayout.Width(InputActionLabelWidth)); EditorGUILayout.LabelField(KeyCodeContent, GUILayout.Width(InputActionLabelWidth)); EditorGUILayout.LabelField(XAxisContent, GUILayout.Width(InputActionLabelWidth)); EditorGUILayout.LabelField(YAxisContent, GUILayout.Width(InputActionLabelWidth)); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(string.Empty, GUILayout.Width(24f)); EditorGUIUtility.labelWidth = defaultLabelWidth; EditorGUIUtility.fieldWidth = defaultFieldWidth; } GUILayout.EndHorizontal(); for (int i = 0; i < interactionList.arraySize; i++) { EditorGUILayout.BeginHorizontal(); var interaction = interactionList.GetArrayElementAtIndex(i); if (useCustomInteractionMapping) { EditorGUILayout.LabelField($"{i + 1}", GUILayout.Width(32f)); var inputType = interaction.FindPropertyRelative("inputType"); EditorGUILayout.PropertyField(inputType, GUIContent.none, GUILayout.Width(InputActionLabelWidth)); var axisType = interaction.FindPropertyRelative("axisType"); EditorGUILayout.PropertyField(axisType, GUIContent.none, GUILayout.Width(InputActionLabelWidth)); var invertXAxis = interaction.FindPropertyRelative("invertXAxis"); var invertYAxis = interaction.FindPropertyRelative("invertYAxis"); var interactionAxisConstraint = interaction.FindPropertyRelative("axisType"); var action = interaction.FindPropertyRelative("inputAction"); var actionId = action.FindPropertyRelative("id"); var actionDescription = action.FindPropertyRelative("description"); var actionConstraint = action.FindPropertyRelative("axisConstraint"); GUIContent[] labels; int[] ids; switch ((AxisType)interactionAxisConstraint.intValue) { // case AxisType.None: default: labels = actionLabels; ids = actionIds; break; case AxisType.Raw: labels = rawActionLabels; ids = rawActionIds; break; case AxisType.Digital: labels = digitalActionLabels; ids = digitalActionIds; break; case AxisType.SingleAxis: labels = singleAxisActionLabels; ids = singleAxisActionIds; break; case AxisType.DualAxis: labels = dualAxisActionLabels; ids = dualAxisActionIds; break; case AxisType.ThreeDofPosition: labels = threeDofPositionActionLabels; ids = threeDofPositionActionIds; break; case AxisType.ThreeDofRotation: labels = threeDofRotationActionLabels; ids = threeDofRotationActionIds; break; case AxisType.SixDof: labels = sixDofActionLabels; ids = sixDofActionIds; break; } EditorGUI.BeginChangeCheck(); actionId.intValue = EditorGUILayout.IntPopup(GUIContent.none, actionId.intValue, labels, ids, GUILayout.Width(InputActionLabelWidth)); if (EditorGUI.EndChangeCheck()) { var inputAction = actionId.intValue == 0 ? MixedRealityInputAction.None : inputSystemProfile.InputActionsProfile.InputActions[actionId.intValue - 1]; actionDescription.stringValue = inputAction.Description; actionConstraint.enumValueIndex = (int)inputAction.AxisConstraint; } if ((AxisType)axisType.intValue == AxisType.Digital) { var keyCode = interaction.FindPropertyRelative("keyCode"); EditorGUILayout.PropertyField(keyCode, GUIContent.none, GUILayout.Width(InputActionLabelWidth)); } else { if ((AxisType)axisType.intValue == AxisType.DualAxis) { EditorGUIUtility.labelWidth = InputActionLabelWidth * 0.5f; EditorGUIUtility.fieldWidth = InputActionLabelWidth * 0.5f; int currentAxisSetting = 0; if (invertXAxis.boolValue) { currentAxisSetting += 1; } if (invertYAxis.boolValue) { currentAxisSetting += 2; } EditorGUI.BeginChangeCheck(); currentAxisSetting = EditorGUILayout.IntPopup(InvertContent, currentAxisSetting, InvertAxisContent, InvertAxisValues, GUILayout.Width(InputActionLabelWidth)); if (EditorGUI.EndChangeCheck()) { switch (currentAxisSetting) { case 0: invertXAxis.boolValue = false; invertYAxis.boolValue = false; break; case 1: invertXAxis.boolValue = true; invertYAxis.boolValue = false; break; case 2: invertXAxis.boolValue = false; invertYAxis.boolValue = true; break; case 3: invertXAxis.boolValue = true; invertYAxis.boolValue = true; break; } } EditorGUIUtility.labelWidth = defaultLabelWidth; EditorGUIUtility.fieldWidth = defaultFieldWidth; } else if ((AxisType)axisType.intValue == AxisType.SingleAxis) { invertXAxis.boolValue = EditorGUILayout.ToggleLeft("Invert X", invertXAxis.boolValue, GUILayout.Width(InputActionLabelWidth)); EditorGUIUtility.labelWidth = defaultLabelWidth; } else { EditorGUILayout.LabelField(GUIContent.none, GUILayout.Width(InputActionLabelWidth)); } } if ((AxisType)axisType.intValue == AxisType.SingleAxis || (AxisType)axisType.intValue == AxisType.DualAxis) { var axisCodeX = interaction.FindPropertyRelative("axisCodeX"); RenderAxisPopup(axisCodeX, InputActionLabelWidth); } else { EditorGUILayout.LabelField(GUIContent.none, GUILayout.Width(InputActionLabelWidth)); } if ((AxisType)axisType.intValue == AxisType.DualAxis) { var axisCodeY = interaction.FindPropertyRelative("axisCodeY"); RenderAxisPopup(axisCodeY, InputActionLabelWidth); } else { EditorGUILayout.LabelField(GUIContent.none, GUILayout.Width(InputActionLabelWidth)); } if (GUILayout.Button(InteractionMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.ExpandWidth(true))) { interactionList.DeleteArrayElementAtIndex(i); } } else { var interactionDescription = interaction.FindPropertyRelative("description"); var interactionAxisConstraint = interaction.FindPropertyRelative("axisType"); var action = interaction.FindPropertyRelative("inputAction"); var actionId = action.FindPropertyRelative("id"); var actionDescription = action.FindPropertyRelative("description"); var actionConstraint = action.FindPropertyRelative("axisConstraint"); var invertXAxis = interaction.FindPropertyRelative("invertXAxis"); var invertYAxis = interaction.FindPropertyRelative("invertYAxis"); int[] ids; GUIContent[] labels; var axisConstraint = (AxisType)interactionAxisConstraint.intValue; switch (axisConstraint) { // case AxisType.None: default: labels = actionLabels; ids = actionIds; break; case AxisType.Raw: labels = rawActionLabels; ids = rawActionIds; break; case AxisType.Digital: labels = digitalActionLabels; ids = digitalActionIds; break; case AxisType.SingleAxis: labels = singleAxisActionLabels; ids = singleAxisActionIds; break; case AxisType.DualAxis: labels = dualAxisActionLabels; ids = dualAxisActionIds; break; case AxisType.ThreeDofPosition: labels = threeDofPositionActionLabels; ids = threeDofPositionActionIds; break; case AxisType.ThreeDofRotation: labels = threeDofRotationActionLabels; ids = threeDofRotationActionIds; break; case AxisType.SixDof: labels = sixDofActionLabels; ids = sixDofActionIds; break; } EditorGUI.BeginChangeCheck(); if (currentControllerTexture == null) { bool skip = false; var description = interactionDescription.stringValue; if (currentControllerType == SupportedControllerType.WindowsMixedReality && currentHandedness == Handedness.None) { switch (description) { case "Grip Press": case "Trigger Position": case "Trigger Touched": case "Touchpad Position": case "Touchpad Touch": case "Touchpad Press": case "Menu Press": case "Thumbstick Position": case "Thumbstick Press": skip = true; break; case "Trigger Press (Select)": description = "Air Tap (Select)"; break; } } if (!skip) { var currentLabelWidth = EditorGUIUtility.labelWidth; if (axisConstraint == AxisType.SingleAxis || axisConstraint == AxisType.DualAxis) { EditorGUIUtility.labelWidth = 12f; EditorGUILayout.LabelField("Invert:"); invertXAxis.boolValue = EditorGUILayout.Toggle("X", invertXAxis.boolValue); } if (axisConstraint == AxisType.DualAxis) { invertYAxis.boolValue = EditorGUILayout.Toggle("Y", invertYAxis.boolValue); } EditorGUIUtility.labelWidth = currentLabelWidth; actionId.intValue = EditorGUILayout.IntPopup(GUIContent.none, actionId.intValue, labels, ids, GUILayout.Width(80f)); EditorGUILayout.LabelField(description, GUILayout.ExpandWidth(true)); GUILayout.FlexibleSpace(); } } else { var flipped = currentControllerOption.IsLabelFlipped[i]; var rectPosition = currentControllerOption.InputLabelPositions[i]; var rectSize = InputActionLabelPosition + InputActionDropdownPosition + new Vector2(flipped ? 0f : 8f, EditorGUIUtility.singleLineHeight); GUI.Box(new Rect(rectPosition, rectSize), GUIContent.none, EditorGUIUtility.isProSkin ? "ObjectPickerBackground" : "ObjectPickerResultsEven"); var offset = flipped ? InputActionLabelPosition : Vector2.zero; var popupRect = new Rect(rectPosition + offset, new Vector2(InputActionDropdownPosition.x, EditorGUIUtility.singleLineHeight)); actionId.intValue = EditorGUI.IntPopup(popupRect, actionId.intValue, labels, ids); offset = flipped ? Vector2.zero : InputActionDropdownPosition; var labelRect = new Rect(rectPosition + offset, new Vector2(InputActionLabelPosition.x, EditorGUIUtility.singleLineHeight)); EditorGUI.LabelField(labelRect, interactionDescription.stringValue, flipped ? flippedLabelStyle : EditorStyles.label); if (!editInputActionPositions) { offset = flipped ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace : Vector2.zero; if (axisConstraint == AxisType.SingleAxis || axisConstraint == AxisType.DualAxis) { if (!flipped) { if (axisConstraint == AxisType.DualAxis) { offset += new Vector2(-112f, 0f); } else { offset += new Vector2(-76f, 0f); } } var boxSize = axisConstraint == AxisType.DualAxis ? new Vector2(112f, EditorGUIUtility.singleLineHeight) : new Vector2(76f, EditorGUIUtility.singleLineHeight); GUI.Box(new Rect(rectPosition + offset, boxSize), GUIContent.none, EditorGUIUtility.isProSkin ? "ObjectPickerBackground" : "ObjectPickerResultsEven"); labelRect = new Rect(rectPosition + offset, new Vector2(48f, EditorGUIUtility.singleLineHeight)); EditorGUI.LabelField(labelRect, "Invert X", flipped ? flippedLabelStyle : EditorStyles.label); offset += new Vector2(52f, 0f); var toggleXAxisRect = new Rect(rectPosition + offset, new Vector2(12f, EditorGUIUtility.singleLineHeight)); invertXAxis.boolValue = EditorGUI.Toggle(toggleXAxisRect, invertXAxis.boolValue); } if (axisConstraint == AxisType.DualAxis) { offset += new Vector2(24f, 0f); labelRect = new Rect(rectPosition + offset, new Vector2(8f, EditorGUIUtility.singleLineHeight)); EditorGUI.LabelField(labelRect, "Y", flipped ? flippedLabelStyle : EditorStyles.label); offset += new Vector2(12f, 0f); var toggleYAxisRect = new Rect(rectPosition + offset, new Vector2(12f, EditorGUIUtility.singleLineHeight)); invertYAxis.boolValue = EditorGUI.Toggle(toggleYAxisRect, invertYAxis.boolValue); } } else { offset = flipped ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace : InputActionFlipTogglePosition; var toggleRect = new Rect(rectPosition + offset, new Vector2(-InputActionFlipTogglePosition.x, EditorGUIUtility.singleLineHeight)); EditorGUI.BeginChangeCheck(); currentControllerOption.IsLabelFlipped[i] = EditorGUI.Toggle(toggleRect, flipped); if (EditorGUI.EndChangeCheck()) { if (currentControllerOption.IsLabelFlipped[i]) { currentControllerOption.InputLabelPositions[i] -= InputActionLabelPosition; } else { currentControllerOption.InputLabelPositions[i] += InputActionLabelPosition; } } if (!isMouseInRects.Any(value => value) || isMouseInRects[i]) { switch (Event.current.type) { case EventType.MouseDrag when labelRect.Contains(Event.current.mousePosition) && !isMouseInRects[i]: isMouseInRects[i] = true; mouseDragOffset = Event.current.mousePosition - currentControllerOption.InputLabelPositions[i]; break; case EventType.Repaint when isMouseInRects[i]: