protected static BaseMixedRealityProfile CreateCustomProfile(BaseMixedRealityProfile sourceProfile)
        {
            if (sourceProfile == null)
            {
                return(null);
            }

            ScriptableObject        newProfile    = CreateInstance(sourceProfile.GetType().ToString());
            BaseMixedRealityProfile targetProfile = newProfile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles") as BaseMixedRealityProfile;

            Debug.Assert(targetProfile != null);

            EditorUtility.CopySerialized(sourceProfile, targetProfile);

            var serializedProfile = new SerializedObject(targetProfile);

            serializedProfile.FindProperty(IsCustomProfileProperty).boolValue = true;
            serializedProfile.ApplyModifiedProperties();
            AssetDatabase.SaveAssets();

            if (!sourceProfile.IsCustomProfile)
            {
                // For now we only replace it if it's the master configuration profile.
                // Sub-profiles are easy to update in the master configuration inspector.
                if (MixedRealityToolkit.Instance.ActiveProfile.GetType() == targetProfile.GetType())
                {
                    UnityEditor.Undo.RecordObject(MixedRealityToolkit.Instance, "Copy & Customize Profile");
                    MixedRealityToolkit.Instance.ActiveProfile = targetProfile as MixedRealityToolkitConfigurationProfile;
                }
            }

            return(targetProfile);
        }
        protected static bool RenderProfile(SerializedProperty property)
        {
            bool changed = false;

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(property);

            if (property.objectReferenceValue == null)
            {
                if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                {
                    var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                    Debug.Assert(profileTypeName != null, "No Type Found");
                    ScriptableObject instance = CreateInstance(profileTypeName);
                    var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                    property.objectReferenceValue = newProfile;
                    property.serializedObject.ApplyModifiedProperties();
                    changed = true;
                }
            }
            else
            {
                var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                Debug.Assert(renderedProfile != null);
                Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");

                if (!renderedProfile.IsCustomProfile && profile.IsCustomProfile)
                {
                    if (GUILayout.Button(new GUIContent("</>", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(32f)))
                    {
                        profileToCopy = renderedProfile;
                        var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                        Debug.Assert(profileTypeName != null, "No Type Found");

                        ScriptableObject instance = CreateInstance(profileTypeName);
                        var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                        property.objectReferenceValue = newProfile;
                        property.serializedObject.ApplyModifiedProperties();
                        PasteProfileValuesDelay(newProfile);
                        changed = true;
                    }
                }
            }

            EditorGUILayout.EndHorizontal();
            return(changed);
        }
        private static BaseMixedRealityProfile CloneProfile(BaseMixedRealityProfile parentProfile, BaseMixedRealityProfile profileToClone, string childProfileTypeName, SerializedProperty childProperty, Object targetFolder, string profileName)
        {
            ScriptableObject instance = CreateInstance(childProfileTypeName);

            instance.name = string.IsNullOrEmpty(profileName) ? childProfileTypeName : profileName;

            string fileName = instance.name;
            string path     = AssetDatabase.GetAssetPath(targetFolder);

            Debug.Log("Creating asset in path " + targetFolder);

            var newChildProfile = instance.CreateAsset(path, fileName) as BaseMixedRealityProfile;

            childProperty.objectReferenceValue = newChildProfile;
            childProperty.serializedObject.ApplyModifiedProperties();

            return(newChildProfile);
        }
        private static void RenderProfile(SerializedProperty property)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(property);

            if (property.objectReferenceValue == null)
            {
                if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton))
                {
                    var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                    Debug.Assert(profileTypeName != null, "No Type Found");
                    ScriptableObject profile = CreateInstance(profileTypeName);
                    profile.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject));
                    property.objectReferenceValue = profile;
                }
            }

            EditorGUILayout.EndHorizontal();
        }
예제 #5
0
        protected static async void CreateCopyProfileValues()
        {
            profileToCopy = profile;
            ScriptableObject newProfile = CreateInstance(profile.GetType().ToString());

            profile = newProfile.CreateAsset("Assets/XRTK-Generated/CustomProfiles") as BaseMixedRealityProfile;
            Debug.Assert(profile != null);

            await new WaitUntil(() => profileToCopy != profile);

            Selection.activeObject = null;
            PasteProfileValues();
            Selection.activeObject = profile;

            if (!profileToCopy.IsCustomProfile)
            {
                // For now we only replace it if it's the master configuration profile.
                // Sub-profiles are easy to update in the master configuration inspector.
                if (MixedRealityToolkit.Instance.ActiveProfile.GetType() == profile.GetType())
                {
                    MixedRealityToolkit.Instance.ActiveProfile = profile as MixedRealityToolkitConfigurationProfile;
                }
            }
        }
예제 #6
0
 /// <summary>
 /// Attempts to find the asset associated to the instance of the <see cref="ScriptableObject"/>, if none is found a new asset is created.
 /// </summary>
 /// <param name="scriptableObject"><see cref="ScriptableObject"/> you want get or create an asset file for.</param>
 /// <param name="path">Optional path for the new asset.</param>
 /// <param name="fileName">Optional filename for the new asset.</param>
 /// <param name="ping">The new asset should be selected and opened in the inspector.</param>
 public static ScriptableObject GetOrCreateAsset(this ScriptableObject scriptableObject, string path, string fileName, bool ping)
 {
     return(!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(scriptableObject, out var guid, out long _)
         ? scriptableObject.CreateAsset(path, fileName, ping)
         : AssetDatabase.LoadAssetAtPath <ScriptableObject>(AssetDatabase.GUIDToAssetPath(guid)));
 }
