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();
            }
        }
        public override void OnInspectorGUI()
        {
            RenderHeader("This profile defines the type of controller that is valid for this data provider, which hand it belongs to, and how to visualize this controller in the scene, and binds each interactions on every physical control mechanism or sensor on the device.");

            serializedObject.Update();

            EditorGUILayout.PropertyField(controllerType);
            EditorGUILayout.PropertyField(handedness);
            EditorGUILayout.PropertyField(visualizationProfile);
            EditorGUILayout.Space();

            if (GUILayout.Button(EditButtonContent))
            {
                ControllerPopupWindow.Show(controllerMappingProfile, interactionMappingProfiles);
            }

            EditorGUILayout.Space();
            interactionsList.DoLayoutList();

            serializedObject.ApplyModifiedProperties();
        }
        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();
        }
Ejemplo n.º 6
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();
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Resets the input actions of the controller mapping according to the mapping's GetDefaultInteractionMappings() function
 /// </summary>
 /// <param name="controllerMapping">A reference to the controller mapping struct geing reset</param>
 private void ResetInputActions(ref MixedRealityControllerMapping controllerMapping)
 {
     controllerMapping.SetDefaultInteractionMapping(true);
     serializedObject.ApplyModifiedProperties();
     ControllerPopupWindow.RepaintWindow();
 }