public static void Resize(ref IList list, Type elementType, int newSize) { int oldSize = list.Count; // Unity's default behaviour when expanding a collection is to use the last element as the new element value object objectToAdd = null; if (newSize > oldSize) { if (oldSize >= 1) { objectToAdd = list[oldSize - 1]; } else { objectToAdd = TypeUtility.GetDefaultValue(elementType); } } if (list.IsFixedSize) { Array newArray = Array.CreateInstance(elementType, newSize); Array.Copy((Array)list, newArray, Math.Min(oldSize, newArray.Length)); if (newSize > oldSize) { int toAdd = newSize - oldSize; for (int i = 0; i < toAdd; i++) { newArray.SetValue(objectToAdd, oldSize + i); } } list = newArray; } else { if (newSize > oldSize) { int toAdd = newSize - oldSize; for (int i = 0; i < toAdd; i++) { list.Add(objectToAdd); } } else if (newSize < oldSize) { int toRemove = oldSize - newSize; for (int i = 0; i < toRemove; i++) { list.RemoveAt(oldSize - i - 1); } } } }
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(); } } }
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 static void DrawVariable(Type fieldType, string fieldName, object fieldValue, string tooltip, VariableAttributes variableAttributes, IEnumerable <Attribute> customAttributes, bool allowExtensions, Type contextType, Action <object> changeCallback) { if ((variableAttributes & VariableAttributes.Static) != 0) { var style = new GUIStyle { normal = { background = SidekickEditorGUI.StaticBackground } }; EditorGUILayout.BeginVertical(style); } GUIStyle expandButtonStyle = new GUIStyle(GUI.skin.button); RectOffset padding = expandButtonStyle.padding; padding.left = 0; padding.right = 1; expandButtonStyle.padding = padding; fieldValue ??= TypeUtility.GetDefaultValue(fieldType); string displayName = SidekickUtility.NicifyIdentifier(fieldName); GUIContent label = new GUIContent(displayName, tooltip); bool isArray = fieldType.IsArray; bool isGenericList = TypeUtility.IsGenericList(fieldType); bool isGenericDictionary = TypeUtility.IsGenericDictionary(fieldType); if (isGenericDictionary) { EditorGUILayout.BeginHorizontal(); string expandedID = fieldType.FullName + fieldName; bool expanded = DrawHeader(expandedID, label, (variableAttributes & VariableAttributes.Static) != 0); int count = 0; if (fieldValue != null) { EditorGUI.BeginDisabledGroup(true); count = (int)fieldType.GetProperty("Count").GetValue(fieldValue); EditorGUILayout.IntField(count, GUILayout.Width(80)); EditorGUI.EndDisabledGroup(); } if (allowExtensions) { DrawExtensions(fieldValue, expandButtonStyle); } EditorGUILayout.EndHorizontal(); if (expanded) { EditorGUI.indentLevel++; if (fieldValue != null) { FieldInfo entriesArrayField = fieldType.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance); IList entriesArray = (IList)entriesArrayField.GetValue(fieldValue); Type elementType = TypeUtility.GetFirstElementType(entriesArrayField.FieldType); FieldInfo elementKeyFieldInfo = elementType.GetField("key", BindingFlags.Public | BindingFlags.Instance); FieldInfo elementValueFieldInfo = elementType.GetField("value", BindingFlags.Public | BindingFlags.Instance); int oldIndent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; for (int i = 0; i < count; i++) { object entry = entriesArray[i]; EditorGUILayout.BeginHorizontal(); object key = elementKeyFieldInfo.GetValue(entry); object value = elementValueFieldInfo.GetValue(entry); using (new EditorGUI.DisabledScope(true)) { DrawIndividualVariable(GUIContent.none, key.GetType(), key, null, out _, newValue => { /*list[index] = newValue;*/ }); } DrawIndividualVariable(GUIContent.none, value.GetType(), value, null, out var handled, newValue => { PropertyInfo indexer = fieldType.GetProperties().First(x => x.GetIndexParameters().Length > 0); indexer.SetValue(fieldValue, newValue, new[] { key }); }); EditorGUILayout.EndHorizontal(); } EditorGUI.indentLevel = oldIndent; } EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); } else if (isArray || isGenericList) { Type elementType = TypeUtility.GetFirstElementType(fieldType); EditorGUILayout.BeginHorizontal(); string expandedID = fieldType.FullName + fieldName; bool expanded = DrawHeader(expandedID, label, (variableAttributes & VariableAttributes.Static) != 0); EditorGUI.BeginDisabledGroup((variableAttributes & VariableAttributes.ReadOnly) != 0); IList list = null; int previousSize = 0; if (fieldValue != null) { list = (IList)fieldValue; previousSize = list.Count; } int newSize = Mathf.Max(0, EditorGUILayout.IntField(previousSize, GUILayout.Width(80))); if (newSize != previousSize) { var newValue = CollectionUtility.Resize(list, isArray, fieldType, elementType, newSize); changeCallback(newValue); } if (allowExtensions) { DrawExtensions(fieldValue, expandButtonStyle); } EditorGUILayout.EndHorizontal(); if (expanded) { EditorGUI.indentLevel++; if (list != null) { for (int i = 0; i < list.Count; i++) { EditorGUILayout.BeginHorizontal(); int index = i; DrawIndividualVariable(new GUIContent("Element " + i), elementType, list[i], null, out var handled, newValue => { list[index] = newValue; }); if (allowExtensions) { DrawExtensions(list[i], expandButtonStyle); } EditorGUILayout.EndHorizontal(); } } EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); } else { EditorGUI.BeginDisabledGroup((variableAttributes & VariableAttributes.ReadOnly) != 0); // Not a collection EditorGUILayout.BeginHorizontal(); DrawIndividualVariable(label, fieldType, fieldValue, customAttributes, out var handled, changeCallback); if (handled && allowExtensions) { DrawExtensions(fieldValue, expandButtonStyle); } EditorGUILayout.EndHorizontal(); if (!handled) { EditorGUI.EndDisabledGroup(); string expandedID = fieldType.FullName + fieldName; EditorGUILayout.BeginHorizontal(); bool expanded = DrawHeader(expandedID, label, (variableAttributes & VariableAttributes.Static) != 0); if (allowExtensions) { DrawExtensions(fieldValue, expandButtonStyle); } EditorGUILayout.EndHorizontal(); EditorGUI.BeginDisabledGroup((variableAttributes & VariableAttributes.ReadOnly) != 0); if (expanded) { EditorGUI.indentLevel++; if (fieldValue != null) { var fields = fieldType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var fieldInfo in fields) { GUIContent subLabel = new GUIContent(fieldInfo.Name); DrawIndividualVariable(subLabel, fieldInfo.FieldType, fieldInfo.GetValue(fieldValue), null, out _, newValue => { fieldInfo.SetValue(fieldValue, newValue); }); } } else { GUILayout.Label("Null"); } EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); } } EditorGUI.EndDisabledGroup(); if ((variableAttributes & VariableAttributes.Static) != 0) { EditorGUILayout.EndVertical(); } }
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(); } } }