using System; using System.Collections.Generic; using UnityEngine; using DynamicExpresso; using System.Text.RegularExpressions; using System.Linq; using UnityEngine.InputSystem; using TMPro; using System.Reflection; using System.Linq.Expressions; using Sirenix.Utilities; using System.Collections; using DG.Tweening; //又在写大粪 ——神币 namespace Ichni.Editor { public partial class EditorConsole : MonoBehaviour { public Interpreter functionInterpreter; public TMP_InputField InputCommand; private Dictionary historyCommand = new Dictionary(); private int historycount = 0; public GameObject ConsoleUI; public TMP_Text cueText; bool isHide = true; private string FillCueCommand(MethodInfo method) { if (method == null) { return ""; } string methodName = method.Name; // 3. 获取参数信息 var parameters = method.GetParameters(); if (parameters.Length == 0) { return $"{methodName} " + "\n"; } // 4. 生成参数提示 string paramHint = string.Join(" ", parameters.Select(p => p.IsOptional ? $"[{p.ParameterType.Name}:{p.Name}]" : $"{p.ParameterType.Name}:{p.Name}" )); return $"{methodName} {paramHint}".Trim() + "\n"; } public void GetChange(string change) { if (change == "help") { List Allmethods = typeof(EditorConsoleMethods).GetMethods(). Where(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void)). ToList(); cueText.text = ""; foreach (MethodInfo method in Allmethods) { cueText.text += FillCueCommand(method); } return; } // Task t = new Task(() => // { // 1. 提取命令名 string trimmed = change.Trim(); if (string.IsNullOrEmpty(trimmed)) { cueText.text = ""; return; } // 支持 func(...) 或 func abc 123 var match = Regex.Match(trimmed, @"^(\w+)"); if (!match.Success) { cueText.text = ""; return; } string funcName = match.Groups[1].Value; // 2. 查找方法 List methods = typeof(EditorConsoleMethods).GetMethods() .Where(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void) && m.Name.Contains(funcName)).ToList(); cueText.text = ""; foreach (MethodInfo method in methods) { cueText.text += FillCueCommand(method); } if (cueText.text.IsNullOrWhitespace()) { cueText.text = "No matching commands found."; } // }); // t.RunSynchronously(); } public void GetCommand(string Command)//当提交命令时 { try { functionInterpreter.Eval(Command); } catch (Exception e) { Debug.LogWarning("WTF Command! " + e); LogWindow.Log("Unknow Command!", Color.red); } } private void Update() { UIscale(); if (InputCommand.isFocused) InputDect(); } private void UIscale() { if (Keyboard.current.backquoteKey.wasPressedThisFrame) { isHide = !isHide; if (!isHide) { ConsoleUI.SetActive(true); } else ConsoleUI.SetActive(false); } } //这是史,不要看 private void InputDect() { // 向下翻历史命令 if (Keyboard.current.downArrowKey.wasPressedThisFrame) { if (historyCommand.Count - 1 > historycount) { historycount++; InputCommand.text = historyCommand[historycount]; } else { InputCommand.text = ""; historycount = historyCommand.Count; } return; } // 向上翻历史命令 if (Keyboard.current.upArrowKey.wasPressedThisFrame && historycount != 0) { historycount--; InputCommand.text = historyCommand[historycount]; return; } // 提交命令 if (Keyboard.current.enterKey.wasPressedThisFrame) { string input = InputCommand.text; if (string.IsNullOrWhiteSpace(input)) { InputCommand.text = ""; return; } string ExpoCommand = TransformCommand(input); print(ExpoCommand); GetCommand(ExpoCommand); // 记录历史命令 if (historyCommand.ContainsKey(historycount)) historyCommand[historycount] = input; else historyCommand.Add(historycount, input); historycount++; InputCommand.text = ""; } } private string TransformCommand(string input) { string getFloatorInt(string a) { return a.Contains(".") ? $"{a}f" : a; } // 处理命令格式,适配 DynamicExpresso string trimmed = input.Trim(); // 1. 直接支持 func(...) 形式 if (Regex.IsMatch(trimmed, @"^\w+\s*\(.*\)$")) return trimmed; // 2. 直接支持赋值表达式 if (trimmed.Contains("=")) return trimmed; // 3. 支持 func abc 123 [1,2,3] 形式 var match = Regex.Match(trimmed, @"^(\w+)\s*(.*)$"); if (match.Success) { string func = match.Groups[1].Value; string args = match.Groups[2].Value.Trim(); // 匹配参数:中括号、引号、或连续非空白 var argMatches = Regex.Matches(args, @"(\[[^\]]+\]|""(?:[^""\\]|\\.)*""|\S+)"); var argList = argMatches.Cast().Select(m => m.Value).ToList(); List processedArgs = new List(); foreach (var arg in argList) { string a = arg.Trim(); // Vector2/3: [1,2] 或 [1,2,3],支持小数 if (Regex.IsMatch(a, @"^\[\s*-?\d*\.?\d+\s*,\s*-?\d*\.?\d+(\s*,\s*-?\d*\.?\d+)*\s*\]$")) { // 去除中括号和空格 string content = a.Substring(1, a.Length - 2).Trim(); var nums = content.Split(',').Select(s => s.Trim()).ToArray(); if (nums.Length == 2) processedArgs.Add($"new Vector2({getFloatorInt(nums[0])},{getFloatorInt(nums[1])})"); else if (nums.Length == 3) processedArgs.Add($"new Vector3({getFloatorInt(nums[0])},{getFloatorInt(nums[1])},{getFloatorInt(nums[2])})"); else processedArgs.Add(a); // 不是2或3维,原样返回 } // 已有引号的字符串 else if (a.StartsWith("\"") && a.EndsWith("\"")) { processedArgs.Add(a); } // 数字 else if (Regex.IsMatch(a, @"^-?\d+(\.\d+)?([eE][+-]?\d+)?$")) { processedArgs.Add(getFloatorInt(a)); } // 变量名(字母开头,允许字母数字下划线) else if (Regex.IsMatch(a, @"^[a-zA-Z_]\w*$")) { processedArgs.Add(a); } // 其它未加引号的参数,自动加引号 else { processedArgs.Add($"\"{a}\""); } } string joinedArgs = string.Join(",", processedArgs); return string.IsNullOrEmpty(joinedArgs) ? $"{func}()" : $"{func}({joinedArgs})"; } return trimmed; } private void Start() { SetUpFunctions(); //Test // functionInterpreter.Eval("print(\"Hello World!\")"); // functionInterpreter.Eval("log(\"Hello World but debug!\")"); } } public partial class EditorConsole { public Inspector inspector => EditorManager.instance.uiManager.inspector; public Hierarchy hierarchy => EditorManager.instance.uiManager.hierarchy; public LogWindow logWindow => EditorManager.instance.uiManager.mainPage.logWindow; public List commandList = new List(); public void SetUpFunctions() { functionInterpreter = new Interpreter() .Reference(typeof(Vector3)) .Reference(typeof(Vector2));//这是AI给的东西? foreach (MethodInfo i in typeof(EditorConsoleMethods).GetMethods(). ToList().Where(i => i.IsStatic && i.IsPublic && (i.ReturnType == typeof(void)))) { var parameters = i.GetParameters().Select(p => p.ParameterType).ToArray(); var delegateType = Expression.GetDelegateType(parameters.Concat(new[] { i.ReturnType }).ToArray()); functionInterpreter.SetFunction(i.Name, i.CreateDelegate(delegateType)); commandList.Add(i.Name); } } } }