public override void OnInspectorGUI() { serializedObject.Update(); InspectorUIUtility.DrawTitle("States"); EditorGUILayout.HelpBox("Manage state configurations to drive Interactables or Transitions", MessageType.None); SerializedProperty stateModelClassName = serializedObject.FindProperty("StateModelClassName"); SerializedProperty assemblyQualifiedName = serializedObject.FindProperty("AssemblyQualifiedName"); var stateModelTypes = TypeCacheUtility.GetSubClasses <BaseStateModel>(); var stateModelClassNames = stateModelTypes.Select(t => t?.Name).ToArray(); int id = Array.IndexOf(stateModelClassNames, stateModelClassName.stringValue); Rect stateModelPos = EditorGUILayout.GetControlRect(); using (new EditorGUI.PropertyScope(stateModelPos, new GUIContent("State Model"), stateModelClassName)) { int newId = EditorGUILayout.Popup("State Model", id, stateModelClassNames); if (id != newId) { Type newType = stateModelTypes[newId]; stateModelClassName.stringValue = newType.Name; assemblyQualifiedName.stringValue = newType.AssemblyQualifiedName; } } for (int i = 0; i < stateList.arraySize; i++) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { SerializedProperty stateItem = stateList.GetArrayElementAtIndex(i); SerializedProperty name = stateItem.FindPropertyRelative("Name"); SerializedProperty activeIndex = stateItem.FindPropertyRelative("ActiveIndex"); SerializedProperty bit = stateItem.FindPropertyRelative("Bit"); SerializedProperty index = stateItem.FindPropertyRelative("Index"); // assign the bitcount based on location in the list as power of 2 bit.intValue = 1 << i; activeIndex.intValue = i; Rect position = EditorGUILayout.GetControlRect(); using (new EditorGUILayout.HorizontalScope()) { var label = new GUIContent(name.stringValue + " (" + bit.intValue + ")"); using (new EditorGUI.PropertyScope(position, new GUIContent(), name)) { string[] stateEnums = Enum.GetNames(typeof(InteractableStates.InteractableStateEnum)); int enumIndex = Array.IndexOf(stateEnums, name.stringValue); int newEnumIndex = EditorGUILayout.Popup(label, enumIndex, stateEnums); if (newEnumIndex == -1) { newEnumIndex = 0; } name.stringValue = stateEnums[newEnumIndex]; index.intValue = newEnumIndex; } if (InspectorUIUtility.SmallButton(RemoveStateLabel)) { stateList.DeleteArrayElementAtIndex(i); break; } } } } if (InspectorUIUtility.FlexButton(AddStateLabel)) { stateList.InsertArrayElementAtIndex(stateList.arraySize); } serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { //base.OnInspectorGUI(); serializedObject.Update(); InspectorUIUtility.DrawTitle("States"); InspectorUIUtility.DrawNotice("Manage state configurations to drive Interactables or Tansitions"); // get the list of options and InteractableStates stateOptions = instance.StateOptions; stateTypes = instance.StateTypes; SerializedProperty stateLogicName = serializedObject.FindProperty("StateLogicName"); int option = States.ReverseLookup(stateLogicName.stringValue, stateOptions); int newLogic = EditorGUILayout.Popup("State Model", option, stateOptions); if (option != newLogic) { stateLogicName.stringValue = stateOptions[newLogic]; } int bitCount = 0; for (int i = 0; i < stateList.arraySize; i++) { if (i == 0) { bitCount += 1; } else { bitCount += bitCount; } EditorGUILayout.BeginVertical("Box"); SerializedProperty stateItem = stateList.GetArrayElementAtIndex(i); SerializedProperty name = stateItem.FindPropertyRelative("Name"); SerializedProperty index = stateItem.FindPropertyRelative("ActiveIndex"); SerializedProperty bit = stateItem.FindPropertyRelative("Bit"); index.intValue = i; EditorGUILayout.BeginHorizontal(); string[] stateEnums = GetStateOptions(); int enumIndex = States.ReverseLookup(name.stringValue, stateEnums); int newEnumIndex = EditorGUILayout.Popup(name.stringValue + " (" + bitCount + ")", enumIndex, stateEnums); if (enumIndex != newEnumIndex) { name.stringValue = stateEnums[newEnumIndex]; } InspectorUIUtility.SmallButton(new GUIContent(InspectorUIUtility.Minus, "Remove State"), i, RemoveState); EditorGUILayout.EndHorizontal(); // assign the bitcount based on location in the list bit.intValue = bitCount; EditorGUILayout.EndVertical(); } InspectorUIUtility.FlexButton(new GUIContent("+", "Add Theme Property"), 0, AddState); serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { if (target != null) { serializedObject.Update(); // Help url InspectorUIUtility.RenderHelpURL(target.GetType()); // Data section using (var check = new EditorGUI.ChangeCheckScope()) { EditorGUILayout.Space(); EditorGUILayout.HelpBox(autoConstraintSelection.boolValue == true ? autoMsg : manualMsg , UnityEditor.MessageType.Info); EditorGUILayout.Space(); int tab = autoConstraintSelection.boolValue == true ? 0 : 1; tab = GUILayout.Toolbar(tab, new string[] { "Auto Constraint Selection", "Manual Constraint Selection" }); EditorGUILayout.Space(); switch (tab) { case 0: autoConstraintSelection.boolValue = true; RenderAutoConstraintMenu(); break; case 1: bool oldAutoConstraintSelection = autoConstraintSelection.boolValue; autoConstraintSelection.boolValue = false; bool newAutoConstraintSelection = autoConstraintSelection.boolValue; // manual constraint selection was enabled if (newAutoConstraintSelection == false && oldAutoConstraintSelection != newAutoConstraintSelection) { // manual selection is active and manual list is empty -> auto populate with // existing constraints so user has a base to work on if (selectedConstraints.arraySize == 0) { var constraints = constraintManager.gameObject.GetComponents <TransformConstraint>(); foreach (var constraint in constraints) { int currentId = selectedConstraints.arraySize; selectedConstraints.InsertArrayElementAtIndex(currentId); selectedConstraints.GetArrayElementAtIndex(currentId).objectReferenceValue = constraint; } } } RenderManualConstraintMenu(); break; } // we render the instance id of this component so our highlighting function can distinguish between // the different instances of constraint manager - highlighting in the inspector is currently // only available for string search which causes problems with multiple components of the same type // attached to the same gameobject. EditorGUILayout.Space(); EditorGUILayout.LabelField("ComponentId: " + constraintManager.GetInstanceID(), EditorStyles.miniLabel); // deferred delete elements from array to not break unity layout for (int i = indicesToRemove.Count - 1; i > -1; i--) { var currentArraySize = selectedConstraints.arraySize; selectedConstraints.DeleteArrayElementAtIndex(indicesToRemove[i]); if (currentArraySize == selectedConstraints.arraySize) { selectedConstraints.DeleteArrayElementAtIndex(indicesToRemove[i]); } } indicesToRemove.Clear(); if (check.changed) { serializedObject.ApplyModifiedProperties(); } } } }
private void RenderProfileSettings() { if (!ProfilesSetup && !showProfiles) { InspectorUIUtility.DrawWarning("Profiles (Optional) have not been set up or has errors."); } bool isProfilesOpen = InspectorUIUtility.DrawSectionFoldout("Profiles", showProfiles, FontStyle.Bold, InspectorUIUtility.TitleFontSize); if (showProfiles != isProfilesOpen) { showProfiles = isProfilesOpen; EditorPrefs.SetBool(ShowProfilesPrefKey, showProfiles); } if (profileList.arraySize < 1) { AddProfile(0); } int validProfileCnt = 0; int themeCnt = 0; if (showProfiles) { // Render all profile items for (int i = 0; i < profileList.arraySize; i++) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { SerializedProperty profileItem = profileList.GetArrayElementAtIndex(i); SerializedProperty gameObject = profileItem.FindPropertyRelative("Target"); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.PropertyField(gameObject, new GUIContent("Target", "Target gameObject for this theme properties to manipulate")); if (InspectorUIUtility.SmallButton(new GUIContent(InspectorUIUtility.Minus, "Remove Profile"), i, RemoveProfile)) { continue; } } SerializedProperty themes = profileItem.FindPropertyRelative("Themes"); ValidateThemes(dimensions, themes); // Render all themes for current target for (int t = 0; t < themes.arraySize; t++) { SerializedProperty themeItem = themes.GetArrayElementAtIndex(t); string themeLabel = BuildThemeTitle(dimensions.intValue, t); EditorGUILayout.PropertyField(themeItem, new GUIContent(themeLabel, "Theme properties for interaction feedback")); if (themeItem.objectReferenceValue != null && gameObject.objectReferenceValue) { RenderDefaultThemeWarning(profileItem, themeItem); SerializedProperty hadDefault = profileItem.FindPropertyRelative("HadDefaultTheme"); hadDefault.boolValue = true; string prefKey = themeItem.objectReferenceValue.name + "Profiles" + i + "_Theme" + t + "_Edit"; bool showSettingsPref = EditorPrefs.GetBool(prefKey, true); bool show = InspectorUIUtility.DrawSectionFoldout(themeItem.objectReferenceValue.name + " (Click to edit)", showSettingsPref, FontStyle.Normal); if (show != showSettingsPref) { EditorPrefs.SetBool(prefKey, show); } if (show) { SerializedObject themeObj = new SerializedObject(themeItem.objectReferenceValue); SerializedProperty themeObjSettings = themeObj.FindProperty("Settings"); GUILayout.Space(5); if (InspectorUIUtility.FlexButton(AddThemePropertyLabel)) { AddThemeProperty(profileItem, themeItem); } State[] states = GetStates(); themeObj.Update(); ThemeInspector.RenderThemeSettings(themeObjSettings, themeOptions, gameObject, states, ThemePropertiesBoxMargin); ThemeInspector.RenderThemeStates(themeObjSettings, states, ThemePropertiesBoxMargin); themeObj.ApplyModifiedProperties(); } validProfileCnt++; } else { // show message about profile setup const string themeMsg = "Assign a Target and/or Theme above to add visual effects"; SerializedProperty hadDefault = profileItem.FindPropertyRelative("HadDefaultTheme"); if (!hadDefault.boolValue && t == 0) { string[] themeLocations = AssetDatabase.FindAssets("DefaultTheme"); if (themeLocations.Length > 0) { for (int j = 0; j < themeLocations.Length; j++) { string path = AssetDatabase.GUIDToAssetPath(themeLocations[0]); Theme defaultTheme = (Theme)AssetDatabase.LoadAssetAtPath(path, typeof(Theme)); if (defaultTheme != null) { themeItem.objectReferenceValue = defaultTheme; break; } } if (themeItem.objectReferenceValue != null) { hadDefault.boolValue = true; } } else { InspectorUIUtility.DrawError("DefaultTheme missing from project!"); } } InspectorUIUtility.DrawError(themeMsg); } themeCnt += themes.arraySize; } } }// profile for loop if (GUILayout.Button(new GUIContent("Add Profile"))) { AddProfile(profileList.arraySize); } } else { // make sure profiles are setup if closed by default for (int i = 0; i < profileList.arraySize; i++) { SerializedProperty sItem = profileList.GetArrayElementAtIndex(i); SerializedProperty gameObject = sItem.FindPropertyRelative("Target"); SerializedProperty themes = sItem.FindPropertyRelative("Themes"); if (gameObject.objectReferenceValue != null) { validProfileCnt++; } for (int t = 0; t < themes.arraySize; t++) { SerializedProperty themeItem = themes.GetArrayElementAtIndex(themes.arraySize - 1); if (themeItem.objectReferenceValue != null && gameObject.objectReferenceValue) { validProfileCnt++; SerializedProperty hadDefault = sItem.FindPropertyRelative("HadDefaultTheme"); hadDefault.boolValue = true; } } themeCnt += themes.arraySize; } } ProfilesSetup = validProfileCnt == profileList.arraySize + themeCnt; }
protected void RenderGeneralSettings() { Rect position; bool isPlayMode = EditorApplication.isPlaying || EditorApplication.isPaused; using (new EditorGUILayout.HorizontalScope()) { InspectorUIUtility.DrawTitle("General"); if (target != null) { var helpURL = target.GetType().GetCustomAttribute <HelpURLAttribute>(); if (helpURL != null) { InspectorUIUtility.RenderDocumentationButton(helpURL.URL); } } } EditorGUILayout.BeginVertical(EditorStyles.helpBox); // States // If states value is not provided, try to use Default states type if (statesProperty.objectReferenceValue == null) { statesProperty.objectReferenceValue = ThemeInspector.GetDefaultInteractableStates(); } GUI.enabled = !isPlayMode; EditorGUILayout.PropertyField(statesProperty, new GUIContent("States", "The States this Interactable is based on")); GUI.enabled = true; if (statesProperty.objectReferenceValue == null) { InspectorUIUtility.DrawError("Please assign a States object!"); serializedObject.ApplyModifiedProperties(); return; } EditorGUILayout.PropertyField(enabledProperty, new GUIContent("Enabled", "Is this Interactable Enabled?")); // Input Actions bool validActionOptions = inputActionOptions != null; GUI.enabled = validActionOptions && !isPlayMode; var actionOptions = validActionOptions ? inputActionOptions : new string[] { "Missing Mixed Reality Toolkit" }; DrawDropDownProperty(EditorGUILayout.GetControlRect(), actionId, actionOptions, InputActionsLabel); GUI.enabled = true; using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.PropertyField(isGlobal, new GUIContent("Is Global", "Like a modal, does not require focus")); } // Speech keywords bool validSpeechKeywords = speechKeywordOptions != null; GUI.enabled = validSpeechKeywords && !isPlayMode; string[] keywordOptions = validSpeechKeywords ? speechKeywordOptions : new string[] { "Missing Speech Commands" }; int currentIndex = validSpeechKeywords ? SpeechKeywordLookup(voiceCommands.stringValue, speechKeywordOptions) : 0; position = EditorGUILayout.GetControlRect(); //BeginProperty allows tracking of serialized properties for bolding prefab changes etc EditorGUI.BeginProperty(position, SpeechComamndsLabel, voiceCommands); { currentIndex = EditorGUI.Popup(position, SpeechComamndsLabel.text, currentIndex, keywordOptions); if (validSpeechKeywords) { voiceCommands.stringValue = currentIndex > 0 ? speechKeywordOptions[currentIndex] : string.Empty; } } EditorGUI.EndProperty(); GUI.enabled = true; // show requires gaze because voice command has a value if (!string.IsNullOrEmpty(voiceCommands.stringValue)) { using (new EditorGUI.IndentLevelScope()) { SerializedProperty requireGaze = serializedObject.FindProperty("RequiresFocus"); EditorGUILayout.PropertyField(requireGaze, new GUIContent("Requires Focus", "Does the voice command require gazing at this interactable?")); } } // should be 1 or more dimensions.intValue = Mathf.Clamp(dimensions.intValue, 1, 9); string[] selectionModeNames = Enum.GetNames(typeof(SelectionModes)); // clamp to values in the enum int selectionModeIndex = Mathf.Clamp(dimensions.intValue, 1, selectionModeNames.Length) - 1; // user-friendly dimension settings SelectionModes selectionMode = SelectionModes.Button; position = EditorGUILayout.GetControlRect(); GUI.enabled = !isPlayMode; EditorGUI.BeginProperty(position, selectionModeLabel, dimensions); { selectionMode = (SelectionModes)EditorGUI.EnumPopup(position, selectionModeLabel, (SelectionModes)(selectionModeIndex)); switch (selectionMode) { case SelectionModes.Button: dimensions.intValue = 1; break; case SelectionModes.Toggle: dimensions.intValue = 2; break; case SelectionModes.MultiDimension: // multi dimension mode - set min value to 3 dimensions.intValue = Mathf.Max(3, dimensions.intValue); position = EditorGUILayout.GetControlRect(); dimensions.intValue = EditorGUI.IntField(position, dimensionsLabel, dimensions.intValue); break; default: break; } } EditorGUI.EndProperty(); if (dimensions.intValue > 1) { // toggle or multi dimensional button using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.PropertyField(canSelect, new GUIContent("Can Select", "The user can toggle this button")); EditorGUILayout.PropertyField(canDeselect, new GUIContent("Can Deselect", "The user can untoggle this button, set false for a radial interaction.")); position = EditorGUILayout.GetControlRect(); EditorGUI.BeginProperty(position, startDimensionLabel, startDimensionIndex); { if (dimensions.intValue >= selectionModeNames.Length) { // multi dimensions if (!isPlayMode) { startDimensionIndex.intValue = EditorGUI.IntField(position, startDimensionLabel, startDimensionIndex.intValue); } else { EditorGUI.IntField(position, CurrentDimensionLabel, dimensionIndex.intValue); } } else if (dimensions.intValue == (int)SelectionModes.Toggle + 1) { if (!isPlayMode) { bool isToggled = EditorGUI.Toggle(position, isToggledLabel, startDimensionIndex.intValue > 0); startDimensionIndex.intValue = isToggled ? 1 : 0; } else { bool isToggled = EditorGUI.Toggle(position, isToggledLabel, dimensionIndex.intValue > 0); } } startDimensionIndex.intValue = Mathf.Clamp(startDimensionIndex.intValue, 0, dimensions.intValue - 1); } EditorGUI.EndProperty(); } } GUI.enabled = true; EditorGUILayout.EndVertical(); }
public void RenderThemeDefinitions() { GUIStyle box = InspectorUIUtility.HelpBox(EditorGUI.indentLevel * ThemeBoxMargin); // Loop through all InteractableThemePropertySettings of Theme for (int index = 0; index < themeDefinitions.arraySize; index++) { using (new EditorGUILayout.VerticalScope(box)) { SerializedProperty themeDefinition = themeDefinitions.GetArrayElementAtIndex(index); SerializedProperty className = themeDefinition.FindPropertyRelative("ClassName"); string themeDefinition_prefKey = theme.name + "_Definitions" + index; bool show = false; using (new EditorGUILayout.HorizontalScope()) { show = InspectorUIUtility.DrawSectionFoldoutWithKey(className.stringValue, themeDefinition_prefKey, MixedRealityStylesUtility.BoldFoldoutStyle); if (RenderDeleteButton(index)) { return; } } if (show) { EditorGUILayout.Space(); using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.LabelField("General Properties", EditorStyles.boldLabel); using (new EditorGUILayout.HorizontalScope()) { var themeTypes = TypeCacheUtility.GetSubClasses <InteractableThemeBase>(); var themeClassNames = themeTypes.Select(t => t?.Name).ToArray(); int id = Array.IndexOf(themeClassNames, className.stringValue); int newId = EditorGUILayout.Popup("Theme Runtime", id, themeClassNames); // Some old Themes did not properly save a value here SerializedProperty assemblyQualifiedName = themeDefinition.FindPropertyRelative("AssemblyQualifiedName"); if (string.IsNullOrEmpty(assemblyQualifiedName.stringValue) && newId != -1) { assemblyQualifiedName.stringValue = themeTypes[newId].AssemblyQualifiedName; } // If user changed the theme type for current themeDefinition if (id != newId && newId != -1) { Type oldType = id != -1 ? themeTypes[id] : null; Type newType = themeTypes[newId]; ChangeThemeDefinitionType(index, oldType, newType); return; } } var themeType = theme.Definitions[index].ThemeType; if (themeType != null) { SerializedProperty customProperties = themeDefinition.FindPropertyRelative("customProperties"); RenderCustomProperties(customProperties); var themeExample = (InteractableThemeBase)Activator.CreateInstance(themeType); if (themeExample.IsEasingSupported) { RenderEasingProperties(themeDefinition); } if (themeExample.AreShadersSupported) { RenderShaderProperties(themeDefinition); } EditorGUILayout.Space(); RenderThemeStates(themeDefinition); } else { InspectorUIUtility.DrawError("Theme Runtime Type is not valid"); } } } } } // If no theme properties assigned, add a default one if (themeDefinitions.arraySize < 1 || GUILayout.Button(AddThemePropertyLabel)) { AddThemeDefinition(); } }
private void RenderControllerList(SerializedProperty controllerList) { if (thisProfile.MixedRealityControllerMappingProfiles.Length != controllerList.arraySize) { return; } if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton)) { AddController(controllerList, typeof(GenericJoystickController)); return; } controllerRenderList.Clear(); showControllerDefinitions = EditorGUILayout.Foldout(showControllerDefinitions, "Controller Definitions"); if (showControllerDefinitions) { 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) { try { thisProfile.MixedRealityControllerMappingProfiles[i].SynchronizeInputActions(controllerRenderList[j].Interactions); } catch (ArgumentException e) { Debug.LogError($"Controller mappings between {thisProfile.MixedRealityControllerMappingProfiles[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.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()) { 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.MixedRealityControllerMappingProfiles[i].ControllerType.Type = genericTypes[currentGenericType]; thisProfile.MixedRealityControllerMappingProfiles[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.MixedRealityControllerMappingProfiles[i].SetDefaultInteractionMapping(true); serializedObject.ApplyModifiedProperties(); } } } else { if (supportedControllerType == SupportedControllerType.WindowsMixedReality && handedness == Handedness.None) { controllerTitle = "HoloLens Voice and Clicker"; } 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))) { ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness); } } } if (horizontalScope != null) { horizontalScope.Dispose(); horizontalScope = null; } } } }
private void RenderStateContainers() { InspectorUIUtility.DrawTitle("State Animations"); for (int i = 0; i < stateContainers.arraySize; i++) { SerializedProperty stateContainer = stateContainers.GetArrayElementAtIndex(i); SerializedProperty stateContainerName = stateContainer.FindPropertyRelative("stateName"); SerializedProperty animationTargetsList = stateContainer.FindPropertyRelative("animationTargets"); SerializedProperty stateContainerAnimationClip = stateContainer.FindPropertyRelative("animationClip"); SerializedProperty animationTransitionDuration = stateContainer.FindPropertyRelative("animationTransitionDuration"); Color previousGUIColor = GUI.color; using (new EditorGUILayout.HorizontalScope()) { string stateFoldoutID = stateContainerName.stringValue + "StateContainer" + "_" + target.name; if (inPlayMode) { BaseInteractiveElement baseInteractiveElement = interactiveElement.objectReferenceValue as BaseInteractiveElement; if (baseInteractiveElement.isActiveAndEnabled) { if (baseInteractiveElement.IsStateActive(stateContainerName.stringValue)) { GUI.color = Color.cyan; } } } using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUILayout.Space(); if (InspectorUIUtility.DrawSectionFoldoutWithKey(stateContainerName.stringValue, stateFoldoutID, MixedRealityStylesUtility.TitleFoldoutStyle, false)) { using (new EditorGUI.IndentLevelScope()) { using (var check = new EditorGUI.ChangeCheckScope()) { EditorGUILayout.PropertyField(stateContainerAnimationClip); EditorGUILayout.PropertyField(animationTransitionDuration); if (check.changed) { instance.SetAnimationTransitionDuration(stateContainerName.stringValue, animationTransitionDuration.floatValue); instance.SetAnimationClip(stateContainerName.stringValue, stateContainerAnimationClip.objectReferenceValue as AnimationClip); } } RenderAnimationTargetList(animationTargetsList, stateContainerName); } } EditorGUILayout.Space(); } GUI.color = previousGUIColor; if (!inPlayMode) { if (InspectorUIUtility.SmallButton(RemoveButtonLabel)) { instance.RemoveAnimatorState(instance.RootStateMachine, stateContainerName.stringValue); stateContainers.DeleteArrayElementAtIndex(i); break; } } } } }
private void RenderControllerList(SerializedProperty controllerList) { if (thisProfile.ControllerVisualizationSettings.Length != controllerList.arraySize) { return; } EditorGUILayout.Space(); if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton)) { controllerList.InsertArrayElementAtIndex(controllerList.arraySize); var index = controllerList.arraySize - 1; var controllerSetting = controllerList.GetArrayElementAtIndex(index); var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description"); mixedRealityControllerMappingDescription.stringValue = typeof(GenericJoystickController).Name; var mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness"); mixedRealityControllerHandedness.intValue = 1; serializedObject.ApplyModifiedProperties(); thisProfile.ControllerVisualizationSettings[index].ControllerType.Type = typeof(GenericJoystickController); return; } for (int i = 0; i < controllerList.arraySize; i++) { EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); var controllerSetting = controllerList.GetArrayElementAtIndex(i); var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description"); bool hasValidType = thisProfile.ControllerVisualizationSettings[i].ControllerType != null && thisProfile.ControllerVisualizationSettings[i].ControllerType.Type != null; mixedRealityControllerMappingDescription.stringValue = hasValidType ? thisProfile.ControllerVisualizationSettings[i].ControllerType.Type.Name.ToProperCase() : "Undefined Controller"; serializedObject.ApplyModifiedProperties(); var mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness"); EditorGUILayout.LabelField($"{mixedRealityControllerMappingDescription.stringValue} {((Handedness)mixedRealityControllerHandedness.intValue).ToString().ToProperCase()} Hand", EditorStyles.boldLabel); if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f))) { controllerList.DeleteArrayElementAtIndex(i); EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); return; } EditorGUILayout.EndHorizontal(); EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerType")); EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerVisualizationType")); if (!hasValidType) { EditorGUILayout.HelpBox("A controller type must be defined!", MessageType.Error); } var handednessValue = mixedRealityControllerHandedness.intValue - 1; // Reset in case it was set to something other than left or right. if (handednessValue < 0 || handednessValue > 1) { handednessValue = 0; } EditorGUI.BeginChangeCheck(); handednessValue = EditorGUILayout.IntPopup(new GUIContent(mixedRealityControllerHandedness.displayName, mixedRealityControllerHandedness.tooltip), handednessValue, HandednessSelections, null); if (EditorGUI.EndChangeCheck()) { mixedRealityControllerHandedness.intValue = handednessValue + 1; } var overrideModel = controllerSetting.FindPropertyRelative("overrideModel"); var overrideModelPrefab = overrideModel.objectReferenceValue as GameObject; var controllerUseDefaultModelOverride = controllerSetting.FindPropertyRelative("useDefaultModel"); using (new GUILayout.HorizontalScope()) { EditorGUILayout.PropertyField(controllerUseDefaultModelOverride); var defaultModelMaterial = controllerSetting.FindPropertyRelative("defaultModelMaterial"); EditorGUILayout.PropertyField(defaultModelMaterial); } if (controllerUseDefaultModelOverride.boolValue && overrideModelPrefab != null) { EditorGUILayout.HelpBox("When default model is used, the override model will only be used if the default model cannot be loaded from the driver.", MessageType.Warning); } EditorGUI.BeginChangeCheck(); overrideModelPrefab = EditorGUILayout.ObjectField(new GUIContent(overrideModel.displayName, "If no override model is set, the global model is used."), overrideModelPrefab, typeof(GameObject), false) as GameObject; if (EditorGUI.EndChangeCheck() && CheckVisualizer(overrideModelPrefab)) { overrideModel.objectReferenceValue = overrideModelPrefab; } } }
private void RenderControllerList(SerializedProperty controllerList) { if (thisProfile.ControllerVisualizationSettings.Length != controllerList.arraySize) { return; } EditorGUILayout.Space(); if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton)) { controllerList.InsertArrayElementAtIndex(controllerList.arraySize); var index = controllerList.arraySize - 1; var controllerSetting = controllerList.GetArrayElementAtIndex(index); var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description"); mixedRealityControllerMappingDescription.stringValue = typeof(GenericJoystickController).Name; var mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness"); mixedRealityControllerHandedness.intValue = 1; serializedObject.ApplyModifiedProperties(); thisProfile.ControllerVisualizationSettings[index].ControllerType.Type = typeof(GenericJoystickController); return; } #if UNITY_2019 xrPipelineUtility.RenderXRPipelineTabs(); #endif // UNITY_2019 for (int i = 0; i < controllerList.arraySize; i++) { var controllerSetting = controllerList.GetArrayElementAtIndex(i); var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description"); SystemType controllerType = thisProfile.ControllerVisualizationSettings[i].ControllerType; bool hasValidType = controllerType != null && controllerType.Type != null; if (hasValidType) { MixedRealityControllerAttribute controllerAttribute = MixedRealityControllerAttribute.Find(controllerType.Type); if (controllerAttribute != null && !controllerAttribute.SupportedUnityXRPipelines.HasFlag(xrPipelineUtility.SelectedPipeline)) { continue; } } else if (!MixedRealityProjectPreferences.ShowNullDataProviders) { continue; } EditorGUILayout.Space(); mixedRealityControllerMappingDescription.stringValue = hasValidType ? controllerType.Type.Name.ToProperCase() : "Undefined Controller"; serializedObject.ApplyModifiedProperties(); SerializedProperty mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness"); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField($"{mixedRealityControllerMappingDescription.stringValue} {((Handedness)mixedRealityControllerHandedness.intValue).ToString().ToProperCase()} Hand{(mixedRealityControllerHandedness.intValue == (int)(Handedness.Both) ? "s" : "")}", EditorStyles.boldLabel); if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f))) { controllerList.DeleteArrayElementAtIndex(i); return; } } EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerType")); EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerVisualizationType")); if (!hasValidType) { EditorGUILayout.HelpBox("A controller type must be defined!", MessageType.Error); } var handednessValue = mixedRealityControllerHandedness.intValue - 1; // Reset in case it was set to something other than left, right, or both. if (handednessValue < 0 || handednessValue > 2) { handednessValue = 0; } EditorGUI.BeginChangeCheck(); handednessValue = EditorGUILayout.IntPopup(new GUIContent(mixedRealityControllerHandedness.displayName, mixedRealityControllerHandedness.tooltip), handednessValue, HandednessSelections, null); if (EditorGUI.EndChangeCheck()) { mixedRealityControllerHandedness.intValue = handednessValue + 1; } var overrideModel = controllerSetting.FindPropertyRelative("overrideModel"); var overrideModelPrefab = overrideModel.objectReferenceValue as GameObject; var controllerUsePlatformModelOverride = controllerSetting.FindPropertyRelative("usePlatformModels"); EditorGUILayout.PropertyField(controllerUsePlatformModelOverride); if (controllerUsePlatformModelOverride.boolValue) { var platformModelMaterial = controllerSetting.FindPropertyRelative("platformModelMaterial"); EditorGUILayout.PropertyField(platformModelMaterial); } if (controllerUsePlatformModelOverride.boolValue && overrideModelPrefab != null) { EditorGUILayout.HelpBox("When platform model is used, the override model will only be used if the default model cannot be loaded from the driver.", MessageType.Warning); } EditorGUI.BeginChangeCheck(); overrideModelPrefab = EditorGUILayout.ObjectField(new GUIContent(overrideModel.displayName, "If no override model is set, the global model is used."), overrideModelPrefab, typeof(GameObject), false) as GameObject; if (overrideModelPrefab == null && !controllerUsePlatformModelOverride.boolValue) { EditorGUILayout.HelpBox("No override model was assigned and this controller will not attempt to use the platform's model, the global model will be used instead", MessageType.Warning); } if (EditorGUI.EndChangeCheck() && CheckVisualizer(overrideModelPrefab)) { overrideModel.objectReferenceValue = overrideModelPrefab; } } }
private void RenderAnimationTargetList(SerializedProperty animationTargetList, SerializedProperty stateContainerName) { using (new EditorGUI.IndentLevelScope()) { for (int j = 0; j < animationTargetList.arraySize; j++) { SerializedProperty animationTarget = animationTargetList.GetArrayElementAtIndex(j); SerializedProperty targetObj = animationTarget.FindPropertyRelative("target"); SerializedProperty animatablePropertyList = animationTarget.FindPropertyRelative("stateAnimatableProperties"); EditorGUILayout.Space(); using (new EditorGUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.Space(); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.PropertyField(targetObj); if (InspectorUIUtility.SmallButton(RemoveButtonLabel)) { // Clear keyframes of a deleted target for (int k = 0; k < animatablePropertyList.arraySize; k++) { SerializedProperty animatableProperty = animatablePropertyList.GetArrayElementAtIndex(k); SerializedProperty animatablePropertyName = animatableProperty.FindPropertyRelative("animatablePropertyName"); if (animatableProperty != null) { RemoveKeyFrames(stateContainerName.stringValue, animatablePropertyName.stringValue, j); } } animationTargetList.DeleteArrayElementAtIndex(j); break; } } using (new EditorGUILayout.VerticalScope()) { if (targetObj.objectReferenceValue != null) { InspectorUIUtility.DrawDivider(); GameObject targetGameObject = targetObj.objectReferenceValue as GameObject; // Ensure the target game object has a State Visualizer attached or is a child of an // object with State Visualizer attached if (targetGameObject.transform.FindAncestorComponent <StateVisualizer>(true)) { string animatablePropertiesFoldoutID = stateContainerName.stringValue + "AnimatableProperties" + "_" + targetGameObject.name + target.name; if (InspectorUIUtility.DrawSectionFoldoutWithKey(targetGameObject.name + " Animatable Properties", animatablePropertiesFoldoutID, MixedRealityStylesUtility.BoldFoldoutStyle, false)) { using (new EditorGUI.IndentLevelScope()) { RenderAnimatablePropertyList(animatablePropertyList, stateContainerName, j); } } } else { targetObj.objectReferenceValue = null; Debug.LogError("The target object must be itself or a child object"); } } EditorGUILayout.Space(); } } } EditorGUILayout.Space(); RenderAddTargetButton(animationTargetList); } }
private void RenderList(SerializedProperty list) { // Disable gestures list if we could not initialize successfully using (new EditorGUI.DisabledGroupScope(!isInitialized)) { EditorGUILayout.Space(); using (new EditorGUILayout.VerticalScope()) { if (InspectorUIUtility.RenderIndentedButton(AddButtonContent, EditorStyles.miniButton)) { list.arraySize += 1; var speechCommand = list.GetArrayElementAtIndex(list.arraySize - 1); var keyword = speechCommand.FindPropertyRelative("description"); keyword.stringValue = string.Empty; var gestureType = speechCommand.FindPropertyRelative("gestureType"); gestureType.intValue = (int)GestureInputType.None; var action = speechCommand.FindPropertyRelative("action"); var actionId = action.FindPropertyRelative("id"); actionId.intValue = 0; var actionDescription = action.FindPropertyRelative("description"); actionDescription.stringValue = string.Empty; var actionConstraint = action.FindPropertyRelative("axisConstraint"); actionConstraint.intValue = 0; } if (list == null || list.arraySize == 0) { EditorGUILayout.HelpBox("Define a new Gesture.", MessageType.Warning); UpdateGestureLabels(); return; } using (new EditorGUILayout.HorizontalScope()) { var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 24f; EditorGUILayout.LabelField(DescriptionContent, GUILayout.ExpandWidth(true)); EditorGUILayout.LabelField(GestureTypeContent, GUILayout.Width(80f)); EditorGUILayout.LabelField(ActionContent, GUILayout.Width(64f)); EditorGUILayout.LabelField(string.Empty, GUILayout.Width(24f)); EditorGUIUtility.labelWidth = labelWidth; } var inputActions = GetInputActions(); for (int i = 0; i < list.arraySize; i++) { using (new EditorGUILayout.HorizontalScope()) { SerializedProperty gesture = list.GetArrayElementAtIndex(i); var keyword = gesture.FindPropertyRelative("description"); var gestureType = gesture.FindPropertyRelative("gestureType"); var action = gesture.FindPropertyRelative("action"); var actionId = action.FindPropertyRelative("id"); var actionDescription = action.FindPropertyRelative("description"); var actionConstraint = action.FindPropertyRelative("axisConstraint"); EditorGUILayout.PropertyField(keyword, GUIContent.none, GUILayout.ExpandWidth(true)); Debug.Assert(allGestureLabels.Length == allGestureIds.Length); var gestureLabels = new GUIContent[allGestureLabels.Length + 1]; var gestureIds = new int[allGestureIds.Length + 1]; gestureLabels[0] = new GUIContent(((GestureInputType)gestureType.intValue).ToString()); gestureIds[0] = gestureType.intValue; for (int j = 0; j < allGestureLabels.Length; j++) { gestureLabels[j + 1] = allGestureLabels[j]; gestureIds[j + 1] = allGestureIds[j]; } EditorGUI.BeginChangeCheck(); gestureType.intValue = EditorGUILayout.IntPopup(GUIContent.none, gestureType.intValue, gestureLabels, gestureIds, GUILayout.Width(80f)); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); UpdateGestureLabels(); } EditorGUI.BeginChangeCheck(); actionId.intValue = EditorGUILayout.IntPopup(GUIContent.none, actionId.intValue, actionLabels, actionIds, GUILayout.Width(64f)); if (EditorGUI.EndChangeCheck()) { MixedRealityInputAction inputAction = MixedRealityInputAction.None; int idx = actionId.intValue - 1; if (idx >= 0 && idx < inputActions.Length) { inputAction = inputActions[idx]; } actionDescription.stringValue = inputAction.Description; actionConstraint.intValue = (int)inputAction.AxisConstraint; serializedObject.ApplyModifiedProperties(); } if (GUILayout.Button(MinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f))) { list.DeleteArrayElementAtIndex(i); serializedObject.ApplyModifiedProperties(); UpdateGestureLabels(); } } } } } }
private void DrawDebugSection() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Debug Options", ShowDebugOptionsPrefKey, MixedRealityStylesUtility.BoldFoldoutStyle)) { using (new EditorGUI.IndentLevelScope()) { using (var check = new EditorGUI.ChangeCheckScope()) { EditorGUILayout.PropertyField(maskEnabled); if (check.changed) { scrollView.MaskEnabled = maskEnabled.boolValue; } } using (new EditorGUI.DisabledGroupScope(EditorApplication.isPlaying)) { visibleDebugPlanes = EditorGUILayout.Toggle("Show Threshold Planes", visibleDebugPlanes); EditorGUILayout.Space(); } } using (new EditorGUI.IndentLevelScope()) { using (new EditorGUI.DisabledGroupScope(!EditorApplication.isPlaying)) { if (ShowDebugPagination = EditorGUILayout.Foldout(ShowDebugPagination, new GUIContent("Debug Pagination", "Pagination is only available during playmode."), MixedRealityStylesUtility.BoldFoldoutStyle)) { using (new EditorGUI.IndentLevelScope()) { animateTransition = EditorGUILayout.Toggle(new GUIContent("Animate", "Toggling will use animation to move scroller to new position."), animateTransition); using (new EditorGUILayout.HorizontalScope()) { debugPaginationMode = (PaginationMode)EditorGUILayout.EnumPopup(new GUIContent("Pagination Mode"), debugPaginationMode, GUILayout.Width(400.0f)); paginationMoveNumber = EditorGUILayout.IntField(paginationMoveNumber); if (GUILayout.Button("Move")) { switch (debugPaginationMode) { case PaginationMode.ByTier: default: scrollView.MoveByTiers(paginationMoveNumber, animateTransition); break; case PaginationMode.ByPage: scrollView.MoveByPages(paginationMoveNumber, animateTransition); break; case PaginationMode.ToCellIndex: scrollView.MoveToIndex(paginationMoveNumber, animateTransition); break; } } } } } } } } }
private void RenderSection(ToolboxCategory bucket) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { string key = $"MixedRealityToolboxWindow_{bucket.CategoryName}"; if (InspectorUIUtility.DrawSectionFoldoutWithKey(bucket.CategoryName, key, MixedRealityStylesUtility.BoldTitleFoldoutStyle)) { InspectorUIUtility.DrawDivider(); EditorGUILayout.Space(); bool isCategoryNameSearchMatch = IsSearchMatch(bucket.CategoryName, searchString); List <ToolboxItem> validItems = new List <ToolboxItem>(); foreach (var item in bucket.Items) { if (item != null && item.Prefab != null && (isCategoryNameSearchMatch || IsSearchMatch(item, searchString))) { validItems.Add(item); } } bool requiresCanvas = bucket.CategoryName.Contains(RequiresCanvas); if (requiresCanvas) { using (new EditorGUILayout.HorizontalScope()) { dropdownIndex = EditorGUILayout.Popup(CanvasDropdownContent, dropdownIndex, dropdownValues); if (GUILayout.Button(RefreshButtonContent, EditorStyles.miniButton, GUILayout.Width(ReloadButtonWidth))) { FindAllMRTKCanvases(); } } if (canvasUtilities.Length == 0) { GUIStyle CanvasWarningStyle = new GUIStyle(EditorStyles.textField) { wordWrap = true }; GUILayout.TextField("These MRTK components require an MRTK Canvas Utility on one of the Unity UI Canvases in the scene.\nNone were detected. Press refresh if you recently added any.\nTo create a MRTK Canvas: GameObject > UI > Canvas, and under the Canvas component in the inspector, click 'Convert to MRTK Canvas' button.", CanvasWarningStyle); } } EditorGUILayout.Space(); // Render grid of toolbox items int itemsPerRow = Mathf.Max((int)(position.width / ToolboxItemWidth), 1); for (int row = 0; row <= validItems.Count / itemsPerRow; row++) { using (new EditorGUILayout.HorizontalScope()) { int startIndex = row * itemsPerRow; for (int col = 0; col < itemsPerRow && startIndex + col < validItems.Count; col++) { var item = validItems[startIndex + col]; RenderToolboxItem(item, requiresCanvas); } } } } } }
public static void RenderEventSettings(SerializedProperty eventItem, int index, InteractableTypesContainer options, InspectorUIUtility.MultiListButtonEvent changeEvent, InspectorUIUtility.ListButtonEvent removeEvent) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); SerializedProperty uEvent = eventItem.FindPropertyRelative("Event"); SerializedProperty eventName = eventItem.FindPropertyRelative("Name"); SerializedProperty className = eventItem.FindPropertyRelative("ClassName"); SerializedProperty assemblyQualifiedName = eventItem.FindPropertyRelative("AssemblyQualifiedName"); SerializedProperty hideEvents = eventItem.FindPropertyRelative("HideUnityEvents"); // show event dropdown int id = InspectorUIUtility.ReverseLookup(className.stringValue, options.ClassNames); EditorGUILayout.BeginHorizontal(); Rect position = EditorGUILayout.GetControlRect(); GUIContent selectLabel = new GUIContent("Select Event Type", "Select the event type from the list"); EditorGUI.BeginProperty(position, selectLabel, className); { //int newId = EditorGUI.Popup(position, selectLabel.text, id, options.ClassNames); int newId = EditorGUI.Popup(position, id, options.ClassNames); if (id != newId || String.IsNullOrEmpty(className.stringValue)) { className.stringValue = options.ClassNames[newId]; assemblyQualifiedName.stringValue = options.AssemblyQualifiedNames[newId]; changeEvent(new int[] { index, newId }, eventItem); } } EditorGUI.EndProperty(); if (removeEvent != null) { InspectorUIUtility.FlexButton(new GUIContent("Remove Event"), index, removeEvent); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (!hideEvents.boolValue) { EditorGUILayout.PropertyField(uEvent, new GUIContent(eventName.stringValue)); } // show event properties SerializedProperty eventSettings = eventItem.FindPropertyRelative("Settings"); for (int j = 0; j < eventSettings.arraySize; j++) { SerializedProperty propertyField = eventSettings.GetArrayElementAtIndex(j); bool isEvent = InspectorFieldsUtility.IsPropertyType(propertyField, InspectorField.FieldTypes.Event); if (!hideEvents.boolValue || !isEvent) { InspectorFieldsUtility.DisplayPropertyField(eventSettings.GetArrayElementAtIndex(j)); } } EditorGUILayout.EndVertical(); }
/// <summary> /// Helper function to render header correctly for all profiles /// </summary> /// <param name="title">Title of profile</param> /// <param name="description">profile tooltip describing purpose</param> /// <param name="selectionObject">The profile object. Used to re-select the object after MRTK instance is created.</param> /// <param name="isProfileInitialized">profile properties are full initialized for rendering</param> /// <param name="backText">Text for back button if not rendering as sub-profile</param> /// <param name="backProfile">Target profile to return to if not rendering as sub-profile</param> /// <returns>True if the rest of the profile should be rendered.</returns> protected bool RenderProfileHeader(string title, string description, Object selectionObject, bool isProfileInitialized = true, BackProfileType returnProfileTarget = BackProfileType.Configuration) { if (!RenderMRTKLogoAndSearch()) { CheckEditorPlayMode(); return(false); } var profile = target as BaseMixedRealityProfile; if (!RenderAsSubProfile) { CheckEditorPlayMode(); if (!profile.IsCustomProfile) { EditorGUILayout.HelpBox("Default MRTK profiles cannot be edited. Create a clone of this profile to modify settings.", MessageType.Warning); if (GUILayout.Button(new GUIContent("Clone"))) { MixedRealityProfileCloneWindow.OpenWindow(null, (BaseMixedRealityProfile)target, null); } } if (IsProfileInActiveInstance()) { DrawBacktrackProfileButton(returnProfileTarget); } if (!isProfileInitialized) { if (!MixedRealityToolkit.IsInitialized) { EditorGUILayout.HelpBox("There is not a MRTK instance in your scene. Some properties may not be editable", MessageType.Error); if (InspectorUIUtility.RenderIndentedButton(new GUIContent("Add Mixed Reality Toolkit instance to scene"), EditorStyles.miniButton)) { MixedRealityInspectorUtility.AddMixedRealityToolkitToScene(MixedRealityInspectorUtility.GetDefaultConfigProfile()); // After the toolkit has been created, set the selection back to this item so the user doesn't get lost Selection.activeObject = selectionObject; } } else if (!MixedRealityToolkit.Instance.HasActiveProfile) { EditorGUILayout.HelpBox("There is no active profile assigned in the current MRTK instance. Some properties may not be editable.", MessageType.Error); } } } else { if (!isProfileInitialized && profile.IsCustomProfile) { EditorGUILayout.HelpBox("Some properties may not be editable in this profile. Please refer to the error messages below to resolve editing.", MessageType.Warning); } } using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField(new GUIContent(title, description), EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); RenderDocumentation(selectionObject); } EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider); return(true); }