예제 #7
0
        private static bool RenderProfileInternal(SerializedProperty property, GUIContent guiContent, bool showAddButton)
        {
            bool changed = false;

            EditorGUILayout.BeginHorizontal();

            var oldObject = property.objectReferenceValue;

            if (guiContent == null)
            {
                EditorGUILayout.PropertyField(property);
            }
            else
            {
                EditorGUILayout.PropertyField(property, guiContent);
            }

            if (property.objectReferenceValue == null)
            {
                if (showAddButton &&
                    GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                {
                    var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                    Debug.Assert(profileTypeName != null, "No Type Found");

                    ScriptableObject instance = CreateInstance(profileTypeName);
                    var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                    property.objectReferenceValue = newProfile;
                    property.serializedObject.ApplyModifiedProperties();
                    changed = true;
                }
            }
            else
            {
                var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                Debug.Assert(renderedProfile != null);
                Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");

                if (profile.IsCustomProfile &&
                    !renderedProfile.IsCustomProfile &&
                    GUILayout.Button(CopyProfileContent, EditorStyles.miniButton, GUILayout.Width(42f)))
                {
                    profileToCopy = renderedProfile;
                    var typeName = renderedProfile.GetType().Name;
                    Debug.Assert(typeName != null, "No Type Found");

                    ScriptableObject instance = CreateInstance(typeName);
                    var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                    property.objectReferenceValue = newProfile;
                    property.serializedObject.ApplyModifiedProperties();
                    PasteProfileValuesDelay(newProfile);
                    changed = true;
                }
            }

            if (oldObject != property.objectReferenceValue)
            {
                changed = true;
            }

            EditorGUILayout.EndHorizontal();
            return(changed);
        }
예제 #8
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(activeProfile);
            bool   changed           = EditorGUI.EndChangeCheck();
            string commandName       = Event.current.commandName;
            var    allConfigProfiles = ScriptableObjectExtensions.GetAllInstances <MixedRealityToolkitConfigurationProfile>();

            if (activeProfile.objectReferenceValue == null && currentPickerWindow == -1 && checkChange)
            {
                if (allConfigProfiles.Length > 1)
                {
                    EditorUtility.DisplayDialog("Attention!", "You must choose a profile for the Mixed Reality Toolkit.", "OK");
                    currentPickerWindow = GUIUtility.GetControlID(FocusType.Passive);
                    EditorGUIUtility.ShowObjectPicker <MixedRealityToolkitConfigurationProfile>(null, false, string.Empty, currentPickerWindow);
                }
                else if (allConfigProfiles.Length == 1)
                {
                    activeProfile.objectReferenceValue = allConfigProfiles[0];
                    changed = true;
                    Selection.activeObject = allConfigProfiles[0];
                    EditorGUIUtility.PingObject(allConfigProfiles[0]);
                }
                else
                {
                    if (EditorUtility.DisplayDialog("Attention!", "No profiles were found for the Mixed Reality Toolkit.\n\n" +
                                                    "Would you like to create one now?", "OK", "Later"))
                    {
                        ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                        profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles");
                        activeProfile.objectReferenceValue = profile;
                        Selection.activeObject             = profile;
                        EditorGUIUtility.PingObject(profile);
                    }
                }

                checkChange = false;
            }

            if (EditorGUIUtility.GetObjectPickerControlID() == currentPickerWindow)
            {
                switch (commandName)
                {
                case "ObjectSelectorUpdated":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    changed = true;
                    break;

                case "ObjectSelectorClosed":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    currentPickerWindow    = -1;
                    changed                = true;
                    Selection.activeObject = activeProfile.objectReferenceValue;
                    EditorGUIUtility.PingObject(activeProfile.objectReferenceValue);
                    break;
                }
            }

            serializedObject.ApplyModifiedProperties();

            if (changed)
            {
                MixedRealityToolkit.Instance.ResetConfiguration((MixedRealityToolkitConfigurationProfile)activeProfile.objectReferenceValue);
            }

            if (activeProfile.objectReferenceValue != null)
            {
                UnityEditor.Editor activeProfileEditor = CreateEditor(activeProfile.objectReferenceValue);
                activeProfileEditor.OnInspectorGUI();
            }
        }
        private static bool RenderProfileInternal(SerializedProperty property, GUIContent guiContent, bool showAddButton)
        {
            bool changed = false;

            EditorGUILayout.BeginHorizontal();

            var oldObject = property.objectReferenceValue;

            if (guiContent == null)
            {
                EditorGUILayout.PropertyField(property);
            }
            else
            {
                EditorGUILayout.PropertyField(property, guiContent);
            }

            if (property.objectReferenceValue == null)
            {
                if (showAddButton)
                {
                    if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                    {
                        var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                        Debug.Assert(profileTypeName != null, "No Type Found");

                        ScriptableObject instance = CreateInstance(profileTypeName);
                        var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                        property.objectReferenceValue = newProfile;
                        property.serializedObject.ApplyModifiedProperties();
                        changed = true;
                    }
                }
            }
            else
            {
                var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                Debug.Assert(renderedProfile != null);
                Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");

                if (!renderedProfile.IsCustomProfile && profile.IsCustomProfile)
                {
                    if (GUILayout.Button(new GUIContent("</>", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(32f)))
                    {
                        profileToCopy = renderedProfile;
                        var profileTypeName = property.objectReferenceValue.GetType().Name;
                        Debug.Assert(profileTypeName != null, "No Type Found");

                        ScriptableObject instance = CreateInstance(profileTypeName);
                        var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                        property.objectReferenceValue = newProfile;
                        property.serializedObject.ApplyModifiedProperties();
                        PasteProfileValuesDelay(newProfile);
                        changed = true;
                    }
                }
            }

            if (oldObject != property.objectReferenceValue)
            {
                changed = true;
            }

            EditorGUILayout.EndHorizontal();

            // Check fields within profile for other nested profiles
            // Draw them when found
            if (property.objectReferenceValue != null)
            {
                Type profileType = property.objectReferenceValue.GetType();
                if (typeof(BaseMixedRealityProfile).IsAssignableFrom(profileType))
                {
                    string showFoldoutKey = GetSubProfileDropdownKey(property);
                    bool   showFoldout    = SessionState.GetBool(showFoldoutKey, false);
                    showFoldout = EditorGUILayout.Foldout(showFoldout, showFoldout ? "Hide " + property.displayName + " contents" : "Show " + property.displayName + " contents");

                    if (showFoldout)
                    {
                        Editor subProfileEditor = Editor.CreateEditor(property.objectReferenceValue);

                        // If this is a default MRTK configuration profile, ask it to render as a sub-profile
                        if (typeof(BaseMixedRealityToolkitConfigurationProfileInspector).IsAssignableFrom(subProfileEditor.GetType()))
                        {
                            BaseMixedRealityToolkitConfigurationProfileInspector configProfile = (BaseMixedRealityToolkitConfigurationProfileInspector)subProfileEditor;
                            configProfile.RenderAsSubProfile = true;
                        }

                        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                        EditorGUI.indentLevel++;
                        subProfileEditor.OnInspectorGUI();
                        EditorGUI.indentLevel--;
                        EditorGUILayout.EndVertical();
                    }

                    SessionState.SetBool(showFoldoutKey, showFoldout);
                }
            }

            return(changed);
        }
        public override void OnInspectorGUI()
        {
            MixedRealityToolkit instance = (MixedRealityToolkit)target;

            if (MixedRealityToolkit.Instance == null && instance.isActiveAndEnabled)
            {   // See if an active instance exists at all. If it doesn't register this instance preemptively.
                MixedRealityToolkit.SetActiveInstance(instance);
            }

            if (!instance.IsActiveInstance)
            {
                EditorGUILayout.HelpBox("This instance of the toolkit is inactive. There can only be one active instance loaded at any time.", MessageType.Warning);
                using (new EditorGUILayout.HorizontalScope())
                {
                    if (GUILayout.Button("Select Active Instance"))
                    {
                        UnityEditor.Selection.activeGameObject = MixedRealityToolkit.Instance.gameObject;
                    }

                    if (GUILayout.Button("Make this the Active Instance"))
                    {
                        MixedRealityToolkit.SetActiveInstance(instance);
                    }
                }
                return;
            }

            serializedObject.Update();
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(activeProfile);
            bool   changed     = EditorGUI.EndChangeCheck();
            string commandName = Event.current.commandName;

            // If not profile is assigned, then warn user
            if (activeProfile.objectReferenceValue == null)
            {
                EditorGUILayout.HelpBox("MixedRealityToolkit cannot initialize unless an Active Profile is assigned!", MessageType.Error);

                if (GUILayout.Button("Assign MixedRealityToolkit Profile") || forceShowProfilePicker)
                {
                    forceShowProfilePicker = false;

                    var allConfigProfiles = ScriptableObjectExtensions.GetAllInstances <MixedRealityToolkitConfigurationProfile>();

                    // Shows the list of MixedRealityToolkitConfigurationProfiles in our project,
                    // selecting the default profile by default (if it exists).
                    if (allConfigProfiles.Length > 0)
                    {
                        currentPickerWindow = GUIUtility.GetControlID(FocusType.Passive);

                        var defaultMRTKProfile = MixedRealityInspectorUtility.GetDefaultConfigProfile(allConfigProfiles);
                        activeProfile.objectReferenceValue = defaultMRTKProfile;

                        EditorGUIUtility.ShowObjectPicker <MixedRealityToolkitConfigurationProfile>(defaultMRTKProfile, false, string.Empty, currentPickerWindow);
                    }
                    else
                    {
                        if (EditorUtility.DisplayDialog("Attention!", "No profiles were found for the Mixed Reality Toolkit.\n\n" +
                                                        "Would you like to create one now?", "OK", "Later"))
                        {
                            ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                            profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles");
                            activeProfile.objectReferenceValue = profile;
                            EditorGUIUtility.PingObject(profile);
                        }
                    }
                }
            }

            // If user selects a new MRTK Active Profile, then update configuration
            if (EditorGUIUtility.GetObjectPickerControlID() == currentPickerWindow)
            {
                switch (commandName)
                {
                case "ObjectSelectorUpdated":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    changed = true;
                    break;

                case "ObjectSelectorClosed":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    currentPickerWindow = -1;
                    changed             = true;
                    break;
                }
            }

            serializedObject.ApplyModifiedProperties();

            if (changed)
            {
                MixedRealityToolkit.Instance.ResetConfiguration((MixedRealityToolkitConfigurationProfile)activeProfile.objectReferenceValue);
            }

            if (activeProfile.objectReferenceValue != null)
            {
                UnityEditor.Editor activeProfileEditor = CreateEditor(activeProfile.objectReferenceValue);
                activeProfileEditor.OnInspectorGUI();
            }
        }
예제 #11
0
        public override void OnInspectorGUI()
        {
            var configurationProfile = (MixedRealityToolkitConfigurationProfile)target;

            serializedObject.Update();

            RenderMixedRealityToolkitLogo();

            if (!MixedRealityToolkit.IsInitialized)
            {
                EditorGUILayout.HelpBox("No Mixed Reality Toolkit found in scene.", MessageType.Warning);
                if (GUILayout.Button("Click here to add Mixed Reality Toolkit instance to scene"))
                {
                    new GameObject("MixedRealityToolkit").AddComponent <MixedRealityToolkit>();
                }
            }

            if (!configurationProfile.IsCustomProfile)
            {
                EditorGUILayout.HelpBox("The Mixed Reality Toolkit's core SDK profiles can be used to get up and running quickly.\n\n" +
                                        "You can use the default profiles provided, copy and customize the default profiles, or create your own.", MessageType.Warning);
                EditorGUILayout.BeginHorizontal();

                if (GUILayout.Button("Copy & Customize"))
                {
                    var originalSelection = Selection.activeObject;
                    CreateCustomProfile(target as BaseMixedRealityProfile);
                    Selection.activeObject = originalSelection;
                }

                if (MixedRealityToolkit.IsInitialized)
                {
                    if (GUILayout.Button("Create new profiles"))
                    {
                        ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                        var newProfile           = profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles") as MixedRealityToolkitConfigurationProfile;
                        UnityEditor.Undo.RecordObject(MixedRealityToolkit.Instance, "Create new profiles");
                        MixedRealityToolkit.Instance.ActiveProfile = newProfile;
                        Selection.activeObject = newProfile;
                    }
                }

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider);
            }

            bool isGUIEnabled = !IsProfileLock((BaseMixedRealityProfile)target);

            GUI.enabled = isGUIEnabled;

            EditorGUI.BeginChangeCheck();
            bool changed = false;

            // Experience configuration
            ExperienceScale experienceScale = (ExperienceScale)targetExperienceScale.intValue;

            EditorGUILayout.PropertyField(targetExperienceScale, TargetScaleContent);

            string scaleDescription = GetExperienceDescription(experienceScale);

            if (!string.IsNullOrEmpty(scaleDescription))
            {
                EditorGUILayout.HelpBox(scaleDescription, MessageType.Info);
                EditorGUILayout.Space();
            }

            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Width(100));
            GUI.enabled        = true;  // Force enable so we can view profile defaults
            SelectedProfileTab = GUILayout.SelectionGrid(SelectedProfileTab, ProfileTabTitles, 1, EditorStyles.boldLabel, GUILayout.MaxWidth(125));
            GUI.enabled        = isGUIEnabled;
            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            using (new EditorGUI.IndentLevelScope())
            {
                changed |= RenderProfileFuncs[SelectedProfileTab]();
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();

            if (!changed)
            {
                changed |= EditorGUI.EndChangeCheck();
            }

            serializedObject.ApplyModifiedProperties();
            GUI.enabled = true;

            if (changed && MixedRealityToolkit.IsInitialized)
            {
                EditorApplication.delayCall += () => MixedRealityToolkit.Instance.ResetConfiguration(configurationProfile);
            }
        }
        public override void OnInspectorGUI()
        {
            MixedRealityInspectorUtility.RenderMixedRealityToolkitLogo();
            serializedObject.Update();

            if (!MixedRealityToolkit.IsInitialized)
            {
                EditorGUILayout.HelpBox("Unable to find Mixed Reality Toolkit!", MessageType.Error);
                return;
            }

            if (!configurationProfile.IsCustomProfile)
            {
                EditorGUILayout.HelpBox("The Mixed Reality Toolkit's core SDK profiles can be used to get up and running quickly.\n\n" +
                                        "You can use the default profiles provided, copy and customize the default profiles, or create your own.", MessageType.Warning);
                EditorGUILayout.BeginHorizontal();

                if (GUILayout.Button("Copy & Customize"))
                {
                    CreateCopyProfileValues();
                }

                if (GUILayout.Button("Create new profiles"))
                {
                    ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                    var newProfile           = profile.CreateAsset("Assets/XRTK.Generated/CustomProfiles") as MixedRealityToolkitConfigurationProfile;
                    MixedRealityToolkit.Instance.ActiveProfile = newProfile;
                    Selection.activeObject = newProfile;
                }

                EditorGUILayout.EndHorizontal();
            }

            // We don't call the CheckLock method so won't get a duplicate message.
            if (MixedRealityPreferences.LockProfiles && !((BaseMixedRealityProfile)target).IsCustomProfile)
            {
                GUI.enabled = false;
            }

            var previousLabelWidth = EditorGUIUtility.labelWidth;

            EditorGUIUtility.labelWidth = 160f;
            EditorGUI.BeginChangeCheck();
            bool changed = false;

            // Camera Profile configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Camera Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableCameraProfile);

            changed |= RenderProfile(cameraProfile);

            // Input System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Input System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableInputSystem);
            EditorGUILayout.PropertyField(inputSystemType);
            changed |= RenderProfile(inputSystemProfile);

            // Boundary System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Boundary System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableBoundarySystem);
            EditorGUILayout.PropertyField(boundarySystemType);
            changed |= RenderProfile(boundaryVisualizationProfile);

            // Teleport System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Teleport System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableTeleportSystem);
            EditorGUILayout.PropertyField(teleportSystemType);

            // Spatial Awareness System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Spatial Awareness System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableSpatialAwarenessSystem);
            EditorGUILayout.PropertyField(spatialAwarenessSystemType);
            changed |= RenderProfile(spatialAwarenessProfile);

            // Networking System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Networking System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableNetworkingSystem);
            EditorGUILayout.PropertyField(networkingSystemType);
            changed |= RenderProfile(networkingSystemProfile);

            // Diagnostics System configuration
            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Diagnostics System Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(enableDiagnosticsSystem);
            EditorGUILayout.PropertyField(diagnosticsSystemType);
            changed |= RenderProfile(diagnosticsSystemProfile);

            GUILayout.Space(12f);
            EditorGUILayout.LabelField("Additional Service Providers", EditorStyles.boldLabel);
            changed |= RenderProfile(registeredServiceProvidersProfile);

            if (!changed)
            {
                changed |= EditorGUI.EndChangeCheck();
            }

            EditorGUIUtility.labelWidth = previousLabelWidth;
            serializedObject.ApplyModifiedProperties();

            if (changed)
            {
                EditorApplication.delayCall += () => MixedRealityToolkit.Instance.ResetConfiguration(configurationProfile);
            }
        }
        /// <summary>
        /// Renders a <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/>.
        /// </summary>
        /// <param name="property">the <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/> property.</param>
        /// <param name="showAddButton">If true, draw the clone button, if false, don't</param>
        /// <param name="renderProfileInBox">if true, render box around profile content, if false, don't</param>
        /// <param name="serviceType">Optional service type to limit available profile types.</param>
        /// <returns>True, if the profile changed.</returns>
        private static bool RenderProfileInternal(SerializedProperty property, Type profileType,
                                                  bool showAddButton, bool renderProfileInBox, Type serviceType = null)
        {
            var  profile   = property.serializedObject.targetObject as BaseMixedRealityProfile;
            bool changed   = false;
            var  oldObject = property.objectReferenceValue;

            if (profileType != null && !profileType.IsSubclassOf(typeof(BaseMixedRealityProfile)) && profileType != typeof(BaseMixedRealityProfile))
            {
                // If they've drag-and-dropped a non-profile scriptable object, set it to null.
                profileType = null;
            }

            // If we're constraining this to a service type, check whether the profile is valid
            // If it isn't, issue a warning.
            if (serviceType != null && oldObject != null)
            {
                if (!IsProfileForService(oldObject.GetType(), serviceType))
                {
                    EditorGUILayout.HelpBox("This profile is not supported for " + serviceType.Name + ". Using an unsupported service may result in unexpected behavior.", MessageType.Warning);
                }
            }

            // Find the profile type so we can limit the available object field options
            if (serviceType != null)
            {
                // If GetProfileTypesForService has a count greater than one, then it won't be possible to use
                // EditorGUILayout.ObjectField to restrict the set of profiles to a single type - in this
                // case all profiles of BaseMixedRealityProfile will be visible in the picker.
                //
                // However in the case where there is just a single profile type for the service, we can improve
                // upon the user experience by limiting the set of things that show in the picker by restricting
                // the set of profiles listed to only that type.
                profileType = GetProfileTypesForService(serviceType).FirstOrDefault();
            }

            // If the profile type is still null, just set it to base profile type
            if (profileType == null)
            {
                profileType = typeof(BaseMixedRealityProfile);
            }

            // Begin the horizontal group
            EditorGUILayout.BeginHorizontal();

            // Draw the object field with an empty label - label is kept in the foldout
            property.objectReferenceValue = EditorGUILayout.ObjectField(oldObject != null ? "" : property.displayName, oldObject, profileType, false, GUILayout.ExpandWidth(true));
            changed = (property.objectReferenceValue != oldObject);

            // Draw the clone button
            if (property.objectReferenceValue == null)
            {
                var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                if (showAddButton && IsConcreteProfileType(profileTypeName))
                {
                    if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                    {
                        Debug.Assert(profileTypeName != null, "No Type Found");

                        ScriptableObject instance = CreateInstance(profileTypeName);
                        var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                        property.objectReferenceValue = newProfile;
                        property.serializedObject.ApplyModifiedProperties();
                        changed = true;
                    }
                }
            }
            else
            {
                var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                Debug.Assert(renderedProfile != null);
                Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");

                if (GUILayout.Button(new GUIContent("Clone", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(42f)))
                {
                    MixedRealityProfileCloneWindow.OpenWindow(profile, renderedProfile, property);
                }
            }

            EditorGUILayout.EndHorizontal();

            if (property.objectReferenceValue != null)
            {
                UnityEditor.Editor subProfileEditor = UnityEditor.Editor.CreateEditor(property.objectReferenceValue);

                // If this is a default MRTK configuration profile, ask it to render as a sub-profile
                if (typeof(BaseMixedRealityToolkitConfigurationProfileInspector).IsAssignableFrom(subProfileEditor.GetType()))
                {
                    BaseMixedRealityToolkitConfigurationProfileInspector configProfile = (BaseMixedRealityToolkitConfigurationProfileInspector)subProfileEditor;
                    configProfile.RenderAsSubProfile = true;
                }

                var subProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                if (subProfile != null && !subProfile.IsCustomProfile)
                {
                    EditorGUILayout.HelpBox("Clone this default profile to edit properties below", MessageType.Warning);
                }

                if (renderProfileInBox)
                {
                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                }
                else
                {
                    EditorGUILayout.BeginVertical();
                }

                EditorGUILayout.Space();
                subProfileEditor.OnInspectorGUI();
                EditorGUILayout.Space();

                EditorGUILayout.EndVertical();
            }

            return(changed);
        }
예제 #14
0
        public override void OnInspectorGUI()
        {
            MixedRealityToolkit instance = (MixedRealityToolkit)target;

            if (MixedRealityToolkit.Instance == null)
            {   // See if an active instance exists at all. If it doesn't register this instance pre-emptively.
                MixedRealityToolkit.SetActiveInstance(instance);
            }

            if (!instance.IsActiveInstance)
            {
                EditorGUILayout.HelpBox("This instance of the toolkt is inactive. There can only be one active instance loaded at any time.", MessageType.Warning);
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Select Active Instance"))
                {
                    UnityEditor.Selection.activeGameObject = MixedRealityToolkit.Instance.gameObject;
                }
                if (GUILayout.Button("Make this the Active Instance"))
                {
                    MixedRealityToolkit.SetActiveInstance(instance);
                }
                EditorGUILayout.EndHorizontal();
                return;
            }

            serializedObject.Update();
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(activeProfile);
            bool   changed           = EditorGUI.EndChangeCheck();
            string commandName       = Event.current.commandName;
            var    allConfigProfiles = ScriptableObjectExtensions.GetAllInstances <MixedRealityToolkitConfigurationProfile>();

            if (activeProfile.objectReferenceValue == null && currentPickerWindow == -1 && checkChange && !BuildPipeline.isBuildingPlayer)
            {
                if (allConfigProfiles.Length > 1)
                {
                    EditorUtility.DisplayDialog("Attention!", "You must choose a profile for the Mixed Reality Toolkit.", "OK");
                    currentPickerWindow = GUIUtility.GetControlID(FocusType.Passive);
                    // Shows the list of MixedRealityToolkitConfigurationProfiles in our project,
                    // selecting the default profile by default (if it exists).
                    EditorGUIUtility.ShowObjectPicker <MixedRealityToolkitConfigurationProfile>(GetDefaultProfile(allConfigProfiles), false, string.Empty, currentPickerWindow);
                }
                else if (allConfigProfiles.Length == 1)
                {
                    activeProfile.objectReferenceValue = allConfigProfiles[0];
                    changed = true;
                    Selection.activeObject = allConfigProfiles[0];
                    EditorGUIUtility.PingObject(allConfigProfiles[0]);
                }
                else
                {
                    if (EditorUtility.DisplayDialog("Attention!", "No profiles were found for the Mixed Reality Toolkit.\n\n" +
                                                    "Would you like to create one now?", "OK", "Later"))
                    {
                        ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                        profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles");
                        activeProfile.objectReferenceValue = profile;
                        Selection.activeObject             = profile;
                        EditorGUIUtility.PingObject(profile);
                    }
                }

                checkChange = false;
            }

            if (EditorGUIUtility.GetObjectPickerControlID() == currentPickerWindow)
            {
                switch (commandName)
                {
                case "ObjectSelectorUpdated":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    changed = true;
                    break;

                case "ObjectSelectorClosed":
                    activeProfile.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
                    currentPickerWindow    = -1;
                    changed                = true;
                    Selection.activeObject = activeProfile.objectReferenceValue;
                    EditorGUIUtility.PingObject(activeProfile.objectReferenceValue);
                    break;
                }
            }

            serializedObject.ApplyModifiedProperties();

            if (changed)
            {
                MixedRealityToolkit.Instance.ResetConfiguration((MixedRealityToolkitConfigurationProfile)activeProfile.objectReferenceValue);
            }

            if (activeProfile.objectReferenceValue != null)
            {
                UnityEditor.Editor activeProfileEditor = CreateEditor(activeProfile.objectReferenceValue);
                activeProfileEditor.OnInspectorGUI();
            }
        }
        public override void OnInspectorGUI()
        {
            var configurationProfile = (MixedRealityToolkitConfigurationProfile)target;

            serializedObject.Update();
            RenderMixedRealityToolkitLogo();

            if (!MixedRealityToolkit.IsInitialized)
            {
                EditorGUILayout.HelpBox("Unable to find Mixed Reality Toolkit!", MessageType.Error);
                return;
            }

            if (!configurationProfile.IsCustomProfile)
            {
                EditorGUILayout.HelpBox("The Mixed Reality Toolkit's core SDK profiles can be used to get up and running quickly.\n\n" +
                                        "You can use the default profiles provided, copy and customize the default profiles, or create your own.", MessageType.Warning);
                EditorGUILayout.BeginHorizontal();

                if (GUILayout.Button("Copy & Customize"))
                {
                    CreateCopyProfileValues();
                }

                if (GUILayout.Button("Create new profiles"))
                {
                    ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                    var newProfile           = profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles") as MixedRealityToolkitConfigurationProfile;
                    MixedRealityToolkit.Instance.ActiveProfile = newProfile;
                    Selection.activeObject = newProfile;
                }

                EditorGUILayout.EndHorizontal();
            }

            // We don't call the CheckLock method so won't get a duplicate message.
            if (MixedRealityPreferences.LockProfiles && !((BaseMixedRealityProfile)target).IsCustomProfile)
            {
                GUI.enabled = false;
            }

            var previousLabelWidth = EditorGUIUtility.labelWidth;

            EditorGUIUtility.labelWidth = 160f;
            EditorGUI.BeginChangeCheck();
            bool changed = false;

            // Experience configuration
            EditorGUILayout.Space();
            ExperienceScale experienceScale = (ExperienceScale)targetExperienceScale.intValue;

            showExperienceProperties = EditorGUILayout.Foldout(showExperienceProperties, "Experience Settings", true);
            if (showExperienceProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.PropertyField(targetExperienceScale, TargetScaleContent);
                    string scaleDescription = string.Empty;

                    switch (experienceScale)
                    {
                    case ExperienceScale.OrientationOnly:
                        scaleDescription = "The user is stationary. Position data does not change.";
                        break;

                    case ExperienceScale.Seated:
                        scaleDescription = "The user is stationary and seated. The origin of the world is at a neutral head-level position.";
                        break;

                    case ExperienceScale.Standing:
                        scaleDescription = "The user is stationary and standing. The origin of the world is on the floor, facing forward.";
                        break;

                    case ExperienceScale.Room:
                        scaleDescription = "The user is free to move about the room. The origin of the world is on the floor, facing forward. Boundaries are available.";
                        break;

                    case ExperienceScale.World:
                        scaleDescription = "The user is free to move about the world. Relies upon knowledge of the environment (Spatial Anchors and Spatial Mapping).";
                        break;
                    }

                    if (scaleDescription != string.Empty)
                    {
                        GUILayout.Space(6f);
                        EditorGUILayout.HelpBox(scaleDescription, MessageType.Info);
                    }
                }
            }

            // Camera Profile configuration
            EditorGUILayout.Space();
            showCameraProperties = EditorGUILayout.Foldout(showCameraProperties, "Camera Settings", true);
            if (showCameraProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.PropertyField(enableCameraProfile);
                    changed |= RenderProfile(cameraProfile);
                }
            }

            // Input System configuration
            EditorGUILayout.Space();
            showInputProperties = EditorGUILayout.Foldout(showInputProperties, "Input System Settings", true);
            if (showInputProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.PropertyField(enableInputSystem);
                    EditorGUILayout.PropertyField(inputSystemType);
                    changed |= RenderProfile(inputSystemProfile);
                }
            }

            // Boundary System configuration
            EditorGUILayout.Space();
            showBoundaryProperties = EditorGUILayout.Foldout(showBoundaryProperties, "Boundary System Settings", true);
            if (showBoundaryProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    if (experienceScale != ExperienceScale.Room)
                    {
                        // Alert the user if the experience scale does not support boundary features.
                        GUILayout.Space(6f);
                        EditorGUILayout.HelpBox("Boundaries are only supported in Room scale experiences.", MessageType.Warning);
                        GUILayout.Space(6f);
                    }
                    EditorGUILayout.PropertyField(enableBoundarySystem);
                    EditorGUILayout.PropertyField(boundarySystemType);
                    changed |= RenderProfile(boundaryVisualizationProfile);
                }
            }

            // Teleport System configuration
            EditorGUILayout.Space();
            showTeleportProperties = EditorGUILayout.Foldout(showTeleportProperties, "Teleport System Settings", true);
            if (showTeleportProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.PropertyField(enableTeleportSystem);
                    EditorGUILayout.PropertyField(teleportSystemType);
                }
            }

            // Spatial Awareness System configuration
            EditorGUILayout.Space();
            showSpatialAwarenessProperties = EditorGUILayout.Foldout(showSpatialAwarenessProperties, "Spatial Awareness System Settings", true);
            if (showSpatialAwarenessProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.PropertyField(enableSpatialAwarenessSystem);
                    EditorGUILayout.PropertyField(spatialAwarenessSystemType);
                    EditorGUILayout.HelpBox("Spatial Awareness settings are configured per observer.", MessageType.Info);
                    changed |= RenderProfile(spatialAwarenessSystemProfile);
                }
            }

            // Diagnostics System configuration
            EditorGUILayout.Space();
            showDiagnosticProperties = EditorGUILayout.Foldout(showDiagnosticProperties, "Diagnostics System Settings", true);
            if (showDiagnosticProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    EditorGUILayout.HelpBox("It is recommended to enable the Diagnostics system during development. Be sure to disable prior to building your shipping product.", MessageType.Warning);
                    EditorGUILayout.PropertyField(enableDiagnosticsSystem);
                    EditorGUILayout.PropertyField(diagnosticsSystemType);
                    changed |= RenderProfile(diagnosticsSystemProfile);
                }
            }

            // Registered Services configuration
            EditorGUILayout.Space();
            showRegisteredServiceProperties = EditorGUILayout.Foldout(showRegisteredServiceProperties, "Extension Services", true);
            if (showRegisteredServiceProperties)
            {
                using (new EditorGUI.IndentLevelScope())
                {
                    changed |= RenderProfile(registeredServiceProvidersProfile);
                }
            }

            if (!changed)
            {
                changed |= EditorGUI.EndChangeCheck();
            }

            EditorGUIUtility.labelWidth = previousLabelWidth;
            serializedObject.ApplyModifiedProperties();

            if (changed)
            {
                EditorApplication.delayCall += () => MixedRealityToolkit.Instance.ResetConfiguration(configurationProfile);
            }
        }
        public override void OnInspectorGUI()
        {
            var configurationProfile = (MixedRealityToolkitConfigurationProfile)target;

            serializedObject.Update();

            RenderMRTKLogo();

            CheckEditorPlayMode();

            if (!MixedRealityToolkit.IsInitialized)
            {
                EditorGUILayout.HelpBox("No Mixed Reality Toolkit found in scene.", MessageType.Warning);
                if (InspectorUIUtility.RenderIndentedButton("Add Mixed Reality Toolkit instance to scene"))
                {
                    MixedRealityInspectorUtility.AddMixedRealityToolkitToScene(configurationProfile);
                }
            }

            if (!configurationProfile.IsCustomProfile)
            {
                EditorGUILayout.HelpBox("The Mixed Reality Toolkit's core SDK profiles can be used to get up and running quickly.\n\n" +
                                        "You can use the default profiles provided, copy and customize the default profiles, or create your own.", MessageType.Warning);
                EditorGUILayout.BeginHorizontal();

                if (GUILayout.Button("Copy & Customize"))
                {
                    SerializedProperty targetProperty  = null;
                    UnityEngine.Object selectionTarget = null;
                    // If we have an active MRTK instance, find its config profile serialized property
                    if (MixedRealityToolkit.IsInitialized)
                    {
                        selectionTarget = MixedRealityToolkit.Instance;
                        SerializedObject mixedRealityToolkitObject = new SerializedObject(MixedRealityToolkit.Instance);
                        targetProperty = mixedRealityToolkitObject.FindProperty("activeProfile");
                    }
                    MixedRealityProfileCloneWindow.OpenWindow(null, target as BaseMixedRealityProfile, targetProperty, selectionTarget);
                }

                if (MixedRealityToolkit.IsInitialized)
                {
                    if (GUILayout.Button("Create new profiles"))
                    {
                        ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
                        var newProfile           = profile.CreateAsset("Assets/MixedRealityToolkit.Generated/CustomProfiles") as MixedRealityToolkitConfigurationProfile;
                        UnityEditor.Undo.RecordObject(MixedRealityToolkit.Instance, "Create new profiles");
                        MixedRealityToolkit.Instance.ActiveProfile = newProfile;
                        Selection.activeObject = newProfile;
                    }
                }

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider);
            }

            bool isGUIEnabled = !IsProfileLock((BaseMixedRealityProfile)target) && GUI.enabled;

            GUI.enabled = isGUIEnabled;

            EditorGUI.BeginChangeCheck();
            bool changed = false;

            // Experience configuration
            ExperienceScale experienceScale = (ExperienceScale)targetExperienceScale.intValue;

            EditorGUILayout.PropertyField(targetExperienceScale, TargetScaleContent);

            string scaleDescription = GetExperienceDescription(experienceScale);

            if (!string.IsNullOrEmpty(scaleDescription))
            {
                EditorGUILayout.HelpBox(scaleDescription, MessageType.Info);
                EditorGUILayout.Space();
            }

            changed |= EditorGUI.EndChangeCheck();

            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Width(100));
            GUI.enabled = true; // Force enable so we can view profile defaults

            int prefsSelectedTab = EditorPrefs.GetInt(SelectedTabPreferenceKey);

            SelectedProfileTab = GUILayout.SelectionGrid(prefsSelectedTab, ProfileTabTitles, 1, EditorStyles.boldLabel, GUILayout.MaxWidth(125));
            if (SelectedProfileTab != prefsSelectedTab)
            {
                EditorPrefs.SetInt(SelectedTabPreferenceKey, SelectedProfileTab);
            }

            GUI.enabled = isGUIEnabled;
            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            using (new EditorGUI.IndentLevelScope())
            {
                changed |= RenderProfileFuncs[SelectedProfileTab]();
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();

            serializedObject.ApplyModifiedProperties();
            GUI.enabled = true;

            if (changed && MixedRealityToolkit.IsInitialized)
            {
                EditorApplication.delayCall += () => MixedRealityToolkit.Instance.ResetConfiguration(configurationProfile);
            }
        }
