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(); }
public void DrawMethods(Type componentType, object component, MethodInfo[] methods) { OldSettings settings = OldInspectorSidekick.Current.Settings; // Grab the active window's settings 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; List <MethodSetup> expandedMethods = OldInspectorSidekick.Current.PersistentData.ExpandedMethods; GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; for (int j = 0; j < methods.Length; j++) { MethodInfo method = methods[j]; if (!string.IsNullOrEmpty(settings.SearchTerm) && !method.Name.Contains(settings.SearchTerm, StringComparison.InvariantCultureIgnoreCase)) { // Does not match search term, skip it continue; } // object[] customAttributes = method.GetCustomAttributes(false); EditorGUILayout.BeginHorizontal(); ParameterInfo[] parameters = method.GetParameters(); if (method.ReturnType == typeof(void)) { labelStyle.normal.textColor = Color.grey; } else if (method.ReturnType.IsValueType) { labelStyle.normal.textColor = new Color(0, 0, 1); } else { labelStyle.normal.textColor = new Color32(255, 130, 0, 255); } bool buttonClicked = GUILayout.Button(method.Name + " " + parameters.Length, normalButtonStyle); Rect lastRect = GUILayoutUtility.GetLastRect(); lastRect.xMax = normalButtonStyle.padding.left; GUI.Label(lastRect, TypeUtility.NameForType(method.ReturnType), labelStyle); if (buttonClicked) { object[] arguments = null; if (parameters.Length > 0) { arguments = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { arguments[i] = TypeUtility.GetDefaultValue(parameters[i].ParameterType); } } methodOutput = FireMethod(method, component, arguments); opacity = 1f; } if (parameters.Length > 0) { string methodIdentifier = componentType.FullName + "." + method.Name; bool wasExpanded = expandedMethods.Any(item => item.MethodName == methodIdentifier); bool expanded = GUILayout.Toggle(wasExpanded, "▼", expandButtonStyle, GUILayout.Width(20)); if (expanded != wasExpanded) { if (expanded) { MethodSetup methodSetup = new MethodSetup() { MethodName = methodIdentifier, Values = new object[parameters.Length], }; expandedMethods.Add(methodSetup); } else { expandedMethods.RemoveAll(item => item.MethodName == methodIdentifier); } } EditorGUILayout.EndHorizontal(); if (expanded) { MethodSetup methodSetup = expandedMethods.FirstOrDefault(item => item.MethodName == methodIdentifier); if (methodSetup.Values.Length != parameters.Length) { methodSetup.Values = new object[parameters.Length]; } EditorGUI.indentLevel++; for (int i = 0; i < parameters.Length; i++) { // VariablePane.DrawVariable(parameters[i].ParameterType, parameters[i].Name, GetDefaultValue(parameters[i].ParameterType), "", false); EditorGUI.BeginChangeCheck(); object newValue = VariablePane.DrawVariable(parameters[i].ParameterType, parameters[i].Name, methodSetup.Values[i], "", false, null); if (EditorGUI.EndChangeCheck()) { methodSetup.Values[i] = newValue; } } EditorGUI.indentLevel--; EditorGUILayout.BeginHorizontal(); GUILayout.Space(30); if (GUILayout.Button("Fire")) { methodOutput = FireMethod(method, component, methodSetup.Values); opacity = 1f; } EditorGUILayout.EndHorizontal(); GUILayout.Space(20); } } else { EditorGUILayout.EndHorizontal(); } } }
private static void DrawIndividualVariable(GUIContent label, Type fieldType, object fieldValue, IEnumerable <Attribute> customAttributes, out bool handled, Action <object> changeCallback) { EditorGUI.BeginChangeCheck(); handled = true; object newValue; RangeAttribute rangeAttribute = null; if (customAttributes != null) { foreach (var customAttribute in customAttributes) { if (customAttribute is RangeAttribute attribute) { rangeAttribute = attribute; } } } if (fieldType == typeof(int)) { if (SidekickSettings.PreferUnityAttributes && rangeAttribute != null) { newValue = EditorGUILayout.IntSlider(label, (int)fieldValue, (int)rangeAttribute.min, (int)rangeAttribute.max); } else { newValue = EditorGUILayout.IntField(label, (int)fieldValue); } } else if (fieldType == typeof(uint)) { long newLong = EditorGUILayout.LongField(label, (uint)fieldValue); // Replicate Unity's built in behaviour newValue = (uint)Mathf.Clamp(newLong, uint.MinValue, uint.MaxValue); } else if (fieldType == typeof(long)) { newValue = EditorGUILayout.LongField(label, (long)fieldValue); } else if (fieldType == typeof(ulong)) { // Note that Unity doesn't have a built in way to handle larger values than long.MaxValue (its inspector // doesn't work correctly with ulong in fact), so display it as a validated text field string newString = EditorGUILayout.TextField(label, ((ulong)fieldValue).ToString()); if (ulong.TryParse(newString, out ulong newULong)) { newValue = newULong; } else { newValue = fieldValue; } } else if (fieldType == typeof(byte)) { int newInt = EditorGUILayout.IntField(label, (byte)fieldValue); // Replicate Unity's built in behaviour newValue = (byte)Mathf.Clamp(newInt, byte.MinValue, byte.MaxValue); } else if (fieldType == typeof(sbyte)) { int newInt = EditorGUILayout.IntField(label, (sbyte)fieldValue); // Replicate Unity's built in behaviour newValue = (sbyte)Mathf.Clamp(newInt, sbyte.MinValue, sbyte.MaxValue); } else if (fieldType == typeof(ushort)) { int newInt = EditorGUILayout.IntField(label, (ushort)fieldValue); // Replicate Unity's built in behaviour newValue = (ushort)Mathf.Clamp(newInt, ushort.MinValue, ushort.MaxValue); } else if (fieldType == typeof(short)) { int newInt = EditorGUILayout.IntField(label, (short)fieldValue); // Replicate Unity's built in behaviour newValue = (short)Mathf.Clamp(newInt, short.MinValue, short.MaxValue); } else if (fieldType == typeof(string)) { newValue = EditorGUILayout.TextField(label, (string)fieldValue); } else if (fieldType == typeof(char)) { string newString = EditorGUILayout.TextField(label, new string((char)fieldValue, 1)); // Replicate Unity's built in behaviour if (newString.Length == 1) { newValue = newString[0]; } else { newValue = fieldValue; } } else if (fieldType == typeof(float)) { if (SidekickSettings.PreferUnityAttributes && rangeAttribute != null) { newValue = EditorGUILayout.Slider(label, (float)fieldValue, rangeAttribute.min, rangeAttribute.max); } else { newValue = EditorGUILayout.FloatField(label, (float)fieldValue); } } else if (fieldType == typeof(double)) { newValue = EditorGUILayout.DoubleField(label, (double)fieldValue); } else if (fieldType == typeof(bool)) { newValue = EditorGUILayout.Toggle(label, (bool)fieldValue); } else if (fieldType == typeof(Vector2)) { newValue = EditorGUILayout.Vector2Field(label, (Vector2)fieldValue); } else if (fieldType == typeof(Vector3)) { newValue = EditorGUILayout.Vector3Field(label, (Vector3)fieldValue); } else if (fieldType == typeof(Vector4)) { newValue = EditorGUILayout.Vector4Field(label, (Vector4)fieldValue); } else if (fieldType == typeof(Vector2Int)) { newValue = EditorGUILayout.Vector2IntField(label, (Vector2Int)fieldValue); } else if (fieldType == typeof(Vector3Int)) { newValue = EditorGUILayout.Vector3IntField(label, (Vector3Int)fieldValue); } else if (fieldType == typeof(Quaternion)) { Quaternion quaternion = (Quaternion)fieldValue; Vector4 vector = new Vector4(quaternion.x, quaternion.y, quaternion.z, quaternion.w); vector = EditorGUILayout.Vector4Field(label, vector); newValue = new Quaternion(vector.x, vector.y, vector.z, vector.z); } #if UNITY_MATH_EXISTS else if (fieldType == typeof(float2)) { newValue = (float2)EditorGUILayout.Vector2Field(label, (float2)fieldValue); } else if (fieldType == typeof(float3)) { newValue = (float3)EditorGUILayout.Vector3Field(label, (float3)fieldValue); } else if (fieldType == typeof(float4)) { newValue = (float4)EditorGUILayout.Vector4Field(label, (float4)fieldValue); } #endif else if (fieldType == typeof(Bounds)) { newValue = EditorGUILayout.BoundsField(label, (Bounds)fieldValue); } else if (fieldType == typeof(BoundsInt)) { newValue = EditorGUILayout.BoundsIntField(label, (BoundsInt)fieldValue); } else if (fieldType == typeof(Color)) { newValue = EditorGUILayout.ColorField(label, (Color)fieldValue); } else if (fieldType == typeof(Color32)) { newValue = (Color32)EditorGUILayout.ColorField(label, (Color32)fieldValue); } else if (fieldType == typeof(Gradient)) { newValue = EditorGUILayout.GradientField(new GUIContent(label), (Gradient)fieldValue); } else if (fieldType == typeof(AnimationCurve)) { newValue = EditorGUILayout.CurveField(label, (AnimationCurve)fieldValue); } else if (fieldType.IsSubclassOf(typeof(Enum))) { newValue = EditorGUILayout.EnumPopup(label, (Enum)fieldValue); Type underlyingType = Enum.GetUnderlyingType(fieldValue.GetType()); // Cast from the enum to the underlying type (e.g. byte) then to int object cast = Convert.ChangeType(newValue, underlyingType); cast = Convert.ChangeType(cast, typeof(int)); // Allow them to edit as an int then cast back newValue = Convert.ChangeType(EditorGUILayout.IntField((int)cast), underlyingType); } else if (fieldType == typeof(Rect)) { newValue = EditorGUILayout.RectField(label, (Rect)fieldValue); } else if (fieldType == typeof(RectInt)) { newValue = EditorGUILayout.RectIntField(label, (RectInt)fieldValue); } else if (fieldType.IsSubclassOf(typeof(UnityEngine.Object))) { newValue = EditorGUILayout.ObjectField(label, (UnityEngine.Object)fieldValue, fieldType, true); } else if (fieldType == typeof(Type)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(label, new GUIContent(TypeUtility.NameForType((Type)fieldValue))); var popupRect = GUILayoutUtility.GetLastRect(); popupRect.width = EditorGUIUtility.currentViewWidth; var selectTypeButtonLabel = new GUIContent("Select"); if (GUILayout.Button(selectTypeButtonLabel, EditorStyles.miniButton)) { TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type => { // Async apply changeCallback?.Invoke(type); }); dropdown.Show(popupRect); } EditorGUILayout.EndHorizontal(); newValue = fieldValue; } else { handled = false; newValue = fieldValue; } if (EditorGUI.EndChangeCheck()) { changeCallback?.Invoke(newValue); } }
public static object DrawVariable(Type fieldType, string fieldName, object fieldValue, string metaSuffix, bool allowExtensions, Type contextType) { GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; if (fieldValue == null) { fieldValue = TypeUtility.GetDefaultValue(fieldType); } fieldName = SidekickUtility.ParseDisplayString(fieldName); if (!string.IsNullOrEmpty(metaSuffix)) { fieldName += " " + metaSuffix; } object newValue = fieldValue; bool isArray = fieldType.IsArray; bool isGenericList = TypeUtility.IsGenericList(fieldType); if (isArray || isGenericList) { Type elementType = TypeUtility.GetElementType(fieldType); string elementTypeName = TypeUtility.NameForType(elementType); if (isGenericList) { GUILayout.Label("List<" + elementTypeName + "> " + fieldName); } else { GUILayout.Label(elementTypeName + "[] " + fieldName); } IList list = null; int previousSize = 0; if (fieldValue != null) { list = (IList)fieldValue; previousSize = list.Count; } int newSize = Mathf.Max(0, EditorGUILayout.IntField("Size", previousSize)); if (newSize != previousSize) { if (list == null) { list = (IList)Activator.CreateInstance(fieldType); } CollectionUtility.Resize(ref list, elementType, newSize); } if (list != null) { for (int i = 0; i < list.Count; i++) { list[i] = DrawIndividualVariable("Element " + i, elementType, list[i]); } } } else { // Not a collection EditorGUILayout.BeginHorizontal(); newValue = DrawIndividualVariable(fieldName, fieldType, fieldValue); if (allowExtensions) { GUI.enabled = true; // GUI.SetNextControlName( if (GUILayout.Button("->", expandButtonStyle, GUILayout.Width(20))) { OldInspectorSidekick.Current.SetSelection(fieldValue, true); } bool expanded = GUILayout.Button("...", expandButtonStyle, GUILayout.Width(20)); if (Event.current.type == EventType.Repaint) { string methodIdentifier = contextType.FullName + "." + fieldType.FullName; guiRects[methodIdentifier] = GUILayoutUtility.GetLastRect(); } // if (GUIUtility.hot { // GUILayoutUtility // gridRect = GUILayoutUtility.GetLastRect(); // gridRect.width = 100; } if (expanded) { string methodIdentifier = contextType.FullName + "." + fieldType.FullName; Rect gridRect = guiRects[methodIdentifier]; GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Placeholder"), false, null); // if(fieldType == typeof(Texture)) { menu.AddItem(new GUIContent("Export PNG"), false, ExportTexture, fieldValue); } menu.DropDown(gridRect); } } EditorGUILayout.EndHorizontal(); } return(newValue); }
public void DrawMethods(Type componentType, object component, string searchTerm, MethodInfo[] methods) { GUIStyle labelStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleRight }; GUIStyle normalButtonStyle = new GUIStyle(GUI.skin.button) { alignment = TextAnchor.MiddleLeft }; normalButtonStyle.padding = normalButtonStyle.padding.SetLeft(100); List <MethodSetup> expandedMethods = SidekickWindow.Current.PersistentData.ExpandedMethods; GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; foreach (MethodInfo method in methods) { if (!SearchMatches(searchTerm, method.Name)) { // Does not match search term, skip it continue; } // object[] customAttributes = method.GetCustomAttributes(false); EditorGUILayout.BeginHorizontal(); ParameterInfo[] parameters = method.GetParameters(); if (method.ReturnType == typeof(void)) { labelStyle.normal.textColor = Color.grey; } else if (method.ReturnType.IsValueType) { labelStyle.normal.textColor = new Color(0, 0, 1); } else { labelStyle.normal.textColor = new Color32(255, 130, 0, 255); } labelStyle.fontSize = 10; var genericArguments = method.GetGenericArguments(); GUIContent buttonLabel = new GUIContent("", "Click to fire with defaults"); if (genericArguments.Length != 0) { string genericArgumentsDisplay = string.Join(", ", genericArguments.Select(item => item.Name)); buttonLabel.text = $"{method.Name} <{genericArgumentsDisplay}> {parameters.Length}"; } else { buttonLabel.text = $"{method.Name} {parameters.Length}"; } using (new EditorGUI.DisabledScope(method.IsGenericMethod)) { bool buttonClicked = GUILayout.Button(buttonLabel, normalButtonStyle); Rect lastRect = GUILayoutUtility.GetLastRect(); lastRect.xMax = normalButtonStyle.padding.left; GUI.Label(lastRect, TypeUtility.NameForType(method.ReturnType), labelStyle); if (buttonClicked) { object[] arguments = null; if (parameters.Length > 0) { arguments = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { arguments[i] = TypeUtility.GetDefaultValue(parameters[i].ParameterType); } } var output = FireMethod(method, component, arguments, null); outputObjects.AddRange(output); opacity = 1f; } } if (parameters.Length > 0 || genericArguments.Length > 0) { string methodIdentifier = TypeUtility.GetMethodIdentifier(method); bool wasExpanded = expandedMethods.Any(item => item.MethodIdentifier == methodIdentifier); string label = wasExpanded ? "▲" : "▼"; bool expanded = GUILayout.Toggle(wasExpanded, label, expandButtonStyle, GUILayout.Width(20)); if (expanded != wasExpanded) { if (expanded) { MethodSetup methodSetup = new MethodSetup() { MethodIdentifier = methodIdentifier, Values = new object[parameters.Length], GenericArguments = new Type[genericArguments.Length], }; expandedMethods.Add(methodSetup); } else { expandedMethods.RemoveAll(item => item.MethodIdentifier == methodIdentifier); } } EditorGUILayout.EndHorizontal(); if (expanded) { MethodSetup methodSetup = expandedMethods.FirstOrDefault(item => item.MethodIdentifier == methodIdentifier); if (methodSetup.Values.Length != parameters.Length) { methodSetup.Values = new object[parameters.Length]; } EditorGUI.indentLevel++; for (var i = 0; i < genericArguments.Length; i++) { Type genericArgument = genericArguments[i]; string displayLabel = genericArgument.Name; Type[] constraints = genericArgument.GetGenericParameterConstraints(); if (constraints.Length != 0) { displayLabel += $" ({string.Join(", ", constraints.Select(item => item.Name))})"; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(displayLabel, TypeUtility.NameForType(methodSetup.GenericArguments[i])); var popupRect = GUILayoutUtility.GetLastRect(); popupRect.width = EditorGUIUtility.currentViewWidth; var selectTypeButtonLabel = new GUIContent("Select"); if (GUILayout.Button(selectTypeButtonLabel, EditorStyles.miniButton)) { int index = i; TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type => methodSetup.GenericArguments[index] = type, constraints); dropdown.Show(popupRect); } EditorGUILayout.EndHorizontal(); } for (int i = 0; i < parameters.Length; i++) { int index = i; VariablePane.DrawVariable(parameters[i].ParameterType, parameters[i].Name, methodSetup.Values[i], "", VariablePane.VariableAttributes.None, null, false, null, newValue => { methodSetup.Values[index] = newValue; }); } EditorGUI.indentLevel--; EditorGUILayout.BeginHorizontal(); GUILayout.Space(30); bool anyGenericArgumentsMissing = methodSetup.GenericArguments.Any(item => item == null); using (new EditorGUI.DisabledScope(anyGenericArgumentsMissing)) { if (GUILayout.Button("Fire")) { var output = FireMethod(method, component, methodSetup.Values, methodSetup.GenericArguments); outputObjects.AddRange(output); opacity = 1f; } } EditorGUILayout.EndHorizontal(); GUILayout.Space(20); } } else { EditorGUILayout.EndHorizontal(); } } }