private void HistoryButton(GUIContent content, List <SelectionInfo> stack, List <SelectionInfo> otherStack) { GUI.enabled = (stack.Count > 0); SidekickEditorGUI.ButtonWithOptions(content, out bool mainPressed, out bool optionsPressed); if (mainPressed) { SwapStackElements(stack, otherStack); } if (optionsPressed) { GenericMenu genericMenu = new GenericMenu(); for (var index = 0; index < stack.Count; index++) { SelectionInfo selectionInfo = stack[index]; genericMenu.AddItem(new GUIContent($"{index} - {selectionInfo.GetDisplayName()}"), false, userData => { SwapStackElements(stack, otherStack, 1 + (int)userData); }, index); } genericMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } }
public void PostDraw() { SidekickEditorGUI.DrawSplitter(); GUILayout.Label("Output", EditorStyles.boldLabel); outputScrollPosition = EditorGUILayout.BeginScrollView(outputScrollPosition, GUILayout.MaxHeight(100)); foreach (var outputObject in outputObjects) { if (TypeUtility.IsNotNull(outputObject)) { string name = outputObject switch { Object unityObject => $"{unityObject.name}", _ => outputObject.ToString() }; if (GUILayout.Button($"Select {name} ({TypeUtility.NameForType(outputObject.GetType())})")) { SidekickWindow.Current.SetSelection(outputObject); } } else { using (new EditorGUI.DisabledScope(true)) { GUILayout.Button("null"); } } } if (opacity > 0) { Rect lastRect = GUILayoutUtility.GetLastRect(); Color baseColor = new Color(0, 0, 1, 0.3f * opacity); GUI.color = baseColor; GUI.DrawTexture(lastRect, EditorGUIUtility.whiteTexture); baseColor.a = 0.8f * opacity; GUI.color = baseColor; float lineThickness = 2; GUI.DrawTexture(new Rect(lastRect.xMin, lastRect.yMin, lineThickness, lastRect.height), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(lastRect.xMax - lineThickness, lastRect.yMin, lineThickness, lastRect.height), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(lastRect.xMin + lineThickness, lastRect.yMin, lastRect.width - lineThickness * 2, lineThickness), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(lastRect.xMin + lineThickness, lastRect.yMax - lineThickness, lastRect.width - lineThickness * 2, lineThickness), EditorGUIUtility.whiteTexture); GUI.color = Color.white; opacity -= AnimationHelper.DeltaTime; AnimationHelper.SetAnimationActive(); } EditorGUILayout.EndScrollView(); }
void OnGUI() { // Frame rate tracking if (Event.current.type == EventType.Repaint) { AnimationHelper.UpdateTime(); } GUILayout.Space(9); SidekickSettings settings = Settings; EditorGUI.BeginChangeCheck(); InspectionConnection newConnectionMode = (InspectionConnection)GUILayout.Toolbar((int)settings.InspectionConnection, new string[] { "Local", "Remote" }, new GUIStyle("LargeButton")); if (EditorGUI.EndChangeCheck()) { SetConnectionMode(newConnectionMode); } settings.SearchTerm = searchField2.OnGUI(settings.SearchTerm); GUILayout.Space(3); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Display"); settings.GetGameObjectFlags = SidekickEditorGUI.EnumFlagsToggle(settings.GetGameObjectFlags, InfoFlags.Fields, "Fields"); settings.GetGameObjectFlags = SidekickEditorGUI.EnumFlagsToggle(settings.GetGameObjectFlags, InfoFlags.Properties, "Properties"); settings.GetGameObjectFlags = SidekickEditorGUI.EnumFlagsToggle(settings.GetGameObjectFlags, InfoFlags.Methods, "Methods"); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { if (!string.IsNullOrEmpty(SelectionManager.SelectedPath)) // Valid path? { APIManager.SendToPlayers(new GetGameObjectRequest(SelectionManager.SelectedPath, Settings.GetGameObjectFlags, Settings.IncludeInherited)); } } scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); if (gameObjectResponse != null) { string activeSearchTerm = settings.SearchTerm; foreach (ComponentDescription component in gameObjectResponse.Components) { SidekickEditorGUI.DrawSplitter(); GUIStyle style = new GUIStyle(EditorStyles.foldout); style.fontStyle = FontStyle.Bold; Texture icon = IconLookup.GetIcon(component.TypeFullName); GUIContent content = new GUIContent(component.TypeShortName, icon, "Object Map ID: " + component.Guid.ToString()); float labelWidth = EditorGUIUtility.labelWidth; // Cache label width // Temporarily set the label width to full width so the icon is not squashed with long strings EditorGUIUtility.labelWidth = position.width / 2f; bool wasComponentExpanded = !settings.CollapsedTypeNames.Contains(component.TypeFullName); bool isComponentExpanded = wasComponentExpanded; bool?activeOrEnabled = null; if (component.TypeShortName == "GameObject" && (settings.GetGameObjectFlags & InfoFlags.Properties) != 0) { activeOrEnabled = (bool)component.Scopes[0].GetPropertyValue("activeSelf"); } else { ComponentScope behaviourScope = component.BehaviourScope; if (behaviourScope != null && (settings.GetGameObjectFlags & InfoFlags.Properties) != 0) { activeOrEnabled = (bool)behaviourScope.GetPropertyValue("enabled"); } } bool?oldActiveOrEnabled = activeOrEnabled; if (SidekickEditorGUI.DrawHeaderWithFoldout(content, isComponentExpanded, ref activeOrEnabled)) { isComponentExpanded = !isComponentExpanded; } if (activeOrEnabled.HasValue && activeOrEnabled != oldActiveOrEnabled) { if (component.TypeShortName == "GameObject") { // Update local cache (requires method call) var property = component.Scopes[0].GetProperty("activeSelf"); property.Value = activeOrEnabled.Value; // Update via method call APIManager.SendToPlayers(new InvokeMethodRequest(component.Guid, "SetActive", new WrappedVariable[] { new WrappedVariable("", activeOrEnabled.Value, typeof(bool), false) })); } else if (component.BehaviourScope != null) { // Update local cache, then ship via SetVariable var property = component.BehaviourScope.GetProperty("enabled"); property.Value = activeOrEnabled.Value; APIManager.SendToPlayers(new SetVariableRequest(component.Guid, property)); } } EditorGUIUtility.labelWidth = labelWidth; // Restore label width if (isComponentExpanded != wasComponentExpanded) { if (isComponentExpanded == false) { // Not expanded, so collapse it settings.CollapsedTypeNames.Add(component.TypeFullName); } else { // Expanded, remove it from collapse list settings.CollapsedTypeNames.Remove(component.TypeFullName); } } if (isComponentExpanded) { foreach (ComponentScope scope in component.Scopes) { if (scope.TypeFullName != component.TypeFullName) { SidekickEditorGUI.DrawHeader2(new GUIContent(": " + scope.TypeShortName)); } ObjectPickerContext objectPickerContext = new ObjectPickerContext(component.Guid); foreach (var field in scope.Fields) { if (!string.IsNullOrEmpty(activeSearchTerm) && !field.VariableName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (field.Attributes & VariableAttributes.Obsolete) == VariableAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } EditorGUI.BeginChangeCheck(); object newValue = VariableDrawer.Draw(objectPickerContext, field, OnOpenObjectPicker); if (EditorGUI.EndChangeCheck() && (field.Attributes & VariableAttributes.ReadOnly) == VariableAttributes.None && field.DataType != DataType.Unknown) { if (newValue != field.Value || field.Attributes.HasFlagByte(VariableAttributes.IsList) || field.Attributes.HasFlagByte(VariableAttributes.IsArray)) { field.Value = newValue; APIManager.SendToPlayers(new SetVariableRequest(component.Guid, field)); } //Debug.Log("Value changed in " + field.VariableName); } } foreach (var property in scope.Properties) { if (!string.IsNullOrEmpty(activeSearchTerm) && !property.VariableName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (property.Attributes & VariableAttributes.Obsolete) == VariableAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } EditorGUI.BeginChangeCheck(); object newValue = VariableDrawer.Draw(objectPickerContext, property, OnOpenObjectPicker); if (EditorGUI.EndChangeCheck() && (property.Attributes & VariableAttributes.ReadOnly) == VariableAttributes.None && property.DataType != DataType.Unknown) { if (newValue != property.Value || property.Attributes.HasFlagByte(VariableAttributes.IsList) || property.Attributes.HasFlagByte(VariableAttributes.IsArray)) { property.Value = newValue; APIManager.SendToPlayers(new SetVariableRequest(component.Guid, property)); } //Debug.Log("Value changed in " + property.VariableName); } } GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; GUIStyle labelStyle = new GUIStyle(GUI.skin.label); labelStyle.alignment = TextAnchor.MiddleRight; GUIStyle normalButtonStyle = new GUIStyle(GUI.skin.button); normalButtonStyle.padding = normalButtonStyle.padding.SetLeft(100); normalButtonStyle.alignment = TextAnchor.MiddleLeft; foreach (var method in scope.Methods) { if (!string.IsNullOrEmpty(activeSearchTerm) && !method.MethodName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (method.MethodAttributes & MethodAttributes.Obsolete) == MethodAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } if (method.SafeToFire == false) { EditorGUI.BeginDisabledGroup(true); } GUILayout.BeginHorizontal(); if (method.ReturnType == DataType.Void) { labelStyle.normal.textColor = Color.grey; } else if ((method.ReturnTypeAttributes & VariableAttributes.IsValueType) == VariableAttributes.IsValueType) { labelStyle.normal.textColor = new Color(0, 0, 1); } else { labelStyle.normal.textColor = new Color32(255, 130, 0, 255); } string displayText = method.MethodName + " (" + method.ParameterCount + ")"; if ((method.MethodAttributes & MethodAttributes.Static) == MethodAttributes.Static) { displayText += " [Static]"; } if (method.SafeToFire == false) { displayText += " [Unsupported]"; } bool wasMethodExpanded = (method.Equals(expandedMethod)); if (GUILayout.Button(displayText, normalButtonStyle)) { if (wasMethodExpanded) { APIManager.SendToPlayers(new InvokeMethodRequest(component.Guid, method.MethodName, arguments.ToArray())); } else { // Not expanded, just use the default values List <WrappedVariable> defaultArguments = new List <WrappedVariable>(); for (int i = 0; i < method.ParameterCount; i++) { WrappedParameter parameter = method.Parameters[i]; defaultArguments.Add(new WrappedVariable(parameter)); } APIManager.SendToPlayers(new InvokeMethodRequest(component.Guid, method.MethodName, defaultArguments.ToArray())); } } Rect lastRect = GUILayoutUtility.GetLastRect(); lastRect.xMax = normalButtonStyle.padding.left; GUI.Label(lastRect, TypeUtility.NameForType(method.ReturnType), labelStyle); if (method.ParameterCount > 0) { bool isMethodExpanded = GUILayout.Toggle(wasMethodExpanded, "▼", expandButtonStyle, GUILayout.Width(20)); GUILayout.EndHorizontal(); if (isMethodExpanded != wasMethodExpanded) // has changed { if (isMethodExpanded) { // Reset the keyboard control as we don't want old text carrying over GUIUtility.keyboardControl = 0; expandedMethod = method; arguments = new List <WrappedVariable>(method.ParameterCount); for (int i = 0; i < method.ParameterCount; i++) { WrappedParameter parameter = method.Parameters[i]; arguments.Add(new WrappedVariable(parameter)); } } else { expandedMethod = null; arguments = null; } } else if (isMethodExpanded) { EditorGUI.indentLevel++; for (int i = 0; i < arguments.Count; i++) { var argument = arguments[i]; argument.Value = VariableDrawer.Draw(new ObjectPickerContext(i), argument, OnOpenObjectPicker); //argument.Value = VariableDrawer.DrawIndividualVariable(null, argument, argument.VariableName, DataTypeHelper.GetSystemTypeFromWrappedDataType(argument.DataType), argument.Value, OnOpenObjectPicker); } //Rect buttonRect = GUILayoutUtility.GetRect(new GUIContent(), GUI.skin.button); //buttonRect = EditorGUI.IndentedRect(buttonRect); EditorGUI.indentLevel--; GUILayout.Space(10); } } else { GUILayout.EndHorizontal(); } if (method.SafeToFire == false) { EditorGUI.EndDisabledGroup(); } } } } } SidekickEditorGUI.DrawSplitter(); } EditorGUILayout.EndScrollView(); DrawOutputBox(); }
void OnGUI() { // Frame rate tracking if (Event.current.type == EventType.Repaint) { AnimationHelper.UpdateTime(); } GUILayout.Space(9); SidekickSettings settings = commonContext.Settings; EditorGUI.BeginChangeCheck(); InspectionConnection newConnectionMode = (InspectionConnection)GUILayout.Toolbar((int)settings.InspectionConnection, new string[] { "Local", "Remote" }, new GUIStyle("LargeButton")); if (EditorGUI.EndChangeCheck()) { SetConnectionMode(newConnectionMode); } settings.SearchTerm = searchField2.OnGUI(settings.SearchTerm); GUILayout.Space(3); EditorGUI.BeginChangeCheck(); #if UNITY_2017_3_OR_NEWER // EnumMaskField became EnumFlagsField in 2017.3 settings.GetGameObjectFlags = (InfoFlags)EditorGUILayout.EnumFlagsField("Display", settings.GetGameObjectFlags); #else settings.GetGameObjectFlags = (InfoFlags)EditorGUILayout.EnumMaskField("Display", settings.GetGameObjectFlags); #endif if (EditorGUI.EndChangeCheck()) { if (!string.IsNullOrEmpty(commonContext.SelectionManager.SelectedPath)) // Valid path? { commonContext.APIManager.SendToPlayers(new GetGameObjectRequest(commonContext.SelectionManager.SelectedPath, commonContext.Settings.GetGameObjectFlags, commonContext.Settings.IncludeInherited)); } } scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); if (gameObjectResponse != null) { string activeSearchTerm = settings.SearchTerm; foreach (ComponentDescription component in gameObjectResponse.Components) { SidekickEditorGUI.DrawSplitter(); GUIStyle style = new GUIStyle(EditorStyles.foldout); style.fontStyle = FontStyle.Bold; Texture icon = IconLookup.GetIcon(component.TypeFullName); GUIContent content = new GUIContent(component.TypeShortName, icon, "Object Map ID: " + component.Guid.ToString()); float labelWidth = EditorGUIUtility.labelWidth; // Cache label width // Temporarily set the label width to full width so the icon is not squashed with long strings EditorGUIUtility.labelWidth = position.width / 2f; bool wasComponentExpanded = !settings.CollapsedTypeNames.Contains(component.TypeFullName); bool isComponentExpanded = wasComponentExpanded; if (SidekickEditorGUI.DrawHeaderWithFoldout(content, isComponentExpanded)) { isComponentExpanded = !isComponentExpanded; } EditorGUIUtility.labelWidth = labelWidth; // Restore label width if (isComponentExpanded != wasComponentExpanded) { if (isComponentExpanded == false) { // Not expanded, so collapse it settings.CollapsedTypeNames.Add(component.TypeFullName); } else { // Expanded, remove it from collapse list settings.CollapsedTypeNames.Remove(component.TypeFullName); } } if (isComponentExpanded) { foreach (var field in component.Fields) { if (!string.IsNullOrEmpty(activeSearchTerm) && !field.VariableName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (field.Attributes & VariableAttributes.Obsolete) == VariableAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } EditorGUI.BeginChangeCheck(); object newValue = VariableDrawer.Draw(component, field, OnOpenObjectPicker); if (EditorGUI.EndChangeCheck() && (field.Attributes & VariableAttributes.ReadOnly) == VariableAttributes.None && field.DataType != DataType.Unknown) { if (newValue != field.Value) { field.Value = newValue; commonContext.APIManager.SendToPlayers(new SetVariableRequest(component.Guid, field)); } //Debug.Log("Value changed in " + field.VariableName); } } foreach (var property in component.Properties) { if (!string.IsNullOrEmpty(activeSearchTerm) && !property.VariableName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (property.Attributes & VariableAttributes.Obsolete) == VariableAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } EditorGUI.BeginChangeCheck(); object newValue = VariableDrawer.Draw(component, property, OnOpenObjectPicker); if (EditorGUI.EndChangeCheck() && (property.Attributes & VariableAttributes.ReadOnly) == VariableAttributes.None && property.DataType != DataType.Unknown) { if (newValue != property.Value) { property.Value = newValue; commonContext.APIManager.SendToPlayers(new SetVariableRequest(component.Guid, property)); } //Debug.Log("Value changed in " + property.VariableName); } } GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; GUIStyle labelStyle = new GUIStyle(GUI.skin.label); labelStyle.alignment = TextAnchor.MiddleRight; GUIStyle normalButtonStyle = new GUIStyle(GUI.skin.button); normalButtonStyle.padding = normalButtonStyle.padding.SetLeft(100); normalButtonStyle.alignment = TextAnchor.MiddleLeft; foreach (var method in component.Methods) { if (!string.IsNullOrEmpty(activeSearchTerm) && !method.MethodName.Contains(activeSearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Active search term not matched, skip it continue; } if (settings.IgnoreObsolete && (method.MethodAttributes & MethodAttributes.Obsolete) == MethodAttributes.Obsolete) { // Skip obsolete entries if that setting is enabled continue; } GUILayout.BeginHorizontal(); if (method.ReturnType == DataType.Void) { labelStyle.normal.textColor = Color.grey; } else if ((method.ReturnTypeAttributes & VariableAttributes.IsValueType) == VariableAttributes.IsValueType) { labelStyle.normal.textColor = new Color(0, 0, 1); } else { labelStyle.normal.textColor = new Color32(255, 130, 0, 255); } string displayText = method.MethodName + " (" + method.ParameterCount + ")"; if ((method.MethodAttributes & MethodAttributes.Static) == MethodAttributes.Static) { displayText += " [Static]"; } if (GUILayout.Button(displayText, normalButtonStyle)) { List <WrappedVariable> defaultArguments = new List <WrappedVariable>(); for (int i = 0; i < method.ParameterCount; i++) { //Type type = DataTypeHelper.GetSystemTypeFromWrappedDataType(method.Parameters[i].DataType); WrappedParameter parameter = method.Parameters[i]; defaultArguments.Add(new WrappedVariable(parameter)); } commonContext.APIManager.SendToPlayers(new InvokeMethodRequest(component.Guid, method.MethodName, defaultArguments.ToArray())); } Rect lastRect = GUILayoutUtility.GetLastRect(); lastRect.xMax = normalButtonStyle.padding.left; GUI.Label(lastRect, TypeUtility.NameForType(method.ReturnType), labelStyle); if (method.ParameterCount > 0) { bool wasMethodExpanded = (method.Equals(expandedMethod)); bool isMethodExpanded = GUILayout.Toggle(wasMethodExpanded, "▼", expandButtonStyle, GUILayout.Width(20)); GUILayout.EndHorizontal(); if (isMethodExpanded != wasMethodExpanded) // has changed { if (isMethodExpanded) { expandedMethod = method; arguments = new List <WrappedVariable>(method.ParameterCount); for (int i = 0; i < method.ParameterCount; i++) { WrappedParameter parameter = method.Parameters[i]; arguments.Add(new WrappedVariable(parameter)); } } else { expandedMethod = null; arguments = null; } } else if (isMethodExpanded) { EditorGUI.indentLevel++; foreach (var argument in arguments) { argument.Value = VariableDrawer.Draw(null, argument, OnOpenObjectPicker); //argument.Value = VariableDrawer.DrawIndividualVariable(null, argument, argument.VariableName, DataTypeHelper.GetSystemTypeFromWrappedDataType(argument.DataType), argument.Value, OnOpenObjectPicker); } Rect buttonRect = GUILayoutUtility.GetRect(new GUIContent(), GUI.skin.button); buttonRect = EditorGUI.IndentedRect(buttonRect); if (GUI.Button(buttonRect, "Fire")) { commonContext.APIManager.SendToPlayers(new InvokeMethodRequest(component.Guid, method.MethodName, arguments.ToArray())); } EditorGUI.indentLevel--; GUILayout.Space(10); } } else { GUILayout.EndHorizontal(); } } } } SidekickEditorGUI.DrawSplitter(); } EditorGUILayout.EndScrollView(); DrawOutputBox(); }
void OnGUI() { // Flexible width for the label based on overall width EditorGUIUtility.labelWidth = Mathf.Round(EditorGUIUtility.currentViewWidth * 0.4f); // Use inline controls if there is enough horizontal room EditorGUIUtility.wideMode = EditorGUIUtility.currentViewWidth > 400; // Frame rate tracking if (Event.current.type == EventType.Repaint) { AnimationHelper.UpdateTime(); } current = this; CleanStacks(); DrawToolbar(); Type[] inspectedTypes = null; object[] inspectedContexts = null; ECSContext[] inspectedECSContexts = null; GUILayout.Space(9); string buttonPrefix = ""; #if ECS_EXISTS int selectionWrapWidth = 465; #else int selectionWrapWidth = 400; #endif if (EditorGUIUtility.currentViewWidth > selectionWrapWidth) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("Selection Helpers"); } else { buttonPrefix = "Select "; } var popupRect = GUILayoutUtility.GetLastRect(); popupRect.width = EditorGUIUtility.currentViewWidth; if (GUILayout.Button(new GUIContent(buttonPrefix + "Type From Assembly"), EditorStyles.miniButton)) { TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), SetSelection); dropdown.Show(popupRect); } if (GUILayout.Button(new GUIContent(buttonPrefix + "Loaded Unity Object"), EditorStyles.miniButton)) { UnityObjectSelectDropdown dropdown = new UnityObjectSelectDropdown(new AdvancedDropdownState(), SetSelection); dropdown.Show(popupRect); } #if ECS_EXISTS if (GUILayout.Button(new GUIContent(buttonPrefix + "ECS System"), EditorStyles.miniButton)) { ECSSystemSelectDropdown dropdown = new ECSSystemSelectDropdown(new AdvancedDropdownState(), SetSelection); dropdown.Show(popupRect); } #endif if (EditorGUIUtility.currentViewWidth > selectionWrapWidth) { EditorGUILayout.EndHorizontal(); } if (activeSelection.IsEmpty) { GUILayout.FlexibleSpace(); GUIStyle style = new GUIStyle(EditorStyles.wordWrappedLabel) { alignment = TextAnchor.MiddleCenter }; GUILayout.Label("No object selected.\n\nSelect something in Unity or use one of the selection helper buttons.", style); GUILayout.FlexibleSpace(); return; } if (activeSelection.Object != null) { if (activeSelection.Object is GameObject selectedGameObject) { List <object> components = selectedGameObject.GetComponents <Component>().Cast <object>().ToList(); components.RemoveAll(item => item == null); components.Insert(0, selectedGameObject); inspectedContexts = components.ToArray(); } #if ECS_EXISTS else if (activeSelection.Object is EntitySelectionProxy entitySelectionProxy) { EntityManager currentEntityManager = entitySelectionProxy.World.EntityManager; string name = currentEntityManager.GetName(entitySelectionProxy.Entity); if (string.IsNullOrEmpty(name)) { name = "Entity " + entitySelectionProxy.Entity.Index; } inspectedContexts = new object [1 + currentEntityManager.GetComponentCount(entitySelectionProxy.Entity)]; inspectedContexts[0] = activeSelection.Object; inspectedECSContexts = new ECSContext[1 + currentEntityManager.GetComponentCount(entitySelectionProxy.Entity)]; inspectedECSContexts[0] = new ECSContext { EntityManager = currentEntityManager, Entity = entitySelectionProxy.Entity }; NativeArray <ComponentType> types = currentEntityManager.GetComponentTypes(entitySelectionProxy.Entity); for (var index = 0; index < types.Length; index++) { object componentData = ECSAccess.GetComponentData(currentEntityManager, entitySelectionProxy.Entity, types[index]); inspectedContexts[1 + index] = componentData; inspectedECSContexts[1 + index] = new ECSContext { EntityManager = currentEntityManager, Entity = entitySelectionProxy.Entity, ComponentType = types[index] }; } types.Dispose(); } #endif else { inspectedContexts = new[] { activeSelection.Object }; } inspectedTypes = inspectedContexts.Select(x => x.GetType()).ToArray(); } else { inspectedTypes = new[] { activeSelection.Type }; inspectedContexts = new Type[] { null }; } if (inspectedECSContexts == null) { inspectedECSContexts = new ECSContext[inspectedContexts.Length]; } GUILayout.Space(5); searchTerm = searchField.OnToolbarGUI(searchTerm); SidekickEditorGUI.BeginLabelHighlight(searchTerm); mode = SidekickUtility.EnumToolbar(mode); GUILayout.Space(5); scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); for (int i = 0; i < inspectedTypes.Length; i++) { Type type = inspectedTypes[i]; var inspectedContext = inspectedContexts[i]; var inspectedECSContext = inspectedECSContexts[i]; bool?activeOrEnabled = inspectedContext switch { GameObject gameObject => gameObject.activeSelf, Behaviour behaviour => behaviour.enabled, _ => null }; if (typesHidden.All(row => row.Key != type)) { typesHidden.Add(new KeyValuePair <Type, bool>(type, false)); } int index = typesHidden.FindIndex(row => row.Key == type); string name; if (inspectedContexts[0] != null) { if (activeOrEnabled.HasValue) { name = " " + type.Name; } else { name = " " + type.Name; } if (i == 0 && inspectedContexts[i] is Object unityObject) { name += $" ({unityObject.name})"; } } else { name = type.Name + " (Class)"; } GUIContent content = new GUIContent(name, $"{type.FullName}, {type.Assembly.FullName}"); Rect foldoutRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.foldoutHeader); Rect toggleRect = foldoutRect; toggleRect.xMin += 36; toggleRect.width = 20; Rect iconRect = foldoutRect; iconRect.xMin += 16; iconRect.yMin += 1; iconRect.height = iconRect.width = 16; // Have to do this before BeginFoldoutHeaderGroup otherwise it'll consume the mouse down event if (activeOrEnabled.HasValue && SidekickEditorGUI.DetectClickInRect(toggleRect)) { switch (inspectedContexts[i]) { case GameObject gameObject: gameObject.SetActive(!gameObject.activeSelf); break; case Behaviour behaviour: behaviour.enabled = !behaviour.enabled; break; } } bool foldout = EditorGUI.BeginFoldoutHeaderGroup(foldoutRect, !typesHidden[index].Value, content, EditorStyles.foldoutHeader, rect => ClassUtilities.GetMenu(inspectedContext, inspectedECSContext).DropDown(rect)); Texture icon = SidekickEditorGUI.GetIcon(inspectedContexts[i], type); if (icon != null) { GUI.DrawTexture(iconRect, icon); } // Right click context menu if (SidekickEditorGUI.DetectClickInRect(foldoutRect, 1)) { ClassUtilities.GetMenu(inspectedContext, inspectedECSContext).DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } if (activeOrEnabled.HasValue) { EditorGUI.Toggle(toggleRect, activeOrEnabled.Value); } EditorGUILayout.EndFoldoutHeaderGroup(); typesHidden[index] = new KeyValuePair <Type, bool>(type, !foldout); if (!typesHidden[index].Value) { SidekickEditorGUI.DrawSplitter(0.5f); EditorGUI.indentLevel++; BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly; if (inspectedContext != null) // Is this an object instance? { bindingFlags |= BindingFlags.Instance; } var typeScope = type; while (typeScope != null) { if (InspectionExclusions.GetExcludedTypes().Contains(typeScope)) { break; } if (typeScope != type) { SidekickEditorGUI.DrawTypeChainHeader(new GUIContent(": " + typeScope.Name)); } FieldInfo[] fields = typeScope.GetFields(bindingFlags); PropertyInfo[] properties = typeScope.GetProperties(bindingFlags); MethodInfo[] methods = typeScope.GetMethods(bindingFlags); // Hide methods and backing fields that have been generated for properties if (SidekickSettings.HideAutoGenerated) { List <MethodInfo> methodList = new List <MethodInfo>(methods.Length); foreach (MethodInfo method in methods) { if (!TypeUtility.IsPropertyMethod(method, typeScope)) { methodList.Add(method); } } methods = methodList.ToArray(); List <FieldInfo> fieldList = new List <FieldInfo>(fields.Length); for (int j = 0; j < fields.Length; j++) { if (!TypeUtility.IsBackingField(fields[j], typeScope)) { fieldList.Add(fields[j]); } } fields = fieldList.ToArray(); } FieldInfo[] events = typeScope.GetFields(bindingFlags); if (mode == InspectorMode.Fields) { fieldPane.DrawFields(inspectedTypes[i], inspectedContexts[i], inspectedECSContext, searchTerm, fields); } else if (mode == InspectorMode.Properties) { propertyPane.DrawProperties(inspectedTypes[i], inspectedContexts[i], searchTerm, properties); } else if (mode == InspectorMode.Methods) { methodPane.DrawMethods(inspectedTypes[i], inspectedContexts[i], searchTerm, methods); } else if (mode == InspectorMode.Events) { eventPane.DrawEvents(inspectedTypes[i], inspectedContexts[i], searchTerm, events); } typeScope = typeScope.BaseType; } EditorGUI.indentLevel--; } SidekickEditorGUI.DrawSplitter(); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (inspectedTypes[0] == typeof(GameObject) #if ECS_EXISTS || inspectedTypes[0] == typeof(EntitySelectionProxy) #endif ) { bool pressed = GUILayout.Button("Add Component", GUILayout.Width(230), GUILayout.Height(24)); var popupRect2 = GUILayoutUtility.GetLastRect(); popupRect2.width = EditorGUIUtility.currentViewWidth; if (pressed) { if (inspectedTypes[0] == typeof(GameObject)) { TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type => { ((GameObject)inspectedContexts[0]).AddComponent(type); }, new[] { typeof(Component) }); dropdown.Show(popupRect2); } #if ECS_EXISTS else if (inspectedTypes[0] == typeof(EntitySelectionProxy)) { TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type => { inspectedECSContexts[0].EntityManager.AddComponent(inspectedECSContexts[0].Entity, ComponentType.ReadWrite(type)); }, null, new [] { typeof(IComponentData) }); dropdown.Show(popupRect2); } #endif } } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndScrollView(); if (mode == InspectorMode.Methods) { methodPane.PostDraw(); } //if(AnimationHelper.AnimationActive) { // Cause repaint on next frame Repaint(); if (Event.current.type == EventType.Repaint) { //AnimationHelper.ClearAnimationActive(); } } SidekickEditorGUI.EndLabelHighlight(); }