/// <summary> /// Renders a non-editable object field and an editable dropdown of a profile. /// </summary> public static void RenderReadOnlyProfile(SerializedProperty property) { using (new EditorGUILayout.HorizontalScope()) { EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ObjectField(property.objectReferenceValue != null ? "" : property.displayName, property.objectReferenceValue, typeof(BaseMixedRealityProfile), false, GUILayout.ExpandWidth(true)); EditorGUI.EndDisabledGroup(); } if (property.objectReferenceValue != null) { bool showReadOnlyProfile = SessionState.GetBool(property.name + ".ReadOnlyProfile", false); using (new EditorGUI.IndentLevelScope()) { RenderFoldout(ref showReadOnlyProfile, property.displayName, () => { using (new EditorGUI.IndentLevelScope()) { UnityEditor.Editor subProfileEditor = 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; } subProfileEditor.OnInspectorGUI(); } }); } SessionState.SetBool(property.name + ".ReadOnlyProfile", showReadOnlyProfile); } }
/// <summary> /// Renders a non-editable object field and an editable dropdown of a profile. /// </summary> /// <param name="property"></param> /// <returns></returns> public static void RenderReadOnlyProfile(SerializedProperty property) { EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ObjectField(property.objectReferenceValue != null ? "" : property.displayName, property.objectReferenceValue, typeof(BaseMixedRealityProfile), false, GUILayout.ExpandWidth(true)); EditorGUI.EndDisabledGroup(); 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; } EditorGUILayout.BeginHorizontal(); EditorGUI.indentLevel++; EditorGUILayout.BeginVertical(EditorStyles.helpBox); subProfileEditor.OnInspectorGUI(); EditorGUILayout.Space(); EditorGUILayout.EndVertical(); EditorGUI.indentLevel--; EditorGUILayout.EndHorizontal(); } }
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> /// 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); }