internal void RenderControllerMappingButton(MixedRealityControllerMappingProfile controllerMappingProfile)
        {
            var controllerType = controllerMappingProfile.ControllerType.Type;

            var handedness = controllerMappingProfile.Handedness;

            if (handedness != Handedness.Right)
            {
                GUILayout.BeginHorizontal();
            }

            var typeName = controllerType?.Name.ToProperCase();

            if (controllerType?.Name == "WindowsMixedRealityMotionController" && controllerMappingProfile.Handedness == Handedness.None)
            {
                typeName = "HoloLens 1";
            }

            var buttonContent = new GUIContent($"Edit {typeName} Action Mapping", ControllerMappingLibrary.GetControllerTextureScaled(controllerMappingProfile));

            if (GUILayout.Button(buttonContent, ControllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
            {
                EditorApplication.delayCall += () => ControllerPopupWindow.Show(controllerMappingProfile, new SerializedObject(controllerMappingProfile).FindProperty("interactionMappingProfiles"));
            }

            if (handedness != Handedness.Left)
            {
                GUILayout.EndHorizontal();
            }
        }
        private void RenderControllerList(SerializedProperty controllerList)
        {
            if (thisProfile.MixedRealityControllerMappingProfiles.Length != controllerList.arraySize)
            {
                return;
            }

            EditorGUILayout.Space();

            if (GUILayout.Button(ControllerAddButtonContent, EditorStyles.miniButton))
            {
                AddController(controllerList, typeof(GenericJoystickController));
                return;
            }

            controllerRenderList.Clear();

            GUILayout.Space(12f);

            using (var outerVerticalScope = new GUILayout.VerticalScope())
            {
                GUILayout.HorizontalScope horizontalScope = null;

                for (int i = 0; i < thisProfile.MixedRealityControllerMappingProfiles.Length; i++)
                {
                    MixedRealityControllerMapping controllerMapping = thisProfile.MixedRealityControllerMappingProfiles[i];
                    Type controllerType = controllerMapping.ControllerType;
                    if (controllerType == null)
                    {
                        continue;
                    }

                    Handedness handedness = controllerMapping.Handedness;
                    bool       useCustomInteractionMappings         = controllerMapping.HasCustomInteractionMappings;
                    SupportedControllerType supportedControllerType = controllerMapping.SupportedControllerType;

                    var controllerMappingProperty = controllerList.GetArrayElementAtIndex(i);
                    var handednessProperty        = controllerMappingProperty.FindPropertyRelative("handedness");

                    if (!useCustomInteractionMappings)
                    {
                        bool skip = false;

                        // Merge controllers with the same supported controller type.
                        for (int j = 0; j < controllerRenderList.Count; j++)
                        {
                            if (controllerRenderList[j].SupportedControllerType == supportedControllerType &&
                                controllerRenderList[j].Handedness == handedness)
                            {
                                thisProfile.MixedRealityControllerMappingProfiles[i].SynchronizeInputActions(controllerRenderList[j].Interactions);
                                serializedObject.ApplyModifiedProperties();
                                skip = true;
                            }
                        }

                        if (skip)
                        {
                            continue;
                        }
                    }

                    controllerRenderList.Add(new ControllerRenderProfile(supportedControllerType, handedness, thisProfile.MixedRealityControllerMappingProfiles[i].Interactions));

                    string controllerTitle      = thisProfile.MixedRealityControllerMappingProfiles[i].Description;
                    var    interactionsProperty = controllerMappingProperty.FindPropertyRelative("interactions");

                    if (useCustomInteractionMappings)
                    {
                        if (horizontalScope != null)
                        {
                            horizontalScope.Dispose(); horizontalScope = null;
                        }

                        GUILayout.Space(24f);

                        using (var verticalScope = new GUILayout.VerticalScope())
                        {
                            using (horizontalScope = new GUILayout.HorizontalScope())
                            {
                                EditorGUIUtility.labelWidth = 64f;
                                EditorGUIUtility.fieldWidth = 64f;
                                EditorGUILayout.LabelField(controllerTitle);
                                EditorGUIUtility.fieldWidth = defaultFieldWidth;
                                EditorGUIUtility.labelWidth = defaultLabelWidth;

                                if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
                                {
                                    controllerList.DeleteArrayElementAtIndex(i);
                                    return;
                                }
                            }
                            EditorGUI.indentLevel++;

                            EditorGUIUtility.labelWidth = 128f;
                            EditorGUIUtility.fieldWidth = 64f;

                            EditorGUI.BeginChangeCheck();

                            // Generic Type dropdown
                            Type[] genericTypes           = MixedRealityControllerMappingProfile.CustomControllerMappingTypes;
                            var    genericTypeListContent = new GUIContent[genericTypes.Length];
                            var    genericTypeListIds     = new int[genericTypes.Length];
                            int    currentGenericType     = -1;
                            for (int genericTypeIdx = 0; genericTypeIdx < genericTypes.Length; genericTypeIdx++)
                            {
                                var attribute = MixedRealityControllerAttribute.Find(genericTypes[genericTypeIdx]);
                                if (attribute != null)
                                {
                                    genericTypeListContent[genericTypeIdx] = new GUIContent(attribute.SupportedControllerType.ToString().Replace("Generic", "").ToProperCase() + " Controller");
                                }
                                else
                                {
                                    genericTypeListContent[genericTypeIdx] = new GUIContent("Unknown Controller");
                                }

                                genericTypeListIds[genericTypeIdx] = genericTypeIdx;

                                if (controllerType == genericTypes[genericTypeIdx])
                                {
                                    currentGenericType = genericTypeIdx;
                                }
                            }
                            Debug.Assert(currentGenericType != -1);

                            currentGenericType = EditorGUILayout.IntPopup(GenericTypeContent, currentGenericType, genericTypeListContent, genericTypeListIds);
                            controllerType     = genericTypes[currentGenericType];

                            {
                                // Handedness dropdown
                                var attribute = MixedRealityControllerAttribute.Find(controllerType);
                                if (attribute != null && attribute.SupportedHandedness.Length >= 1)
                                {
                                    // Make sure handedness is valid for the selected controller type.
                                    if (Array.IndexOf(attribute.SupportedHandedness, (Handedness)handednessProperty.intValue) < 0)
                                    {
                                        handednessProperty.intValue = (int)attribute.SupportedHandedness[0];
                                    }

                                    if (attribute.SupportedHandedness.Length >= 2)
                                    {
                                        var handednessListContent = new GUIContent[attribute.SupportedHandedness.Length];
                                        var handednessListIds     = new int[attribute.SupportedHandedness.Length];
                                        for (int handednessIdx = 0; handednessIdx < attribute.SupportedHandedness.Length; handednessIdx++)
                                        {
                                            handednessListContent[handednessIdx] = new GUIContent(attribute.SupportedHandedness[handednessIdx].ToString());
                                            handednessListIds[handednessIdx]     = (int)attribute.SupportedHandedness[handednessIdx];
                                        }

                                        handednessProperty.intValue = EditorGUILayout.IntPopup(HandednessTypeContent, handednessProperty.intValue, handednessListContent, handednessListIds);
                                    }
                                }
                                else
                                {
                                    handednessProperty.intValue = (int)Handedness.None;
                                }
                            }

                            if (EditorGUI.EndChangeCheck())
                            {
                                interactionsProperty.ClearArray();
                                serializedObject.ApplyModifiedProperties();
                                thisProfile.MixedRealityControllerMappingProfiles[i].ControllerType.Type = genericTypes[currentGenericType];
                                thisProfile.MixedRealityControllerMappingProfiles[i].SetDefaultInteractionMapping(true);
                                serializedObject.ApplyModifiedProperties();
                                return;
                            }

                            EditorGUIUtility.labelWidth = defaultLabelWidth;
                            EditorGUIUtility.fieldWidth = defaultFieldWidth;

                            EditorGUI.indentLevel--;

                            if (GUILayout.Button("Edit Input Action Map"))
                            {
                                ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness);
                            }

                            if (GUILayout.Button("Reset Input Actions"))
                            {
                                interactionsProperty.ClearArray();
                                serializedObject.ApplyModifiedProperties();
                                thisProfile.MixedRealityControllerMappingProfiles[i].SetDefaultInteractionMapping(true);
                                serializedObject.ApplyModifiedProperties();
                            }
                        }
                    }
                    else
                    {
                        if (supportedControllerType == SupportedControllerType.WindowsMixedReality &&
                            handedness == Handedness.None)
                        {
                            controllerTitle = "HoloLens Gestures";
                        }

                        if (handedness != Handedness.Right)
                        {
                            if (horizontalScope != null)
                            {
                                horizontalScope.Dispose(); horizontalScope = null;
                            }
                            horizontalScope = new GUILayout.HorizontalScope();
                        }

                        var buttonContent = new GUIContent(controllerTitle, ControllerMappingLibrary.GetControllerTextureScaled(controllerType, handedness));

                        if (GUILayout.Button(buttonContent, controllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
                        {
                            ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness);
                        }
                    }
                }

                if (horizontalScope != null)
                {
                    horizontalScope.Dispose(); horizontalScope = null;
                }
            }
        }
        private void RenderControllerList(SerializedProperty controllerList)
        {
            if (thisProfile.MixedRealityControllerMappings.Length != controllerList.arraySize)
            {
                return;
            }

            if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton))
            {
                AddController(controllerList, typeof(GenericJoystickController));
                return;
            }

            controllerRenderList.Clear();

            // Generating the set of controllers that belong to each Controller Mapping Signature
            Dictionary <ControllerMappingSignature, List <string> > controllersAffectedByMappingSignatures = new Dictionary <ControllerMappingSignature, List <string> >();

            for (int i = 0; i < thisProfile.MixedRealityControllerMappings.Length; i++)
            {
                MixedRealityControllerMapping controllerMapping = thisProfile.MixedRealityControllerMappings[i];
                Type controllerType = controllerMapping.ControllerType;
                if (controllerType == null)
                {
                    continue;
                }

                Handedness handedness = controllerMapping.Handedness;
                SupportedControllerType supportedControllerType = controllerMapping.SupportedControllerType;

                ControllerMappingSignature currentSignature = new ControllerMappingSignature(supportedControllerType, handedness);
                if (!controllersAffectedByMappingSignatures.ContainsKey(currentSignature))
                {
                    controllersAffectedByMappingSignatures.Add(currentSignature, new List <string>());
                }
                controllersAffectedByMappingSignatures[currentSignature].Add(controllerType.ToString());
            }

            showControllerDefinitions = EditorGUILayout.Foldout(showControllerDefinitions, "Controller Definitions", true);
            if (showControllerDefinitions)
            {
                using (var outerVerticalScope = new GUILayout.VerticalScope())
                {
                    GUILayout.HorizontalScope horizontalScope = null;

                    for (int i = 0; i < thisProfile.MixedRealityControllerMappings.Length; i++)
                    {
                        MixedRealityControllerMapping controllerMapping = thisProfile.MixedRealityControllerMappings[i];
                        Type controllerType = controllerMapping.ControllerType;
                        if (controllerType == null)
                        {
                            continue;
                        }

                        Handedness handedness = controllerMapping.Handedness;
                        bool       useCustomInteractionMappings         = controllerMapping.HasCustomInteractionMappings;
                        SupportedControllerType supportedControllerType = controllerMapping.SupportedControllerType;

                        var controllerMappingProperty = controllerList.GetArrayElementAtIndex(i);
                        var handednessProperty        = controllerMappingProperty.FindPropertyRelative("handedness");

                        #region Profile Migration

                        // Between MRTK v2 RC2 and GA, the HoloLens clicker and HoloLens voice select input were migrated from
                        // SupportedControllerType.WindowsMixedReality && Handedness.None to SupportedControllerType.GGVHand && Handedness.None
                        if (supportedControllerType == SupportedControllerType.WindowsMixedReality && handedness == Handedness.None)
                        {
                            for (int j = 0; j < thisProfile.MixedRealityControllerMappings.Length; j++)
                            {
                                if (thisProfile.MixedRealityControllerMappings[j].SupportedControllerType == SupportedControllerType.GGVHand &&
                                    thisProfile.MixedRealityControllerMappings[j].Handedness == Handedness.None)
                                {
                                    if (horizontalScope != null)
                                    {
                                        horizontalScope.Dispose(); horizontalScope = null;
                                    }

                                    serializedObject.ApplyModifiedProperties();

                                    for (int k = 0; k < controllerMapping.Interactions.Length; k++)
                                    {
                                        MixedRealityInteractionMapping currentMapping = controllerMapping.Interactions[k];

                                        if (currentMapping.InputType == DeviceInputType.Select)
                                        {
                                            thisProfile.MixedRealityControllerMappings[j].Interactions[0].MixedRealityInputAction = currentMapping.MixedRealityInputAction;
                                        }
                                        else if (currentMapping.InputType == DeviceInputType.SpatialGrip)
                                        {
                                            thisProfile.MixedRealityControllerMappings[j].Interactions[1].MixedRealityInputAction = currentMapping.MixedRealityInputAction;
                                        }
                                    }

                                    serializedObject.Update();
                                    controllerList.DeleteArrayElementAtIndex(i);
                                    EditorUtility.DisplayDialog("Mappings updated", "The \"HoloLens Voice and Clicker\" mappings have been migrated to a new serialization. Please save this asset.", "Okay, thanks!");
                                    return;
                                }
                            }
                        }

                        #endregion Profile Migration

                        if (!useCustomInteractionMappings)
                        {
                            bool skip = false;

                            // Merge controllers with the same supported controller type.
                            for (int j = 0; j < controllerRenderList.Count; j++)
                            {
                                if (controllerRenderList[j].SupportedControllerType == supportedControllerType &&
                                    controllerRenderList[j].Handedness == handedness)
                                {
                                    try
                                    {
                                        thisProfile.MixedRealityControllerMappings[i].SynchronizeInputActions(controllerRenderList[j].Interactions);
                                    }
                                    catch (ArgumentException e)
                                    {
                                        Debug.LogError($"Controller mappings between {thisProfile.MixedRealityControllerMappings[i].Description} and {controllerMapping.Description} do not match. Error message: {e.Message}");
                                    }
                                    serializedObject.ApplyModifiedProperties();
                                    skip = true;
                                }
                            }

                            if (skip)
                            {
                                continue;
                            }
                        }

                        controllerRenderList.Add(new ControllerRenderProfile(supportedControllerType, handedness, thisProfile.MixedRealityControllerMappings[i].Interactions));

                        string controllerTitle      = thisProfile.MixedRealityControllerMappings[i].Description;
                        var    interactionsProperty = controllerMappingProperty.FindPropertyRelative("interactions");

                        if (useCustomInteractionMappings)
                        {
                            if (horizontalScope != null)
                            {
                                horizontalScope.Dispose(); horizontalScope = null;
                            }

                            GUILayout.Space(24f);

                            using (var verticalScope = new GUILayout.VerticalScope())
                            {
                                using (horizontalScope = new GUILayout.HorizontalScope())
                                {
                                    EditorGUILayout.LabelField(controllerTitle, EditorStyles.boldLabel);

                                    if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
                                    {
                                        controllerList.DeleteArrayElementAtIndex(i);
                                        return;
                                    }
                                }

                                EditorGUI.BeginChangeCheck();

                                // Generic Type dropdown
                                Type[] genericTypes           = MixedRealityControllerMappingProfile.CustomControllerMappingTypes;
                                var    genericTypeListContent = new GUIContent[genericTypes.Length];
                                var    genericTypeListIds     = new int[genericTypes.Length];
                                int    currentGenericType     = -1;
                                for (int genericTypeIdx = 0; genericTypeIdx < genericTypes.Length; genericTypeIdx++)
                                {
                                    var attribute = MixedRealityControllerAttribute.Find(genericTypes[genericTypeIdx]);
                                    if (attribute != null)
                                    {
                                        genericTypeListContent[genericTypeIdx] = new GUIContent(attribute.SupportedControllerType.ToString().Replace("Generic", "").ToProperCase() + " Controller");
                                    }
                                    else
                                    {
                                        genericTypeListContent[genericTypeIdx] = new GUIContent("Unknown Controller");
                                    }

                                    genericTypeListIds[genericTypeIdx] = genericTypeIdx;

                                    if (controllerType == genericTypes[genericTypeIdx])
                                    {
                                        currentGenericType = genericTypeIdx;
                                    }
                                }
                                Debug.Assert(currentGenericType != -1);

                                currentGenericType = EditorGUILayout.IntPopup(GenericTypeContent, currentGenericType, genericTypeListContent, genericTypeListIds);
                                controllerType     = genericTypes[currentGenericType];

                                {
                                    // Handedness dropdown
                                    var attribute = MixedRealityControllerAttribute.Find(controllerType);
                                    if (attribute != null && attribute.SupportedHandedness.Length >= 1)
                                    {
                                        // Make sure handedness is valid for the selected controller type.
                                        if (Array.IndexOf(attribute.SupportedHandedness, (Handedness)handednessProperty.intValue) < 0)
                                        {
                                            handednessProperty.intValue = (int)attribute.SupportedHandedness[0];
                                        }

                                        if (attribute.SupportedHandedness.Length >= 2)
                                        {
                                            var handednessListContent = new GUIContent[attribute.SupportedHandedness.Length];
                                            var handednessListIds     = new int[attribute.SupportedHandedness.Length];
                                            for (int handednessIdx = 0; handednessIdx < attribute.SupportedHandedness.Length; handednessIdx++)
                                            {
                                                handednessListContent[handednessIdx] = new GUIContent(attribute.SupportedHandedness[handednessIdx].ToString());
                                                handednessListIds[handednessIdx]     = (int)attribute.SupportedHandedness[handednessIdx];
                                            }

                                            handednessProperty.intValue = EditorGUILayout.IntPopup(HandednessTypeContent, handednessProperty.intValue, handednessListContent, handednessListIds);
                                        }
                                    }
                                    else
                                    {
                                        handednessProperty.intValue = (int)Handedness.None;
                                    }
                                }

                                if (EditorGUI.EndChangeCheck())
                                {
                                    interactionsProperty.ClearArray();
                                    serializedObject.ApplyModifiedProperties();
                                    thisProfile.MixedRealityControllerMappings[i].ControllerType.Type = genericTypes[currentGenericType];
                                    thisProfile.MixedRealityControllerMappings[i].SetDefaultInteractionMapping(true);
                                    serializedObject.ApplyModifiedProperties();
                                    return;
                                }

                                if (InspectorUIUtility.RenderIndentedButton("Edit Input Action Map"))
                                {
                                    ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness);
                                }

                                if (InspectorUIUtility.RenderIndentedButton("Reset Input Actions"))
                                {
                                    interactionsProperty.ClearArray();
                                    serializedObject.ApplyModifiedProperties();
                                    thisProfile.MixedRealityControllerMappings[i].SetDefaultInteractionMapping(true);
                                    serializedObject.ApplyModifiedProperties();
                                }
                            }
                        }
                        else
                        {
                            if (handedness != Handedness.Right)
                            {
                                if (horizontalScope != null)
                                {
                                    horizontalScope.Dispose(); horizontalScope = null;
                                }
                                horizontalScope = new GUILayout.HorizontalScope();
                            }

                            var buttonContent = new GUIContent(controllerTitle, ControllerMappingLibrary.GetControllerTextureScaled(controllerType, handedness));

                            if (GUILayout.Button(buttonContent, MixedRealityStylesUtility.ControllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
                            {
                                ControllerMappingSignature buttonSignature = new ControllerMappingSignature(supportedControllerType, handedness);
                                ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness, controllersAffectedByMappingSignatures[buttonSignature]);
                            }
                        }
                    }

                    if (horizontalScope != null)
                    {
                        horizontalScope.Dispose(); horizontalScope = null;
                    }
                }
            }
        }
        private void RenderControllerList(SerializedProperty controllerList)
        {
            if (thisProfile.MixedRealityControllerMappingProfiles.Length != controllerList.arraySize)
            {
                return;
            }

            EditorGUILayout.Space();

            if (GUILayout.Button(ControllerAddButtonContent, EditorStyles.miniButton))
            {
                AddController(controllerList, typeof(GenericJoystickController));
                return;
            }

            bool reset = false;

            if (controllerRenderList.Count > 0)
            {
                for (var type = 1; type <= (int)SupportedControllerType.Mouse; type++)
                {
                    if (controllerRenderList.All(profile => profile.ControllerType != (SupportedControllerType)type))
                    {
                        if ((SupportedControllerType)type == SupportedControllerType.TouchScreen)
                        {
                            AddController(controllerList, typeof(UnityTouchController));
                            reset = true;
                        }

                        if ((SupportedControllerType)type == SupportedControllerType.Mouse)
                        {
                            AddController(controllerList, typeof(MouseController));
                            reset = true;
                        }
                    }
                }
            }

            controllerRenderList.Clear();
            if (reset)
            {
                return;
            }

            GUILayout.Space(12f);
            GUILayout.BeginVertical();

            for (int i = 0; i < controllerList.arraySize; i++)
            {
                var controllerType                = thisProfile.MixedRealityControllerMappingProfiles[i].ControllerType.Type;
                var supportedControllerType       = SupportedControllerType.None;
                var mixedRealityControllerMapping = controllerList.GetArrayElementAtIndex(i);
                var controllerHandedness          = mixedRealityControllerMapping.FindPropertyRelative("handedness");
                var handedness                   = (Handedness)controllerHandedness.intValue;
                var interactionsList             = mixedRealityControllerMapping.FindPropertyRelative("interactions");
                var useCustomInteractionMappings = mixedRealityControllerMapping.FindPropertyRelative("useCustomInteractionMappings");

                if (controllerType == typeof(XboxController))
                {
                    supportedControllerType = SupportedControllerType.Xbox;
                }
                else if (controllerType == typeof(WindowsMixedRealityController) ||
                         controllerType == typeof(WindowsMixedRealityOpenVRMotionController))
                {
                    supportedControllerType = SupportedControllerType.WindowsMixedReality;
                }
                else if (controllerType == typeof(OculusTouchController))
                {
                    supportedControllerType = SupportedControllerType.OculusTouch;
                }
                else if (controllerType == typeof(OculusRemoteController))
                {
                    supportedControllerType = SupportedControllerType.OculusRemote;
                }
                else if (controllerType == typeof(ViveWandController))
                {
                    supportedControllerType = SupportedControllerType.ViveWand;
                }
                else if (controllerType == typeof(GenericOpenVRController))
                {
                    supportedControllerType = SupportedControllerType.GenericOpenVR;
                }
                else if (controllerType == typeof(GenericJoystickController))
                {
                    supportedControllerType = SupportedControllerType.GenericUnity;
                }
                else if (controllerType == typeof(UnityTouchController))
                {
                    supportedControllerType = SupportedControllerType.TouchScreen;
                }
                else if (controllerType == typeof(MouseController))
                {
                    supportedControllerType = SupportedControllerType.Mouse;
                }

                bool skip = false;

                for (int j = 0; j < controllerRenderList.Count; j++)
                {
                    if (supportedControllerType == SupportedControllerType.GenericOpenVR ||
                        supportedControllerType == SupportedControllerType.GenericUnity)
                    {
                        continue;
                    }

                    if (controllerRenderList[j].ControllerType == supportedControllerType &&
                        controllerRenderList[j].Handedness == handedness)
                    {
                        thisProfile.MixedRealityControllerMappingProfiles[i].SynchronizeInputActions(controllerRenderList[j].Interactions);
                        serializedObject.ApplyModifiedProperties();
                        skip = true;
                    }
                }

                if (skip)
                {
                    continue;
                }

                controllerRenderList.Add(new ControllerRenderProfile(supportedControllerType, handedness, thisProfile.MixedRealityControllerMappingProfiles[i].Interactions));

                var handednessTitleText = handedness != Handedness.None ? $"{handedness} Hand " : string.Empty;
                var controllerTitle     = $"{supportedControllerType.ToString().ToProperCase()} {handednessTitleText}Controller";

                if (useCustomInteractionMappings.boolValue)
                {
                    GUILayout.Space(24f);

                    EditorGUILayout.BeginVertical();
                    EditorGUILayout.BeginHorizontal();

                    EditorGUIUtility.labelWidth = 64f;
                    EditorGUIUtility.fieldWidth = 64f;
                    EditorGUILayout.LabelField(controllerTitle);
                    EditorGUIUtility.fieldWidth = defaultFieldWidth;
                    EditorGUIUtility.labelWidth = defaultLabelWidth;

                    if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
                    {
                        controllerList.DeleteArrayElementAtIndex(i);
                        EditorGUILayout.EndHorizontal();
                        GUILayout.EndVertical();
                        return;
                    }

                    EditorGUILayout.EndHorizontal();
                    EditorGUI.indentLevel++;

                    EditorGUIUtility.labelWidth = 128f;
                    EditorGUIUtility.fieldWidth = 64f;

                    EditorGUI.BeginChangeCheck();

                    int currentGenericType = -1;

                    if (controllerType == typeof(GenericJoystickController))
                    {
                        currentGenericType = 0;
                    }

                    if (controllerType == typeof(GenericOpenVRController))
                    {
                        currentGenericType = 1;
                    }

                    Debug.Assert(currentGenericType != -1);

                    currentGenericType = EditorGUILayout.IntPopup(GenericTypeContent, currentGenericType, GenericTypeListContent, GenericTypeIds);

                    if (controllerType != typeof(GenericJoystickController))
                    {
                        EditorGUILayout.PropertyField(controllerHandedness);
                    }

                    if (EditorGUI.EndChangeCheck())
                    {
                        switch (currentGenericType)
                        {
                        case 0:
                            controllerType = typeof(GenericJoystickController);
                            controllerHandedness.intValue = 0;
                            break;

                        case 1:
                            controllerType = typeof(GenericOpenVRController);
                            break;
                        }

                        interactionsList.ClearArray();
                        serializedObject.ApplyModifiedProperties();
                        thisProfile.MixedRealityControllerMappingProfiles[i].ControllerType.Type = controllerType;
                        GUILayout.EndVertical();
                        return;
                    }

                    if (interactionsList.arraySize == 0 && controllerType == typeof(GenericOpenVRController))
                    {
                        thisProfile.MixedRealityControllerMappingProfiles[i].SetDefaultInteractionMapping(true);
                        serializedObject.ApplyModifiedProperties();
                    }

                    EditorGUIUtility.labelWidth = defaultLabelWidth;
                    EditorGUIUtility.fieldWidth = defaultFieldWidth;

                    EditorGUI.indentLevel--;

                    if (GUILayout.Button("Edit Input Action Map"))
                    {
                        ControllerPopupWindow.Show(supportedControllerType, interactionsList, (Handedness)controllerHandedness.intValue);
                    }

                    if (GUILayout.Button("Reset Input Actions"))
                    {
                        interactionsList.ClearArray();
                        serializedObject.ApplyModifiedProperties();
                        thisProfile.MixedRealityControllerMappingProfiles[i].SetDefaultInteractionMapping(true);
                        serializedObject.ApplyModifiedProperties();
                    }

                    EditorGUILayout.EndVertical();
                }
                else
                {
                    if (supportedControllerType == SupportedControllerType.WindowsMixedReality &&
                        handedness == Handedness.None)
                    {
                        controllerTitle = "HoloLens Gestures";
                    }

                    if (handedness != Handedness.Right)
                    {
                        GUILayout.BeginHorizontal();
                    }

                    var buttonContent = new GUIContent(controllerTitle, ControllerMappingLibrary.GetControllerTextureScaled(supportedControllerType, handedness));

                    if (GUILayout.Button(buttonContent, controllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
                    {
                        ControllerPopupWindow.Show(supportedControllerType, interactionsList, (Handedness)controllerHandedness.intValue);
                    }

                    if (handedness != Handedness.Left)
                    {
                        GUILayout.EndHorizontal();
                    }
                }

                GUILayout.Space(8f);
            }

            GUILayout.EndVertical();
        }
Beispiel #5
0
        public override void OnInspectorGUI()
        {
            MixedRealityInspectorUtility.RenderMixedRealityToolkitLogo();

            if (thisProfile.ParentProfile != null &&
                GUILayout.Button("Back to controller mapping list"))
            {
                Selection.activeObject = thisProfile.ParentProfile;
            }

            EditorGUILayout.Space();
            var deviceName = controllerMappingProfile.ControllerType == SupportedControllerType.None ? "Custom Device" : controllerMappingProfile.ControllerType.ToString();

            EditorGUILayout.LabelField($"{deviceName} Mappings", EditorStyles.boldLabel);

            controllerMappingProfile.CheckProfileLock(false);

            if (controllerButtonStyle == null)
            {
                controllerButtonStyle = new GUIStyle("LargeButton")
                {
                    imagePosition = ImagePosition.ImageAbove,
                    fontStyle     = FontStyle.Bold,
                    stretchHeight = true,
                    stretchWidth  = true,
                    wordWrap      = true,
                    fontSize      = 10,
                };
            }

            serializedObject.Update();
            controllerItems.Clear();

            GUILayout.BeginVertical();

            if (controllerMappings.arraySize == 0)
            {
                EditorGUILayout.HelpBox("You must override the controller mappings in your custom implementation to see a list of mappings for your device.", MessageType.Error);
            }

            for (int i = 0; i < controllerMappings?.arraySize; i++)
            {
                var supportedControllerType = controllerMappingProfile.ControllerType;
                var controllerMapping       = controllerMappings.GetArrayElementAtIndex(i);
                var handednessValue         = controllerMapping.FindPropertyRelative("handedness");
                var handedness   = (Handedness)handednessValue.intValue;
                var description  = controllerMapping.FindPropertyRelative("description");
                var interactions = controllerMapping.FindPropertyRelative("interactions");

                bool skip = false;

                for (int j = 0; j < controllerItems.Count; j++)
                {
                    if (controllerItems[j].ControllerType == supportedControllerType &&
                        controllerItems[j].Handedness == handedness)
                    {
                        controllerMappingProfile.ControllerMappings[i].SynchronizeInputActions(controllerItems[j].Interactions);
                        serializedObject.ApplyModifiedProperties();
                        skip = true;
                    }
                }

                if (skip)
                {
                    continue;
                }

                controllerItems.Add(new ControllerItem(supportedControllerType, handedness, controllerMappingProfile.ControllerMappings[i].Interactions));

                string handednessContent = string.Empty;

                switch (handedness)
                {
                case Handedness.Left:
                case Handedness.Right:
                case Handedness.Other:
                    handednessContent = $" {handedness.ToString()} hand";
                    break;

                case Handedness.Both:
                    handednessContent = $" {handedness.ToString()} hands";
                    break;
                }

                if (handedness != Handedness.Right)
                {
                    GUILayout.BeginHorizontal();
                }

                var buttonContent = new GUIContent($"Edit {description.stringValue}{handednessContent}", ControllerMappingLibrary.GetControllerTextureScaled(controllerMappingProfile, supportedControllerType, handedness));

                if (GUILayout.Button(buttonContent, controllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
                {
                    serializedObject.ApplyModifiedProperties();
                    EditorApplication.delayCall += () => ControllerPopupWindow.Show(controllerMappingProfile, controllerMappingProfile.ControllerType, interactions, handedness, MixedRealityPreferences.LockProfiles && !thisProfile.IsCustomProfile);
                }

                if (handedness != Handedness.Left)
                {
                    GUILayout.EndHorizontal();
                }
            }

            GUILayout.EndVertical();

            serializedObject.ApplyModifiedProperties();
        }