#if UNITY_EDITOR using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; namespace Mountools.Tools { public class ToolObjectMethodInvoker : EditorWindow { private string _search = ""; private Vector2 _scrollPositionRight = Vector2.zero; private Dictionary _parameterCache; private Dictionary _foldoutEnableMethod; private bool _showGetter; private bool _showSetter; private bool _showPrivate; private bool _showInherit; private Component _debugComponent; private void OnGUI() { EditorGUILayout.BeginVertical(); Draw(); EditorGUILayout.EndVertical(); } private void Draw() { if (_parameterCache == null) _parameterCache = new(); if (_foldoutEnableMethod == null) _foldoutEnableMethod = new(); if (Selection.gameObjects == null || Selection.gameObjects.Length < 1) { return; } GameObject debugObject = Selection.gameObjects[0]; var components = debugObject.GetComponents(); EditorGUILayout.BeginVertical(); { EditorGUILayout.BeginVertical(GUILayout.Height(20)); { int select = 0; var i = 0; Component[] selections = components; List names = new List(); foreach (var component in components) { names.Add(component.GetType().Name); if (component == _debugComponent) select = i; i++; } _debugComponent = selections[GUILayout.Toolbar(select, names.ToArray(), "toolbarbuttonRight")]; } EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal(); { _showSetter = GUILayout.Toggle(_showSetter, "Setter", "TE toolbarbutton", GUILayout.Width(45)); _showGetter = GUILayout.Toggle(_showGetter, "Getter", "TE toolbarbutton", GUILayout.Width(45)); _showInherit = GUILayout.Toggle(_showInherit, "Inherit", "TE toolbarbutton", GUILayout.Width(60)); _showPrivate = GUILayout.Toggle(_showPrivate, "Private", "TE toolbarbutton", GUILayout.Width(60)); _search = EditorGUILayout.TextField("", _search, "SearchTextField"); } EditorGUILayout.EndHorizontal(); _scrollPositionRight = EditorGUILayout.BeginScrollView(_scrollPositionRight, "OL box NoExpand"); { DrawComponentMethodInvokerView(_debugComponent); } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); } private void DrawComponentMethodInvokerView(Component component) { if (component == null) { return; } var style = new GUIStyle { fontSize = 12, fontStyle = FontStyle.Bold, normal = { textColor = GUI.contentColor } }; #if MT_L_CHINESE var strMethod = "有参数方法列表"; #endif #if MT_L_ENGLISH var strMethod = "Method"; #endif EditorGUILayout.LabelField(" " + strMethod, style); EditorGUILayout.BeginVertical(); { List noParameterMethodInfos = new List(); var methods = component.GetType().GetMethods(); var drawCount = 0; foreach (var method in methods) { if (method.Name.Contains("get_") && !_showGetter) continue; if (method.Name.Contains("set_") && !_showSetter) continue; if (method.IsPrivate && !_showPrivate) continue; if (method.DeclaringType != method.ReflectedType && !_showInherit) continue; if (_search.Trim() != "" && !method.Name.ToLower().Contains(_search.Trim().ToLower())) continue; if (!method.ContainsGenericParameters && !method.IsGenericMethod && !method.IsAbstract && !method.IsConstructor && !method.IsAssembly) { ParameterInfo[] paremeters = method.GetParameters(); if (paremeters.Length > 0) { DrawMethodInvoker(component, method, paremeters); drawCount ++; } else { noParameterMethodInfos.Add(method); } } } #if MT_L_CHINESE var strNone = "无"; var strNoParameter = "无参数方法列表"; #endif #if MT_L_ENGLISH var strNone = "None"; var strNoParameter = "No Parameter"; #endif if (drawCount == 0) { EditorGUILayout.LabelField(strNone); } EditorGUILayout.Space(); EditorGUILayout.LabelField(" " + strNoParameter, style); if (noParameterMethodInfos.Count < 1) { EditorGUILayout.LabelField(strNone); } else { foreach (var method in noParameterMethodInfos) { if (EditorGUILayout.LinkButton(method.Name + "();")) { PrintReturnValue(method, method.Invoke(component, null)); } } } } EditorGUILayout.EndVertical(); } private void DrawMethodInvoker(Component obj, MethodInfo methodInfo, ParameterInfo[] parameters) { string parameterNames = ""; foreach (var parameter in parameters) { parameterNames += parameter.ParameterType.Name + " " + parameter.Name + ", "; } string n = (methodInfo.Name + " (" + parameterNames + ");") .Replace("Single", "float") .Replace("Int32", "int") .Replace(", );", ");"); SetFoldoutMethod(methodInfo, EditorGUILayout.BeginFoldoutHeaderGroup(GetFoldoutMethod(methodInfo), n, "FoldoutHeader")); EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUILayout.BeginHorizontal(); { if (GetFoldoutMethod(methodInfo)) { EditorGUILayout.BeginVertical("OL box NoExpand"); { bool canInvoke = true; foreach (var parameter in parameters) { if (!DrawParameterInputField(parameter)) canInvoke = false; } #if MT_L_CHINESE var strInvoke = "调用方法"; var strInvokeUnsafe = "调用方法 (非安全)"; #endif #if MT_L_ENGLISH var strInvoke = "Invoke"; var strInvokeUnsafe = "Invoke (Unsafe)"; #endif bool click = canInvoke ? GUILayout.Button(strInvoke) : GUILayout.Button(strInvokeUnsafe); if (click) { List param = new List(); foreach (var parameter in parameters) { param.Add(GetParameter(parameter)); } PrintReturnValue(methodInfo, methodInfo.Invoke(obj, param.ToArray())); } } EditorGUILayout.EndVertical(); } } EditorGUILayout.EndHorizontal(); } private bool DrawParameterInputField(ParameterInfo parameterInfo) { var type = parameterInfo.ParameterType; var parameterNameRaw = parameterInfo.Name; var parameterName = ""; // Name Formatter var i = 0; foreach (var nameChar in parameterNameRaw.Trim()) { if (Char.IsUpper(nameChar)) { parameterName += " " + nameChar; continue; } parameterName += nameChar; } if (parameterName.Length > 1) parameterName = parameterName.Substring(0, 1).ToUpper() + parameterName.Substring(1); else parameterName = parameterName.ToUpper(); if (type == typeof(int)) { string t = parameterInfo.Name.ToLower(); if (t.Contains("mask") || t.Contains("layer")) { SetParameter(parameterInfo, EditorGUILayout.LayerField(parameterName, (int) GetParameter(parameterInfo, 0))); return true; } SetParameter(parameterInfo, EditorGUILayout.IntField(parameterName, (int) GetParameter(parameterInfo, 0))); return true; } if (type == typeof(float)) { SetParameter(parameterInfo, EditorGUILayout.FloatField(parameterName, (float) GetParameter(parameterInfo, 0f))); return true; } if (type == typeof(string)) { string t = parameterName.ToLower(); if (t.Contains("password") || t.Contains("pswd") || t.Contains("passwd")) { SetParameter(parameterInfo, EditorGUILayout.PasswordField(parameterName, (string) GetParameter(parameterInfo, 0))); return true; } SetParameter(parameterInfo, EditorGUILayout.TextField(parameterName, (string) GetParameter(parameterInfo, ""))); return true; } if (type == typeof(bool)) { SetParameter(parameterInfo, EditorGUILayout.Toggle(parameterName, (bool) GetParameter(parameterInfo, false))); return true; } if (type == typeof(Quaternion)) { Quaternion q = (Quaternion) GetParameter(parameterInfo, Quaternion.Euler(0, 0, 0)); Vector4 qv4 = new Vector4(q.x, q.y, q.z, q.w); Vector4 v = EditorGUILayout.Vector4Field(parameterName, qv4); SetParameter(parameterInfo, new Quaternion(v.x, v.y, v.z, v.w)); return true; } if (type == typeof(Vector4)) { SetParameter(parameterInfo, EditorGUILayout.Vector4Field(parameterName, (Vector4) GetParameter(parameterInfo, Vector4.zero))); return true; } if (type == typeof(Vector3)) { SetParameter(parameterInfo, EditorGUILayout.Vector3Field(parameterName, (Vector3) GetParameter(parameterInfo, Vector3.zero))); return true; } if (type == typeof(Vector2)) { SetParameter(parameterInfo, EditorGUILayout.Vector2Field(parameterName, (Vector2) GetParameter(parameterInfo, Vector2.zero))); return true; } if (type == typeof(Color)) { SetParameter(parameterInfo, EditorGUILayout.ColorField(parameterName, (Color) GetParameter(parameterInfo, Color.black))); return true; } if (type == typeof(Gradient)) { SetParameter(parameterInfo, EditorGUILayout.GradientField(parameterName, (Gradient) GetParameter(parameterInfo))); return true; } if (type == typeof(Bounds)) { SetParameter(parameterInfo, EditorGUILayout.BoundsField(parameterName, (Bounds) GetParameter(parameterInfo))); return true; } if (type == typeof(AnimationCurve)) { SetParameter(parameterInfo, EditorGUILayout.CurveField(parameterName, (AnimationCurve) GetParameter(parameterInfo))); return true; } if (type == typeof(double)) { SetParameter(parameterInfo, EditorGUILayout.DoubleField(parameterName, (double) GetParameter(parameterInfo))); return true; } if (type == typeof(long)) { SetParameter(parameterInfo, EditorGUILayout.LongField(parameterName, (long) GetParameter(parameterInfo))); return true; } if (type == typeof(Rect)) { SetParameter(parameterInfo, EditorGUILayout.RectField(parameterName, (Rect) GetParameter(parameterInfo))); return true; } if (type == typeof(Transform)) { SetParameter(parameterInfo, EditorGUILayout.ObjectField(parameterName, (Transform) GetParameter(parameterInfo), typeof(Transform), true)); return true; } GUILayout.Label(parameterName); return false; } private void PrintReturnValue(MethodInfo methodInfo, object obj) { if (obj == null) return; Type type = obj.GetType(); if (type == typeof(int) || type == typeof(float) || type == typeof(double) || type == typeof(string) || type == typeof(char) || type == typeof(long)) { PrintReturnValueFormat(methodInfo, obj.ToString()); return; } if (type == typeof(Color)) { Color v = (Color)obj; PrintReturnValueFormat(methodInfo, $"argb:{v.a},{v.r},{v.g},{v.b}"); return; } if (type == typeof(Vector2)) { Vector2 v = (Vector2)obj; PrintReturnValueFormat(methodInfo, $"xy:{v.x},{v.y}"); return; } if (type == typeof(Vector3)) { Vector3 v = (Vector3)obj; PrintReturnValueFormat(methodInfo, $"xyz:{v.x},{v.y},{v.z}"); return; } if (type == typeof(Vector4)) { Vector4 v = (Vector4)obj; PrintReturnValueFormat(methodInfo, $"xyzw:{v.x},{v.y},{v.z},{v.w}"); return; } if (type == typeof(Quaternion)) { Quaternion v = (Quaternion)obj; Vector3 e = v.eulerAngles; PrintReturnValueFormat(methodInfo, $"xyzw:{v.x},{v.y},{v.z},{v.w} euler:{e.x},{e.y},{e.z}"); return; } } private void PrintReturnValueFormat(MethodInfo methodInfo, string value) { Debug.Log(methodInfo.Name + " Returned : ( " + methodInfo.ReturnType.Name + " ) " + value, _debugComponent); } private object GetParameter(ParameterInfo parameterInfo, object defaultValue = null) { if (_parameterCache.ContainsKey(parameterInfo)) { if (_parameterCache[parameterInfo] == null && defaultValue != null) { SetParameter(parameterInfo, defaultValue); } return _parameterCache[parameterInfo]; } _parameterCache.Add(parameterInfo, defaultValue); return defaultValue; } private void SetParameter(ParameterInfo parameterInfo, object value) { if (_parameterCache.ContainsKey(parameterInfo)) { _parameterCache[parameterInfo] = value; return; } _parameterCache.Add(parameterInfo, value); } private bool GetFoldoutMethod(MethodInfo method) { if (_foldoutEnableMethod.ContainsKey(method)) { return _foldoutEnableMethod[method]; } _foldoutEnableMethod.Add(method, false); return false; } private void SetFoldoutMethod(MethodInfo method, bool enable) { if (_foldoutEnableMethod.ContainsKey(method)) { _foldoutEnableMethod[method] = enable; return; } _foldoutEnableMethod.Add(method, enable); } } } #endif