private void RenderEventSettings() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Events", ShowEventsPrefKey, MixedRealityStylesUtility.BoldTitleFoldoutStyle)) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUILayout.PropertyField(serializedObject.FindProperty("OnClick"), OnClickEventLabel); if (InspectorUIUtility.DrawSectionFoldoutWithKey("Receivers", ShowEventReceiversPrefKey, MixedRealityStylesUtility.TitleFoldoutStyle, false)) { SerializedProperty events = serializedObject.FindProperty("Events"); for (int i = 0; i < events.arraySize; i++) { SerializedProperty eventItem = events.GetArrayElementAtIndex(i); if (InteractableEventInspector.RenderEvent(eventItem)) { events.DeleteArrayElementAtIndex(i); // If removed, skip rendering rest of list till next redraw break; } EditorGUILayout.Space(); } if (GUILayout.Button(AddEventReceiverLabel)) { AddEvent(events.arraySize); } } } } }
private void RenderEventSettings() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Events", ShowEventsPrefKey, MixedRealityStylesUtility.TitleFoldoutStyle)) { EditorGUILayout.Space(); SerializedProperty onClick = serializedObject.FindProperty("OnClick"); EditorGUILayout.PropertyField(onClick, new GUIContent("OnClick")); SerializedProperty events = serializedObject.FindProperty("Events"); for (int i = 0; i < events.arraySize; i++) { SerializedProperty eventItem = events.GetArrayElementAtIndex(i); if (InteractableEventInspector.RenderEvent(eventItem)) { events.DeleteArrayElementAtIndex(i); // If removed, skip rendering rest of list till next redraw break; } EditorGUILayout.Space(); } if (GUILayout.Button(new GUIContent("Add Event"))) { AddEvent(events.arraySize); } } }
private void DrawAdvancedSettingsSection() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Advanced settings", ShowAdvancedPrefKey, MixedRealityStylesUtility.BoldFoldoutStyle)) { using (new EditorGUI.IndentLevelScope(2)) { EditorGUILayout.PropertyField(maskEditMode); EditorGUILayout.PropertyField(colliderEditMode); EditorGUILayout.Space(); EditorGUILayout.PropertyField(canScroll); EditorGUILayout.Space(); EditorGUILayout.PropertyField(useCameraPreRender); EditorGUILayout.Space(); EditorGUILayout.PropertyField(animationCurve); EditorGUILayout.PropertyField(animationLength); EditorGUILayout.Space(); EditorGUILayout.PropertyField(handDeltaScrollThreshold); EditorGUILayout.PropertyField(frontTouchDistance); EditorGUILayout.Space(); DrawTouchReleaseThresholdsSection(); EditorGUILayout.Space(); DrawVelocitySection(); EditorGUILayout.Space(); DrawDebugSection(); EditorGUILayout.Space(); } } }
private void DrawPeformanceSection() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Performance Options", ShowPerformanceOptionsPrefKey, MixedRealityStylesUtility.BoldFoldoutStyle)) { EditorGUILayout.PropertyField(disableClippedGameObjects); EditorGUILayout.PropertyField(disableClippedRenderers); } }
private void DrawEventsSection() { if (InspectorUIUtility.DrawSectionFoldoutWithKey("Events", ShowEventsPrefKey, MixedRealityStylesUtility.BoldFoldoutStyle)) { using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.PropertyField(clickEvent); EditorGUILayout.PropertyField(touchStartedEvent); EditorGUILayout.PropertyField(touchEndedEvent); EditorGUILayout.PropertyField(momentumStartedEvent); EditorGUILayout.PropertyField(momentumEndedEvent); EditorGUILayout.Space(); } } }
// Render the Advanced Properties under an indented foldout titled Advanced Properties private void RenderAdvancedProperties() { // Render Advanced Settings if (InspectorUIUtility.DrawSectionFoldoutWithKey("Advanced Properties", AdvancedPropertiesFoldoutKey, MixedRealityStylesUtility.TitleFoldoutStyle, false)) { using (new EditorGUI.IndentLevelScope()) { EditorGUILayout.Space(); EditorGUILayout.PropertyField(updateLinkedTransformProperty); EditorGUILayout.PropertyField(moveLerpTimeProperty); EditorGUILayout.PropertyField(rotateLerpTimeProperty); EditorGUILayout.PropertyField(scaleLerpTimeProperty); EditorGUILayout.PropertyField(maintainScaleProperty); EditorGUILayout.PropertyField(smoothingProperty); EditorGUILayout.PropertyField(lifetimeProperty); EditorGUILayout.PropertyField(magneticSurfaces, true); } } }
private void RenderProfileSettings() { if (profileList.arraySize < 1) { AddProfile(0); } if (InspectorUIUtility.DrawSectionFoldoutWithKey("Profiles", ShowProfilesPrefKey, MixedRealityStylesUtility.BoldTitleFoldoutStyle)) { // Render all profile items. Profiles are per GameObject/ThemeContainer for (int i = 0; i < profileList.arraySize; i++) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { SerializedProperty profileItem = profileList.GetArrayElementAtIndex(i); SerializedProperty hostGameObject = profileItem.FindPropertyRelative("Target"); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.PropertyField(hostGameObject, new GUIContent("Target", "Target gameObject for this theme properties to manipulate")); if (InspectorUIUtility.SmallButton(new GUIContent(InspectorUIUtility.Minus, "Remove Profile"), i, RemoveProfile)) { // Profile removed via RemoveProfile callback continue; } } if (hostGameObject.objectReferenceValue == null) { InspectorUIUtility.DrawError("Assign a GameObject to apply visual effects"); if (GUILayout.Button("Assign Self")) { hostGameObject.objectReferenceValue = instance.gameObject; } } SerializedProperty themes = profileItem.FindPropertyRelative("Themes"); ValidateThemesForDimensions(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); if (themeItem.objectReferenceValue != null) { bool showThemeSettings = false; using (new EditorGUILayout.HorizontalScope()) { string prefKey = themeItem.objectReferenceValue.name + "Profiles" + i + "_Theme" + t + "_Edit"; showThemeSettings = InspectorUIUtility.DrawSectionFoldoutWithKey(themeLabel, prefKey, null, false); EditorGUILayout.PropertyField(themeItem, new GUIContent(string.Empty, "Theme properties for interaction feedback")); } if (themeItem.objectReferenceValue != null) { // TODO: Odd bug where themeStates below is null when it shouldn't be. Use instance object as workaround atm //SerializedProperty themeStates = themeItem.FindPropertyRelative("States"); var themeInstance = themeItem.objectReferenceValue as Theme; if (statesProperty.objectReferenceValue != themeInstance.States) { InspectorUIUtility.DrawWarning($"{themeInstance.name}'s States property does not match Interactable's States property"); } if (showThemeSettings) { using (new EditorGUI.IndentLevelScope()) { UnityEditor.Editor themeEditor = UnityEditor.Editor.CreateEditor(themeItem.objectReferenceValue); themeEditor.OnInspectorGUI(); } } } } else { EditorGUILayout.PropertyField(themeItem, new GUIContent(themeLabel, "Theme properties for interaction feedback")); InspectorUIUtility.DrawError("Assign a Theme to add visual effects"); if (GUILayout.Button(CreateThemeLabel)) { themeItem.objectReferenceValue = CreateThemeAsset(hostGameObject.objectReferenceValue.name); return; } } EditorGUILayout.Space(); } } } if (GUILayout.Button(new GUIContent("Add Profile"))) { AddProfile(profileList.arraySize); } } }
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 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); } } } } } }
private void RenderStates() { // Draw a States title for the State list section InspectorUIUtility.DrawTitle(statesLabel); for (int i = 0; i < states.arraySize; i++) { SerializedProperty state = states.GetArrayElementAtIndex(i); SerializedProperty stateName = state.FindPropertyRelative("stateName"); SerializedProperty stateValue = state.FindPropertyRelative("stateValue"); SerializedProperty stateEventConfiguration = state.FindPropertyRelative("eventConfiguration"); using (new EditorGUILayout.HorizontalScope()) { string stateFoldoutID = stateName.stringValue + "_" + target.name; Color previousGUIColor = GUI.color; if (inPlayMode) { // If the state is active, then highlight the state container with a new color if (stateValue.intValue == 1) { GUI.color = Color.cyan; } } using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUILayout.Space(); // Draw a foldout for the state configuration if (InspectorUIUtility.DrawSectionFoldoutWithKey(stateName.stringValue, stateFoldoutID, MixedRealityStylesUtility.TitleFoldoutStyle, true)) { EditorGUILayout.Space(); using (new EditorGUILayout.VerticalScope()) { using (new EditorGUI.IndentLevelScope()) { // Show the event configuration for the state RenderStateEventConfiguration(stateName, stateEventConfiguration); CheckSpecialCaseStates(stateName.stringValue, stateEventConfiguration); // When a new core state is added via inspector, the name is initialized to "New Core State" and then changed // to the name the user selects from the list of CoreInteractionStates if (stateName.stringValue == newCoreStateName) { SetCoreStateType(state, stateName); } // When a new state is added via inspector, the name is initialized to "Create Custom State" and then changed // to the name the user enters a name in the text field and then selects the "Set State Name" button if (stateName.stringValue == createCustomStateName) { SetUserDefinedState(stateName); } } } } EditorGUILayout.Space(); } // Do not draw a remove button during play mode if (!inPlayMode) { if (CanDrawRemoveButton(stateName.stringValue)) { // Draw a button with a '-' for state removal if (InspectorUIUtility.SmallButton(RemoveStateButtonLabel)) { states.DeleteArrayElementAtIndex(i); break; } } } // Draw the state value in the inspector next to the state during play mode for debugging if (inPlayMode) { using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox, GUILayout.Width(stateValueDisplayWidth))) { EditorGUILayout.Space(); EditorGUILayout.LabelField(stateValue.intValue.ToString(), GUILayout.Width(stateValueDisplayContainerWidth)); EditorGUILayout.Space(); } } GUI.color = previousGUIColor; } } }
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 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); } }