2025-01-29 23:49:18 -05:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using DynamicExpresso;
|
2025-02-04 15:05:05 +08:00
|
|
|
|
using System.Text.RegularExpressions;
|
2025-02-08 01:21:40 +08:00
|
|
|
|
using System.Linq;
|
2025-02-10 15:56:10 +08:00
|
|
|
|
using Ichni.RhythmGame;
|
2025-02-14 22:04:21 -05:00
|
|
|
|
using UnityEngine.InputSystem;
|
2025-02-20 03:15:42 +08:00
|
|
|
|
using TMPro;
|
2025-05-04 16:41:23 +08:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
using System.Linq.Expressions;
|
2025-06-08 01:15:33 +08:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Sirenix.Utilities;
|
2025-02-14 22:04:21 -05:00
|
|
|
|
|
2025-02-08 01:21:40 +08:00
|
|
|
|
//又在写大粪 ——神币
|
2025-01-29 23:49:18 -05:00
|
|
|
|
namespace Ichni.Editor
|
|
|
|
|
|
{
|
|
|
|
|
|
public partial class EditorConsole : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public Interpreter functionInterpreter;
|
2025-02-20 03:15:42 +08:00
|
|
|
|
public TMP_InputField InputCommand;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
private Dictionary<int, string> historyCommand = new Dictionary<int, string>();
|
|
|
|
|
|
private int historycount = 0;
|
2025-02-04 15:05:05 +08:00
|
|
|
|
public GameObject ConsoleUI;
|
2025-06-08 01:15:33 +08:00
|
|
|
|
public TMP_Text cueText;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
bool isHide = true;
|
|
|
|
|
|
|
|
|
|
|
|
public void GetChange(string change)
|
|
|
|
|
|
{
|
2025-06-08 01:15:33 +08:00
|
|
|
|
// 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<MethodInfo> 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)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (method == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
string methodName = method.Name;
|
|
|
|
|
|
// 3. 获取参数信息
|
|
|
|
|
|
var parameters = method.GetParameters();
|
|
|
|
|
|
if (parameters.Length == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
cueText.text += $"{methodName} " + "\n";
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 生成参数提示
|
|
|
|
|
|
string paramHint = string.Join(" ", parameters.Select(p =>
|
|
|
|
|
|
p.IsOptional ? $"[{p.ParameterType.Name}:{p.Name}]" : $"{p.ParameterType.Name}:{p.Name}"
|
|
|
|
|
|
));
|
|
|
|
|
|
cueText.text += $"{methodName} {paramHint}".Trim() + "\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (cueText.text.IsNullOrWhitespace())
|
|
|
|
|
|
{
|
|
|
|
|
|
cueText.text = "No matching commands found.";
|
|
|
|
|
|
}
|
|
|
|
|
|
// });
|
2025-02-08 01:21:40 +08:00
|
|
|
|
|
2025-06-08 01:15:33 +08:00
|
|
|
|
// t.RunSynchronously();
|
2025-02-08 01:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
public void GetCommand(string Command)//当提交命令时
|
2025-02-04 15:05:05 +08:00
|
|
|
|
{
|
2025-02-22 00:05:36 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
functionInterpreter.Eval(Command);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("WTF Command! " + e);
|
|
|
|
|
|
LogWindow.Log("Unknow Command!", Color.red);
|
|
|
|
|
|
}
|
2025-02-04 15:05:05 +08:00
|
|
|
|
}
|
2025-02-22 00:05:36 +08:00
|
|
|
|
private void Update()
|
|
|
|
|
|
{
|
2025-02-21 15:30:14 +08:00
|
|
|
|
UIscale();
|
2025-02-22 00:05:36 +08:00
|
|
|
|
if (InputCommand.isFocused) InputDect();
|
2025-02-21 15:30:14 +08:00
|
|
|
|
}
|
2025-02-22 00:05:36 +08:00
|
|
|
|
private void UIscale()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Keyboard.current.backquoteKey.wasPressedThisFrame)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
2025-02-20 03:15:42 +08:00
|
|
|
|
ConsoleUI.SetActive(isHide);
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
|
|
|
|
|
isHide = !isHide;
|
2025-02-28 20:08:00 +08:00
|
|
|
|
if (!isHide) StartCoroutine(WindowAnim.ShowPanelOnScale(InputCommand.gameObject));
|
2025-02-12 17:57:26 +08:00
|
|
|
|
}
|
2025-02-20 15:25:42 +08:00
|
|
|
|
|
2025-02-21 15:30:14 +08:00
|
|
|
|
}
|
2025-02-10 15:56:10 +08:00
|
|
|
|
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//这是史,不要看
|
|
|
|
|
|
private void InputDect()
|
|
|
|
|
|
{
|
2025-06-07 15:09:22 +08:00
|
|
|
|
// 向下翻历史命令
|
2025-02-22 00:05:36 +08:00
|
|
|
|
if (Keyboard.current.downArrowKey.wasPressedThisFrame)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (historyCommand.Count - 1 > historycount)
|
|
|
|
|
|
{
|
|
|
|
|
|
historycount++;
|
|
|
|
|
|
InputCommand.text = historyCommand[historycount];
|
2025-02-10 15:56:10 +08:00
|
|
|
|
}
|
2025-02-22 00:05:36 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
InputCommand.text = "";
|
|
|
|
|
|
historycount = historyCommand.Count;
|
2025-02-08 01:21:40 +08:00
|
|
|
|
}
|
2025-06-07 15:09:22 +08:00
|
|
|
|
return;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
}
|
2025-06-07 15:09:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 向上翻历史命令
|
2025-02-22 00:05:36 +08:00
|
|
|
|
if (Keyboard.current.upArrowKey.wasPressedThisFrame && historycount != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
historycount--;
|
|
|
|
|
|
InputCommand.text = historyCommand[historycount];
|
2025-06-07 15:09:22 +08:00
|
|
|
|
return;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
}
|
2025-06-07 15:09:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 提交命令
|
2025-02-22 00:05:36 +08:00
|
|
|
|
if (Keyboard.current.enterKey.wasPressedThisFrame)
|
|
|
|
|
|
{
|
2025-06-07 15:09:22 +08:00
|
|
|
|
string input = InputCommand.text;
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(input))
|
2025-02-22 00:05:36 +08:00
|
|
|
|
{
|
2025-06-07 15:09:22 +08:00
|
|
|
|
InputCommand.text = "";
|
|
|
|
|
|
return;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
}
|
2025-06-08 01:15:33 +08:00
|
|
|
|
string ExpoCommand = TransformCommand(input);
|
2025-06-07 15:09:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-02-22 00:05:36 +08:00
|
|
|
|
print(ExpoCommand);
|
|
|
|
|
|
GetCommand(ExpoCommand);
|
2025-06-07 15:09:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 记录历史命令
|
|
|
|
|
|
if (historyCommand.ContainsKey(historycount))
|
|
|
|
|
|
historyCommand[historycount] = input;
|
|
|
|
|
|
else
|
|
|
|
|
|
historyCommand.Add(historycount, input);
|
|
|
|
|
|
|
2025-02-22 00:05:36 +08:00
|
|
|
|
historycount++;
|
|
|
|
|
|
InputCommand.text = "";
|
|
|
|
|
|
}
|
2025-02-08 01:21:40 +08:00
|
|
|
|
}
|
2025-06-08 01:15:33 +08:00
|
|
|
|
private string TransformCommand(string input)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 处理命令格式,适配 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();
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-06-08 01:15:33 +08:00
|
|
|
|
// 匹配参数:中括号、引号、或连续非空白
|
|
|
|
|
|
var argMatches = Regex.Matches(args, @"(\[[^\]]+\]|""(?:[^""\\]|\\.)*""|\S+)");
|
|
|
|
|
|
var argList = argMatches.Cast<Match>().Select(m => m.Value).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
List<string> processedArgs = new List<string>();
|
|
|
|
|
|
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({nums[0]},{nums[1]})");
|
|
|
|
|
|
else if (nums.Length == 3)
|
|
|
|
|
|
processedArgs.Add($"new Vector3({nums[0]},{nums[1]},{nums[2]})");
|
|
|
|
|
|
else
|
|
|
|
|
|
processedArgs.Add(a); // 不是2或3维,原样返回
|
|
|
|
|
|
}
|
|
|
|
|
|
// 已有引号的字符串
|
|
|
|
|
|
else if (a.StartsWith("\"") && a.EndsWith("\""))
|
|
|
|
|
|
{
|
|
|
|
|
|
processedArgs.Add(a);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 数字
|
|
|
|
|
|
else if (Regex.IsMatch(a, @"^-?\d+(\.\d+)?$"))
|
|
|
|
|
|
{
|
|
|
|
|
|
processedArgs.Add(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;
|
|
|
|
|
|
}
|
2025-01-29 23:49:18 -05:00
|
|
|
|
private void Start()
|
|
|
|
|
|
{
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-01-29 23:49:18 -05:00
|
|
|
|
SetUpFunctions();
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-01-29 23:49:18 -05:00
|
|
|
|
//Test
|
2025-02-20 03:15:42 +08:00
|
|
|
|
// functionInterpreter.Eval("print(\"Hello World!\")");
|
|
|
|
|
|
// functionInterpreter.Eval("log(\"Hello World but debug!\")");
|
2025-01-29 23:49:18 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-01-29 23:49:18 -05:00
|
|
|
|
public partial class EditorConsole
|
|
|
|
|
|
{
|
2025-05-04 16:41:23 +08:00
|
|
|
|
public Inspector inspector => EditorManager.instance.uiManager.inspector;
|
|
|
|
|
|
public Hierarchy hierarchy => EditorManager.instance.uiManager.hierarchy;
|
|
|
|
|
|
public LogWindow logWindow => EditorManager.instance.uiManager.mainPage.logWindow;
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-05-04 16:41:23 +08:00
|
|
|
|
public List<string> commandList = new List<string>();
|
|
|
|
|
|
public void SetUpFunctions()
|
2025-01-29 23:49:18 -05:00
|
|
|
|
{
|
2025-06-08 01:15:33 +08:00
|
|
|
|
functionInterpreter = new Interpreter()
|
|
|
|
|
|
.Reference(typeof(Vector3))
|
|
|
|
|
|
.Reference(typeof(Vector2));//这是AI给的东西?
|
2025-05-04 16:41:23 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// functionInterpreter.SetFunction("test", (Action)Test);
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-05-04 16:41:23 +08:00
|
|
|
|
// functionInterpreter.SetFunction("kill", (Action)Kill);
|
|
|
|
|
|
// functionInterpreter.SetFunction("lgp", (Action<int, float, float, float, float, float, float>)LGenPathNodes);
|
|
|
|
|
|
// functionInterpreter.SetFunction("print", (Action<object>)print);
|
|
|
|
|
|
// functionInterpreter.SetFunction("log", (Action<object>)Debug.Log);
|
|
|
|
|
|
// functionInterpreter.SetFunction("tp", (Action<float, float, float>)Tp);
|
|
|
|
|
|
// functionInterpreter.SetFunction("tp", (Action)Tp);
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-01-29 23:49:18 -05:00
|
|
|
|
}
|
2025-02-08 01:21:40 +08:00
|
|
|
|
|
2025-05-04 16:41:23 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
public static class EditorConsoleMethods
|
|
|
|
|
|
{
|
|
|
|
|
|
public static Inspector inspector => EditorManager.instance.uiManager.inspector;
|
|
|
|
|
|
public static Hierarchy hierarchy => EditorManager.instance.uiManager.hierarchy;
|
|
|
|
|
|
public static LogWindow logWindow => EditorManager.instance.uiManager.mainPage.logWindow;
|
|
|
|
|
|
public static void kill()
|
2025-02-22 00:05:36 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (inspector.connectedGameElement == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogWindow.Log("Please select a GameElement first!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (int i = inspector.connectedGameElement.childElementList.Count - 1; i <= 0; i--)
|
|
|
|
|
|
{
|
2025-02-22 00:30:08 +08:00
|
|
|
|
EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(
|
|
|
|
|
|
inspector.connectedGameElement.childElementList[i]
|
|
|
|
|
|
);
|
|
|
|
|
|
inspector.connectedGameElement.childElementList.RemoveAt(i);
|
2025-02-22 00:05:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-04 16:41:23 +08:00
|
|
|
|
public static void test()
|
2025-02-12 01:57:18 +08:00
|
|
|
|
{
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
2025-02-12 01:57:18 +08:00
|
|
|
|
}
|
2025-06-08 01:15:33 +08:00
|
|
|
|
public static void test2()
|
|
|
|
|
|
{
|
2025-02-08 01:21:40 +08:00
|
|
|
|
|
2025-06-08 01:15:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
public static void tttttt()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void tp(Vector3 pos)
|
2025-04-13 14:04:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (EditorManager.instance.cameraManager.isSceneCameraActive)
|
|
|
|
|
|
{
|
2025-06-08 01:15:33 +08:00
|
|
|
|
EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position = pos;
|
2025-04-13 14:04:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-08 01:15:33 +08:00
|
|
|
|
// 保留无参tp
|
2025-05-04 16:41:23 +08:00
|
|
|
|
public static void tp()
|
2025-04-13 14:04:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (EditorManager.instance.cameraManager.isSceneCameraActive)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position =
|
|
|
|
|
|
inspector.connectedGameElement.transform.position;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-10 15:56:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-02-22 00:05:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-06-08 01:15:33 +08:00
|
|
|
|
public static void lgp(int loop, Vector3 start, Vector3 end)
|
2025-02-22 00:05:36 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
|
|
|
|
|
|
{
|
|
|
|
|
|
LogWindow.Log("Please select a Track first!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
Track track = (Track)inspector.connectedGameElement;
|
|
|
|
|
|
for (int i = 0; i < loop; i++)
|
|
|
|
|
|
{
|
2025-06-08 01:15:33 +08:00
|
|
|
|
float t = (float)i / loop;
|
|
|
|
|
|
float x = start.x + (end.x - start.x) * t;
|
|
|
|
|
|
float y = start.y + (end.y - start.y) * t;
|
|
|
|
|
|
float z = start.z + (end.z - start.z) * t;
|
2025-02-22 01:56:33 -05:00
|
|
|
|
PathNode j = PathNode.GenerateElement("PathNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, track, true);
|
2025-02-22 00:05:36 +08:00
|
|
|
|
j.transformSubmodule.originalPosition = new Vector3(x, y, z);
|
|
|
|
|
|
}
|
2025-06-08 01:15:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 支持主轴方向的螺旋线式 PathNode
|
|
|
|
|
|
public static void spiral(int loop, Vector3 center, float r, float h, int pointsPerTurn, string axis = "y")
|
|
|
|
|
|
{
|
|
|
|
|
|
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
|
|
|
|
|
|
{
|
|
|
|
|
|
LogWindow.Log("Please select a Track first!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
Track track = (Track)inspector.connectedGameElement;
|
|
|
|
|
|
for (int i = 0; i < loop; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
float t = (float)i / loop;
|
|
|
|
|
|
float angle = 2 * Mathf.PI * (i % pointsPerTurn) / pointsPerTurn;
|
|
|
|
|
|
Vector3 pos = new Vector3(center.x, center.y, center.z);
|
|
|
|
|
|
|
|
|
|
|
|
switch (axis.ToLower())
|
|
|
|
|
|
{
|
|
|
|
|
|
case "x":
|
|
|
|
|
|
pos.x += h * t;
|
|
|
|
|
|
pos.y += r * Mathf.Cos(angle);
|
|
|
|
|
|
pos.z += r * Mathf.Sin(angle);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "y":
|
|
|
|
|
|
pos.x += r * Mathf.Cos(angle);
|
|
|
|
|
|
pos.y += h * t;
|
|
|
|
|
|
pos.z += r * Mathf.Sin(angle);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "z":
|
|
|
|
|
|
pos.x += r * Mathf.Cos(angle);
|
|
|
|
|
|
pos.y += r * Mathf.Sin(angle);
|
|
|
|
|
|
pos.z += h * t;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
pos.x += r * Mathf.Cos(angle);
|
|
|
|
|
|
pos.y += h * t;
|
|
|
|
|
|
pos.z += r * Mathf.Sin(angle);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-02-10 15:56:10 +08:00
|
|
|
|
|
2025-06-08 01:15:33 +08:00
|
|
|
|
PathNode node = PathNode.GenerateElement("SpiralNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, track, true);
|
|
|
|
|
|
node.transformSubmodule.originalPosition = pos;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 任意方向的螺旋线式 PathNode(中心点和方向均为Vector3)
|
|
|
|
|
|
public static void spiral(int loop, Vector3 center, float r, float h, int pointsPerTurn, Vector3 dir)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
|
|
|
|
|
|
{
|
|
|
|
|
|
LogWindow.Log("Please select a Track first!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
Vector3 direction = dir.normalized;
|
|
|
|
|
|
if (direction == Vector3.zero) direction = Vector3.up; // 默认Y轴
|
|
|
|
|
|
|
|
|
|
|
|
Quaternion rot = Quaternion.FromToRotation(Vector3.up, direction);
|
|
|
|
|
|
|
|
|
|
|
|
Track track = (Track)inspector.connectedGameElement;
|
|
|
|
|
|
for (int i = 0; i < loop; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
float t = (float)i / loop;
|
|
|
|
|
|
float angle = 2 * Mathf.PI * (i % pointsPerTurn) / pointsPerTurn;
|
|
|
|
|
|
Vector3 localPos = new Vector3(
|
|
|
|
|
|
r * Mathf.Cos(angle),
|
|
|
|
|
|
h * t,
|
|
|
|
|
|
r * Mathf.Sin(angle)
|
|
|
|
|
|
);
|
|
|
|
|
|
Vector3 pos = center + rot * localPos;
|
|
|
|
|
|
|
|
|
|
|
|
PathNode node = PathNode.GenerateElement("SpiralNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, track, true);
|
|
|
|
|
|
node.transformSubmodule.originalPosition = pos;
|
|
|
|
|
|
}
|
2025-02-04 15:05:05 +08:00
|
|
|
|
}
|
2025-01-29 23:49:18 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|