using System; using System.Collections; using System.Collections.Generic; using System.Drawing.Printing; using System.Linq; using System.Text.RegularExpressions; using Ichni.RhythmGame; using UnityEngine; namespace Ichni.Editor { 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 tp(Vector3 pos) { if (EditorManager.instance.cameraManager.isSceneCameraActive) { EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position = pos; } } // 保留无参tp public static void tp() { if (EditorManager.instance.cameraManager.isSceneCameraActive) { EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position = inspector.connectedGameElement.transform.position; } } public static void ReName(string message) { inspector.connectedGameElement.elementName = message; inspector.connectedGameElement.Refresh(); } public static void Lgp(int loop, Vector3 start, Vector3 end) { 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 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; PathNode j = PathNode.GenerateElement("PathNode" + i.ToString(), Guid.NewGuid(), new List(), true, track, true); j.transformSubmodule.originalPosition = new Vector3(x, y, z); } } // 支持主轴方向的螺旋线式 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; } PathNode node = PathNode.GenerateElement("SpiralNode" + i.ToString(), Guid.NewGuid(), new List(), 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(), true, track, true); node.transformSubmodule.originalPosition = pos; } } public static void DelSameInParent() { Type type = inspector.connectedGameElement.GetType(); for (int i = inspector.connectedGameElement.parentElement.childElementList.Count - 1; i >= 0; i--) { GameElement element = inspector.connectedGameElement.parentElement.childElementList[i]; if (element.GetType() == type && element != inspector.connectedGameElement) { EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(element); } } EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(inspector.connectedGameElement); } public static void SamplerImport(string inputData) { if (!EditorManager.instance.useNotePrefab) { LogWindow.Log("Pleasee nable \"Note Prefab\" in EditorManager", Color.red); return; } // 改进的正则表达式:支持5个字段和负数 Regex dataPattern = new Regex( @"\(\s*([^,]+?)\s*,\s*([^,]+?)\s*,\s*([-+]?\d*\.?\d+)\s*,\s*([-+]?\d*\.?\d+)\s*(?:,\s*([-+]?\d*\.?\d+)\s*)?\)", RegexOptions.Compiled ); Debug.Log("===== ====="); MatchCollection matches = dataPattern.Matches(inputData); Debug.Log($": {matches.Count}"); int recordCount = 1; Track findTrack(string Findtext) { List tracks = EditorManager.instance.beatmapContainer.gameElementList.OfType().Where(i => i.elementName == Findtext).ToList(); if (tracks.Count == 0) { Debug.LogError($"未找到名为 {Findtext} 的轨道"); return null; } else if (tracks.Count > 1) { LogWindow.Log($"Repeat Track Of {Findtext}, please Cautious", Color.yellow); } return tracks[0]; } foreach (Match match in matches) { if (match.Success) { string action = match.Groups[1].Value.Trim(); string id = match.Groups[2].Value.Trim(); // 解析公共字段 float timestamp = float.Parse(match.Groups[3].Value); float value = float.Parse(match.Groups[4].Value); // 处理Hold操作的特殊字段 float holdDuration = 0f; bool isHold = false; if (action == "Hold" && match.Groups[5].Success) { isHold = true; holdDuration = float.Parse(match.Groups[5].Value); } // 构建输出信息 string logEntry = $"[记录#{recordCount++}] " + $"Note: {action.PadRight(5)} | " + $"ID: {id} | " + $"时间: {timestamp.ToString("0.000").PadLeft(7)} | " + $"X值: {value.ToString("0.000").PadLeft(7)}"; if (isHold) { logEntry += $" | 持续时间: {holdDuration.ToString("0.000")}"; } Debug.Log(logEntry); if (findTrack(id) is null) { Debug.LogError($"未找到名为 {id} 的轨道"); continue; } // 根据动作类型处理 switch (action) { case "Tap": Tap a = Tap.GenerateElement("New Tap", Guid.NewGuid(), new List(), false, findTrack(id), timestamp); ((TransformSubmodule)a.noteVisual.submoduleList.Where(i => i is TransformSubmodule)?.First()).originalPosition = new Vector3(value, 0, 0); a.noteVisual.SetEditorSubmodules(); // 设置selset a.Refresh(); break; case "Stay": Stay b = Stay.GenerateElement("New Stay", Guid.NewGuid(), new List(), false, findTrack(id), timestamp); ((TransformSubmodule)b.noteVisual.submoduleList.Where(i => i is TransformSubmodule)?.First()).originalPosition = new Vector3(value, 0, 0); b.noteVisual.SetEditorSubmodules(); // 设置selset b.Refresh(); break; case "Hold": Hold c = Hold.GenerateElement("New Hold", Guid.NewGuid(), new List(), false, findTrack(id), timestamp, timestamp + holdDuration); ((TransformSubmodule)c.noteVisual.submoduleList.Where(i => i is TransformSubmodule)?.First()).originalPosition = new Vector3(value, 0, 0); c.noteVisual.SetEditorSubmodules(); // 设置selset c.Refresh(); break; case "Flick": Flick d = Flick.GenerateElement("New Flick", Guid.NewGuid(), new List(), false, findTrack(id), timestamp, new List()); ((TransformSubmodule)d.noteVisual.submoduleList.Where(i => i is TransformSubmodule)?.First()).originalPosition = new Vector3(value, 0, 0); d.noteVisual.SetEditorSubmodules(); // 设置selset d.Refresh(); break; default: Debug.LogError($"未知类型: {action}"); break; } } } Debug.Log("===== ====="); } public static void SetNoteHLInGame(bool forceSetOff = false, bool SameTheme = false) { var noteBases = EditorManager.instance.beatmapContainer.gameElementList.OfType().ToList(); // 先全部关闭高亮(如果forceSetOff为true) if (forceSetOff) { foreach (var note in noteBases) { note.noteVisual.isHighlighted = false; note.noteVisual.SetHighlight(); } } // 按时间分组 var groups = SameTheme ? noteBases.GroupBy(n => (object)new { n.exactJudgeTime, Type = n.GetType() }) : noteBases.GroupBy(n => (object)n.exactJudgeTime); foreach (var group in groups) { if (group.Count() > 1) { foreach (var note in group) { note.noteVisual.isHighlighted = true; note.noteVisual.SetHighlight(); } } } } public static void SetNoteHLInElement(bool forceSetOff = false, bool SameTheme = false) { var noteBases = inspector.connectedGameElement.GetAllGameElementsFromThis().OfType().ToList(); // 先全部关闭高亮(如果forceSetOff为true) if (forceSetOff) { foreach (var note in noteBases) { note.noteVisual.isHighlighted = false; note.noteVisual.SetHighlight(); } } // 按时间分组 var groups = SameTheme ? noteBases.GroupBy(n => (object)new { n.exactJudgeTime, Type = n.GetType() }) : noteBases.GroupBy(n => (object)n.exactJudgeTime); foreach (var group in groups) { if (group.Count() > 1) { foreach (var note in group) { note.noteVisual.isHighlighted = true; note.noteVisual.SetHighlight(); } } } } } }