private void RenderInteractionList()

in PC Holographic Remoting/Assets/MRTK/Core/Inspectors/ControllerPopupWindow.cs [286:703]


        private void RenderInteractionList(SerializedProperty interactionList, bool useCustomInteractionMapping)
        {
            if (interactionList == null) { throw new Exception(); }

            bool noInteractions = interactionList.arraySize == 0;

            if (currentControllerOption != null && (currentControllerOption.IsLabelFlipped == null || currentControllerOption.IsLabelFlipped.Length != interactionList.arraySize))
            {
                currentControllerOption.IsLabelFlipped = new bool[interactionList.arraySize];
            }

            GUILayout.BeginVertical();

            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())
                {
                    string editorWindowOptionsPath = ResolveEditorWindowOptionsPath();
                    if (!editInputActionPositions)
                    {
                        File.WriteAllText(editorWindowOptionsPath, JsonUtility.ToJson(controllerInputActionOptions, true));
                    }
                    else
                    {
                        if (!controllerInputActionOptions.Controllers.Any(
                            option => option.Controller == currentControllerMapping.SupportedControllerType && option.Handedness == currentControllerMapping.Handedness))
                        {
                            currentControllerOption = new ControllerInputActionOption
                            {
                                Controller = currentControllerMapping.SupportedControllerType,
                                Handedness = currentControllerMapping.Handedness,
                                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 == 0))
                            {
                                controllerInputActionOptions.Controllers.Remove(
                                    controllerInputActionOptions.Controllers.Find(option =>
                                        option.Controller == 0));
                            }

                            File.WriteAllText(editorWindowOptionsPath, JsonUtility.ToJson(controllerInputActionOptions, true));
                        }
                    }
                }
            }

            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++)
            {
                using (new EditorGUILayout.HorizontalScope())
                {
                    SerializedProperty 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)
                        {
                            default:
                            case AxisType.None:
                                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 : MixedRealityToolkit.Instance.ActiveProfile.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");

                        GUIContent[] labels;
                        int[] ids;

                        switch ((AxisType)interactionAxisConstraint.intValue)
                        {
                            default:
                            case AxisType.None:
                                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 (currentControllerOption == null || currentControllerTexture == null)
                        {
                            bool skip = false;
                            var description = interactionDescription.stringValue;
                            if (currentControllerMapping.SupportedControllerType == SupportedControllerType.GGVHand
                                && currentControllerMapping.Handedness == Handedness.None)
                            {
                                if (description != "Select")
                                {
                                    skip = true;
                                }
                            }

                            if (!skip)
                            {
                                actionId.intValue = EditorGUILayout.IntPopup(GUIContent.none, actionId.intValue, labels, ids, GUILayout.Width(80f));
                                EditorGUILayout.LabelField(description, GUILayout.ExpandWidth(true));
                            }
                        }
                        else
                        {
                            var rectPosition = currentControllerOption.InputLabelPositions[i];
                            var rectSize = InputActionLabelPosition + InputActionDropdownPosition + new Vector2(currentControllerOption.IsLabelFlipped[i] ? 0f : 8f, EditorGUIUtility.singleLineHeight);
                            GUI.Box(new Rect(rectPosition, rectSize), GUIContent.none, EditorGUIUtility.isProSkin ? "ObjectPickerBackground" : "ObjectPickerResultsEven");
                            var offset = currentControllerOption.IsLabelFlipped[i] ? 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 = currentControllerOption.IsLabelFlipped[i] ? Vector2.zero : InputActionDropdownPosition;
                            var labelRect = new Rect(rectPosition + offset, new Vector2(InputActionLabelPosition.x, EditorGUIUtility.singleLineHeight));
                            EditorGUI.LabelField(labelRect, interactionDescription.stringValue, currentControllerOption.IsLabelFlipped[i] ? flippedLabelStyle : EditorStyles.label);

                            if (editInputActionPositions)
                            {
                                offset = currentControllerOption.IsLabelFlipped[i] ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace : InputActionFlipTogglePosition;
                                var toggleRect = new Rect(rectPosition + offset, new Vector2(-InputActionFlipTogglePosition.x, EditorGUIUtility.singleLineHeight));

                                EditorGUI.BeginChangeCheck();
                                currentControllerOption.IsLabelFlipped[i] = EditorGUI.Toggle(toggleRect, currentControllerOption.IsLabelFlipped[i]);

                                if (EditorGUI.EndChangeCheck())
                                {
                                    if (currentControllerOption.IsLabelFlipped[i])
                                    {
                                        currentControllerOption.InputLabelPositions[i] -= InputActionLabelPosition;
                                    }
                                    else
                                    {
                                        currentControllerOption.InputLabelPositions[i] += InputActionLabelPosition;
                                    }
                                }

                                if (!isMouseInRects.Any(value => value) || isMouseInRects[i])
                                {
                                    if (Event.current.type == EventType.MouseDrag && labelRect.Contains(Event.current.mousePosition) && !isMouseInRects[i])
                                    {
                                        isMouseInRects[i] = true;
                                        mouseDragOffset = Event.current.mousePosition - currentControllerOption.InputLabelPositions[i];
                                    }
                                    else if (Event.current.type == EventType.Repaint && isMouseInRects[i])
                                    {
                                        currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset;
                                    }
                                    else if (Event.current.type == EventType.DragUpdated && isMouseInRects[i])
                                    {
                                        currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset;
                                    }
                                    else if (Event.current.type == EventType.MouseUp && isMouseInRects[i])
                                    {
                                        currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset;
                                        mouseDragOffset = Vector2.zero;
                                        isMouseInRects[i] = false;
                                    }
                                }
                            }
                        }

                        if (EditorGUI.EndChangeCheck())
                        {
                            MixedRealityInputAction inputAction = actionId.intValue == 0 ?
                                MixedRealityInputAction.None :
                                MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.InputActionsProfile.InputActions[actionId.intValue - 1];
                            actionId.intValue = (int)inputAction.Id;
                            actionDescription.stringValue = inputAction.Description;
                            actionConstraint.enumValueIndex = (int)inputAction.AxisConstraint;
                            interactionList.serializedObject.ApplyModifiedProperties();
                        }
                    }
                }
            }

            if (useCustomInteractionMapping)
            {
                EditorGUILayout.EndScrollView();
                interactionList.serializedObject.ApplyModifiedProperties();
            }

            GUILayout.EndVertical();
        }