예제 #17
0
        private static bool RenderProfileInternal(SerializedProperty property, GUIContent guiContent, bool showAddButton, Type serviceType = null)
        {
            profile = property.serializedObject.targetObject as BaseMixedRealityProfile;

            bool changed = false;

            var oldObject = property.objectReferenceValue;

            // If we're constraining this to a service type, check whether the profile is valid
            // If it isn't, issue a warning.
            if (serviceType != null && oldObject != null)
            {
                bool profileTypeIsValid = false;

                foreach (MixedRealityServiceProfileAttribute serviceProfileAttribute in oldObject.GetType().GetCustomAttributes(typeof(MixedRealityServiceProfileAttribute), true))
                {
                    if (serviceProfileAttribute.ServiceType.IsAssignableFrom(serviceType))
                    {
                        profileTypeIsValid = true;
                        break;
                    }
                }

                if (!profileTypeIsValid)
                {
                    EditorGUILayout.HelpBox("This profile is not supported for " + serviceType.Name + ". Using an unsupported service may result in unexpected behavior.", MessageType.Warning);
                }
            }

            EditorGUILayout.BeginHorizontal();

            if (guiContent == null)
            {
                EditorGUILayout.PropertyField(property);
            }
            else
            {
                EditorGUILayout.PropertyField(property, guiContent);
            }

            if (property.objectReferenceValue == null)
            {
                if (showAddButton)
                {
                    if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                    {
                        var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
                        Debug.Assert(profileTypeName != null, "No Type Found");

                        ScriptableObject instance = CreateInstance(profileTypeName);
                        var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                        property.objectReferenceValue = newProfile;
                        property.serializedObject.ApplyModifiedProperties();
                        changed = true;
                    }
                }
            }
            else
            {
                var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                Debug.Assert(renderedProfile != null);
                Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");

                if (GUILayout.Button(new GUIContent("Clone", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(42f)))
                {
                    MixedRealityProfileCloneWindow.OpenWindow(profile, renderedProfile, property);
                }
            }

            EditorGUILayout.EndHorizontal();

            // Check fields within profile for other nested profiles
            // Draw them when found
            if (property.objectReferenceValue != null)
            {
                Type profileType = property.objectReferenceValue.GetType();
                if (typeof(BaseMixedRealityProfile).IsAssignableFrom(profileType))
                {
                    string showFoldoutKey = GetSubProfileDropdownKey(property);
                    bool   showFoldout    = SessionState.GetBool(showFoldoutKey, false);
                    showFoldout = EditorGUILayout.Foldout(showFoldout, showFoldout ? "Hide " + property.displayName + " contents" : "Show " + property.displayName + " contents", true);

                    if (showFoldout)
                    {
                        UnityEditor.Editor subProfileEditor = UnityEditor.Editor.CreateEditor(property.objectReferenceValue);

                        // If this is a default MRTK configuration profile, ask it to render as a sub-profile
                        if (typeof(BaseMixedRealityToolkitConfigurationProfileInspector).IsAssignableFrom(subProfileEditor.GetType()))
                        {
                            BaseMixedRealityToolkitConfigurationProfileInspector configProfile = (BaseMixedRealityToolkitConfigurationProfileInspector)subProfileEditor;
                            configProfile.RenderAsSubProfile = true;
                        }

                        EditorGUI.indentLevel++;
                        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                        subProfileEditor.OnInspectorGUI();

                        EditorGUILayout.Space();
                        EditorGUILayout.Space();

                        EditorGUILayout.EndVertical();
                        EditorGUI.indentLevel--;
                    }

                    SessionState.SetBool(showFoldoutKey, showFoldout);
                }
            }

            return(changed);
        }
        /// <summary>
        /// Draws a dropdown with all available profiles of types contained in the array profilyTypes.
        /// </summary>
        /// <returns>True if property was changed.</returns>
        public static bool DrawProfileDropDownList(SerializedProperty property, BaseMixedRealityProfile profile, Object oldProfileObject, Type[] profileTypes, bool requiresProfile, bool showAddButton)
        {
            bool changed = false;

            using (new EditorGUILayout.HorizontalScope())
            {
                List<ScriptableObject> profileInstanceList = new List<ScriptableObject>();
                List<GUIContent> profileContentList = new List<GUIContent>();

                // Pull profile instances and profile content from cache
                for(int i = 0; i < profileTypes.Length; i++)
                {
                    Type profileType = profileTypes[i];
                    profileInstanceList.AddRange(MixedRealityProfileUtility.GetProfilesOfType(profileType));
                    profileContentList.AddRange(MixedRealityProfileUtility.GetProfilePopupOptionsByType(profileType));
                }

                int dropdownOffset = 0;
                if (!requiresProfile || profileInstanceList.Count == 0)
                {
                    profileContentList.Insert(0, new GUIContent("(None)"));
                    dropdownOffset = 1;
                }

                ScriptableObject[] profileInstances = profileInstanceList.ToArray();
                GUIContent[] profileContent = profileContentList.ToArray();

                int selectedIndex = 0;
                // Find our selected index
                for (int i = 0; i < profileInstances.Length; i++)
                {
                    if (profileInstances[i] == oldProfileObject)
                    {   // If a profile is required, then the selected index is the same as the profile instance index, otherwise it is offset by the dropdownOffset
                        // due to the pre-existing (None) option
                        selectedIndex = i + dropdownOffset;
                        break;
                    }
                }

                int newIndex = EditorGUILayout.Popup(
                    new GUIContent(oldProfileObject != null ? "" : property.displayName),
                    selectedIndex,
                    profileContent,
                    GUILayout.ExpandWidth(true));

                int profileInstanceIndex = newIndex - dropdownOffset;
                property.objectReferenceValue = (profileInstanceIndex >= 0) ? profileInstances[profileInstanceIndex] : null;
                changed = property.objectReferenceValue != oldProfileObject;

                // Draw a button that finds the profile in the project window
                if (property.objectReferenceValue != null)
                {
                    // The view asset button should always be enabled.
                    using (new GUIEnabledWrapper())
                    {
                        if (GUILayout.Button("View Asset", EditorStyles.miniButton, GUILayout.Width(80)))
                        {
                            EditorGUIUtility.PingObject(property.objectReferenceValue);
                        }
                    }
                }

                // Draw the clone button
                if (property.objectReferenceValue == null)
                {
                    if (showAddButton && MixedRealityProfileUtility.IsConcreteProfileType(Selection.activeObject.GetType()))
                    {
                        if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                        {
                            ScriptableObject instance = ScriptableObject.CreateInstance(Selection.activeObject.GetType());
                            var newProfile = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                            property.objectReferenceValue = newProfile;
                            property.serializedObject.ApplyModifiedProperties();
                            changed = true;
                        }
                    }
                }
                else
                {
                    var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                    Debug.Assert(renderedProfile != null);
                    if (GUILayout.Button(new GUIContent("Clone", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(45f)))
                    {
                        MixedRealityProfileCloneWindow.OpenWindow(profile, renderedProfile, property);
                    }
                }
            }

            return changed;
        }
예제 #19
0
        /// <summary>
        /// Draws a dropdown with all available profiles of profilyType.
        /// </summary>
        /// <returns>True if property was changed.</returns>
        public static bool DrawProfileDropDownList(SerializedProperty property, BaseMixedRealityProfile profile, Object oldProfileObject, Type profileType, bool showAddButton)
        {
            bool changed = false;

            using (new EditorGUILayout.HorizontalScope())
            {
                // Pull profile instances and profile content from cache
                ScriptableObject[] profileInstances = MixedRealityProfileUtility.GetProfilesOfType(profileType);
                GUIContent[]       profileContent   = MixedRealityProfileUtility.GetProfilePopupOptionsByType(profileType);
                // Set our selected index to our '(None)' option by default
                int selectedIndex = 0;
                // Find our selected index
                for (int i = 0; i < profileInstances.Length; i++)
                {
                    if (profileInstances[i] == oldProfileObject)
                    {   // Our profile content has a '(None)' option at the start
                        selectedIndex = i + 1;
                        break;
                    }
                }

                int newIndex = EditorGUILayout.Popup(
                    new GUIContent(oldProfileObject != null ? "" : property.displayName),
                    selectedIndex,
                    profileContent,
                    GUILayout.ExpandWidth(true));

                property.objectReferenceValue = (newIndex > 0) ? profileInstances[newIndex - 1] : null;
                changed = property.objectReferenceValue != oldProfileObject;

                // Draw a button that finds the profile in the project window
                if (property.objectReferenceValue != null)
                {
                    // The view asset button should always be enabled.
                    using (new GUIEnabledWrapper())
                    {
                        if (GUILayout.Button("View Asset", EditorStyles.miniButton, GUILayout.Width(80)))
                        {
                            EditorGUIUtility.PingObject(property.objectReferenceValue);
                        }
                    }
                }

                // Draw the clone button
                if (property.objectReferenceValue == null)
                {
                    if (showAddButton && MixedRealityProfileUtility.IsConcreteProfileType(profileType))
                    {
                        if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
                        {
                            ScriptableObject instance = ScriptableObject.CreateInstance(profileType);
                            var newProfile            = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
                            property.objectReferenceValue = newProfile;
                            property.serializedObject.ApplyModifiedProperties();
                            changed = true;
                        }
                    }
                }
                else
                {
                    var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
                    Debug.Assert(renderedProfile != null);
                    if (GUILayout.Button(new GUIContent("Clone", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(45f)))
                    {
                        MixedRealityProfileCloneWindow.OpenWindow(profile, renderedProfile, property);
                    }
                }
            }

            return(changed);
        }