Files
ichni_Creator_Studio/Assets/Scripts/Console/EditorConsoleMethods.cs
TRAfoer 135f61a857 改改改
重大bug修复:track删除pathnode后不能正确更新

Signed-off-by: TRAfoer <lhf190@outlook.com>
2025-07-10 20:40:03 +08:00

402 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string>(), 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<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;
}
}
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<Track> tracks = EditorManager.instance.beatmapContainer.gameElementList.OfType<Track>().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<string>(), 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<string>(), 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<string>(), 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<string>(), false, findTrack(id), timestamp, new List<Vector2>());
((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<NoteBase>().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<NoteBase>().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 swapDisplacement()
{
Displacement displacement = inspector.connectedGameElement as Displacement;
if (displacement == null)
{
LogWindow.Log("Please select a Displacement first!", Color.red);
return;
}
foreach (var anim in displacement.positionX.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in displacement.positionY.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in displacement.positionZ.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
}
public static void swapSwirl()
{
Swirl swirl = inspector.connectedGameElement as Swirl;
if (swirl == null)
{
LogWindow.Log("Please select a Swirl first!", Color.red);
return;
}
foreach (var anim in swirl.eulerAngleX.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in swirl.eulerAngleY.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in swirl.eulerAngleZ.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
}
public static void swapScale()
{
Scale scale = inspector.connectedGameElement as Scale;
if (scale == null)
{
LogWindow.Log("Please select a Scale first!", Color.red);
return;
}
foreach (var anim in scale.scaleX.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in scale.scaleY.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
foreach (var anim in scale.scaleZ.animations)
{
anim.endValue = -anim.endValue;
anim.startValue = -anim.startValue;
}
}
}
}