我死去

目前添加了一个能够深度查找和设置反射的helper,但是Tag的系统仍然不完全,另外我觉得console可以重构了

Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2025-12-14 12:15:07 +08:00
parent 1bbb1c51ab
commit 7a2bc844bd
22 changed files with 127636 additions and 35827 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -46,33 +46,14 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
serializationData: serializationData:
SerializedFormat: 2 SerializedFormat: 0
SerializedBytes: SerializedBytes: 29010b00000065006c0065006d0065006e007400470075006900640037792c70b476d344ad481072561faaec01010d0000007300750062006d006f00640075006c0065004c006900730074002f00000000015e000000530079007300740065006d002e0043006f006c006c0065006300740069006f006e0073002e00470065006e0065007200690063002e004c00690073007400600031005b005b004900630068006e0069002e00520068007900740068006d00470061006d0065002e005300750062006d006f00640075006c00650042006100730065002c00200041007300730065006d0062006c0079002d004300530068006100720070005d005d002c0020006d00730063006f0072006c00690062000000000006000000000000000007052d010b00000065006e00610062006c00650054007900700065007300
ReferencedUnityObjects: [] ReferencedUnityObjects: []
SerializedBytesString: SerializedBytesString:
Prefab: {fileID: 0} Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: [] PrefabModificationsReferencedUnityObjects: []
PrefabModifications: [] PrefabModifications: []
SerializationNodes: SerializationNodes: []
- Name: elementGuid
Entry: 2
Data: 702c793776b444d3ad481072561faaec
- Name: submoduleList
Entry: 7
Data: 0|System.Collections.Generic.List`1[[Ichni.RhythmGame.SubmoduleBase,
Assembly-CSharp]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name: enableTypes
Entry: 6
Data:
elementName: elementName:
tags: [] tags: []
parentElement: {fileID: 0} parentElement: {fileID: 0}
@@ -249,7 +230,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_RenderShadows: 1 m_RenderShadows: 0
m_RequiresDepthTextureOption: 2 m_RequiresDepthTextureOption: 2
m_RequiresOpaqueTextureOption: 2 m_RequiresOpaqueTextureOption: 2
m_CameraType: 0 m_CameraType: 0
@@ -261,7 +242,7 @@ MonoBehaviour:
m_VolumeTrigger: {fileID: 0} m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2 m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 1 m_RenderPostProcessing: 1
m_Antialiasing: 0 m_Antialiasing: 2
m_AntialiasingQuality: 2 m_AntialiasingQuality: 2
m_StopNaN: 0 m_StopNaN: 0
m_Dithering: 0 m_Dithering: 0

View File

@@ -8,21 +8,22 @@ Material:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_Name: TrackDisplayer m_Name: TrackDisplayer
m_Shader: {fileID: 4800000, guid: 8516d7a69675844a7a0b7095af7c46af, type: 3} m_Shader: {fileID: 4800000, guid: 650dd9526735d5b46b79224bc6e94025, type: 3}
m_Parent: {fileID: 0} m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0 m_ModifiedSerializedProperties: 0
m_ValidKeywords: m_ValidKeywords:
- _EMISSION - _SURFACE_TYPE_TRANSPARENT
- _RECEIVE_SHADOWS_OFF
m_InvalidKeywords: m_InvalidKeywords:
- _FLIPBOOKBLENDING_OFF - _EMISSION
m_LightmapFlags: 0 m_LightmapFlags: 0
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
m_DoubleSidedGI: 1 m_DoubleSidedGI: 0
m_CustomRenderQueue: 2010 m_CustomRenderQueue: 3010
stringTagMap: stringTagMap:
RenderType: Opaque RenderType: Transparent
disabledShaderPasses: [] disabledShaderPasses:
- DepthOnly
- SHADOWCASTER
m_LockedProperties: m_LockedProperties:
m_SavedProperties: m_SavedProperties:
serializedVersion: 3 serializedVersion: 3
@@ -109,7 +110,7 @@ Material:
- _ClearCoatMask: 0 - _ClearCoatMask: 0
- _ClearCoatSmoothness: 0 - _ClearCoatSmoothness: 0
- _ColorMode: 0 - _ColorMode: 0
- _Cull: 0 - _Cull: 2
- _Cutoff: 0.5 - _Cutoff: 0.5
- _DetailAlbedoMapScale: 1 - _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
@@ -117,8 +118,8 @@ Material:
- _DistortionEnabled: 0 - _DistortionEnabled: 0
- _DistortionStrength: 1 - _DistortionStrength: 1
- _DistortionStrengthScaled: 0.1 - _DistortionStrengthScaled: 0.1
- _DstBlend: 0 - _DstBlend: 10
- _DstBlendAlpha: 0 - _DstBlendAlpha: 10
- _EmissionEnabled: 0 - _EmissionEnabled: 0
- _EnableExternalAlpha: 0 - _EnableExternalAlpha: 0
- _EnvironmentReflections: 1 - _EnvironmentReflections: 1
@@ -136,6 +137,7 @@ Material:
- _QueueControl: 0 - _QueueControl: 0
- _QueueOffset: 10 - _QueueOffset: 10
- _ReceiveShadows: 0 - _ReceiveShadows: 0
- _SampleGI: 0
- _Shininess: 0 - _Shininess: 0
- _Smoothness: 0 - _Smoothness: 0
- _SmoothnessSource: 0 - _SmoothnessSource: 0
@@ -145,9 +147,9 @@ Material:
- _SoftParticlesNearFadeDistance: 0 - _SoftParticlesNearFadeDistance: 0
- _SpecSource: 0 - _SpecSource: 0
- _SpecularHighlights: 1 - _SpecularHighlights: 1
- _SrcBlend: 1 - _SrcBlend: 5
- _SrcBlendAlpha: 1 - _SrcBlendAlpha: 1
- _Surface: 0 - _Surface: 1
- _UseAoMap: 0 - _UseAoMap: 0
- _UseColorMap: 0 - _UseColorMap: 0
- _UseEmissiveMap: 0 - _UseEmissiveMap: 0
@@ -155,7 +157,7 @@ Material:
- _UseNormalMap: 0 - _UseNormalMap: 0
- _UseRoughnessMap: 0 - _UseRoughnessMap: 0
- _WorkflowMode: 1 - _WorkflowMode: 1
- _ZWrite: 1 - _ZWrite: 0
m_Colors: m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _BaseColorAddSubDiff: {r: 0, g: 0, b: 0, a: 0} - _BaseColorAddSubDiff: {r: 0, g: 0, b: 0, a: 0}

File diff suppressed because one or more lines are too long

View File

@@ -46,6 +46,8 @@ namespace Ichni.Editor
)); ));
return $"{methodName} {paramHint}".Trim() + "\n"; return $"{methodName} {paramHint}".Trim() + "\n";
} }
// ... (omitted parts)
public void GetChange(string change) public void GetChange(string change)
{ {
if (change == "help") if (change == "help")
@@ -80,8 +82,9 @@ namespace Ichni.Editor
string funcName = match.Groups[1].Value; string funcName = match.Groups[1].Value;
// 2. 查找方法 // 2. 查找方法
// 【修改点】:使用 StringComparison.OrdinalIgnoreCase 实现忽略大小写的查找
List<MethodInfo> methods = typeof(EditorConsoleMethods).GetMethods() List<MethodInfo> methods = typeof(EditorConsoleMethods).GetMethods()
.Where(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void) && m.Name.Contains(funcName)).ToList(); .Where(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void) && m.Name.IndexOf(funcName, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
cueText.text = ""; cueText.text = "";
for (int i = 0; i < methods.Count; i++) for (int i = 0; i < methods.Count; i++)
{ {
@@ -96,6 +99,7 @@ namespace Ichni.Editor
// t.RunSynchronously(); // t.RunSynchronously();
} }
// ... (omitted parts)
public void GetCommand(string Command)//当提交命令时 public void GetCommand(string Command)//当提交命令时
{ {
try try
@@ -132,7 +136,42 @@ namespace Ichni.Editor
} }
} }
// 在 TransformCommand 或 CheckCtrlNumberShortcut 附近添加
// 辅助方法:获取 cueText 中第一个提示的命令名
private string GetFinalCommandForExecution(string input)
{
string trimmed = input.Trim();
// 1. 提取用户输入的命令名部分
var match = Regex.Match(trimmed, @"^(\w+)");
if (!match.Success)
{
// 如果不是合法的命令开头,直接尝试转换并返回 (DynamicExpresso 也许能处理赋值)
return TransformCommand(trimmed);
}
string funcName = match.Groups[1].Value;
// 2. 重新查找匹配的方法 (和 GetChange 逻辑一致,保证一致性)
List<MethodInfo> methods = typeof(EditorConsoleMethods).GetMethods()
.Where(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void) && m.Name.IndexOf(funcName, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
string finalCommandToTransform = input;
// 3. 找到最佳匹配并替换
if (methods.Count > 0)
{
// 最佳匹配是列表中的第一个方法名
string firstCommand = methods[0].Name;
// 替换用户输入中的命令名部分为完整的、匹配到的命令名
// 例如:用户输入 "pr 10",替换为 "print 10"
finalCommandToTransform = Regex.Replace(trimmed, @"^(\w+)", firstCommand);
}
// 4. 转换并返回 DynamicExpresso 表达式
return TransformCommand(finalCommandToTransform);
}
//这是史,不要看 //这是史,不要看
@@ -165,19 +204,20 @@ namespace Ichni.Editor
// 提交命令 // 提交命令
if (Keyboard.current.enterKey.wasPressedThisFrame) if (Keyboard.current.enterKey.wasPressedThisFrame)
{ {
string input = InputCommand.text; string input = InputCommand.text; // 原始命令文本
if (string.IsNullOrWhiteSpace(input)) if (string.IsNullOrWhiteSpace(input))
{ {
InputCommand.text = ""; InputCommand.text = "";
return; return;
} }
string ExpoCommand = TransformCommand(input);
// 【修改点】:调用新方法获取最终执行的命令(已包含修正逻辑和 TransformCommand
string ExpoCommand = GetFinalCommandForExecution(input);
print(ExpoCommand); // print(ExpoCommand); // 调试语句,可选
GetCommand(ExpoCommand); GetCommand(ExpoCommand);
// 记录历史命令 // 记录历史命令,使用原始命令 input
if (historyCommand.ContainsKey(historycount)) if (historyCommand.ContainsKey(historycount))
historyCommand[historycount] = input; historyCommand[historycount] = input;
else else
@@ -306,6 +346,7 @@ namespace Ichni.Editor
{ {
functionInterpreter = new Interpreter() functionInterpreter = new Interpreter()
.Reference(typeof(Vector3)) .Reference(typeof(Vector3))
.Reference(typeof(Color))
.Reference(typeof(Vector2));//这是AI给的东西 .Reference(typeof(Vector2));//这是AI给的东西
foreach (MethodInfo i in typeof(EditorConsoleMethods).GetMethods(). foreach (MethodInfo i in typeof(EditorConsoleMethods).GetMethods().
ToList().Where(i => i.IsStatic && i.IsPublic && (i.ReturnType == typeof(void)))) ToList().Where(i => i.IsStatic && i.IsPublic && (i.ReturnType == typeof(void))))

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ichni.RhythmGame; using Ichni.RhythmGame;
@@ -15,11 +16,16 @@ namespace Ichni.Editor
{ {
public static class EditorConsoleMethods public static class EditorConsoleMethods
{ {
#region UI/Manager Accessors (UI/访)
public static Inspector inspector => EditorManager.instance.uiManager.inspector; public static Inspector inspector => EditorManager.instance.uiManager.inspector;
public static Hierarchy hierarchy => EditorManager.instance.uiManager.hierarchy; public static Hierarchy hierarchy => EditorManager.instance.uiManager.hierarchy;
public static LogWindow logWindow => EditorManager.instance.uiManager.mainPage.logWindow; public static LogWindow logWindow => EditorManager.instance.uiManager.mainPage.logWindow;
#endregion
#region Scene/Transform Operations (/)
/// <summary>
/// 传送场景相机到指定位置
/// </summary>
public static void tp(Vector3 pos) public static void tp(Vector3 pos)
{ {
if (EditorManager.instance.cameraManager.isSceneCameraActive) if (EditorManager.instance.cameraManager.isSceneCameraActive)
@@ -27,7 +33,10 @@ namespace Ichni.Editor
EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position = pos; EditorManager.instance.cameraManager.sceneCamera.sceneCamera.transform.position = pos;
} }
} }
// 保留无参tp
/// <summary>
/// 传送场景相机到选中元素位置
/// </summary>
public static void tp() public static void tp()
{ {
if (EditorManager.instance.cameraManager.isSceneCameraActive) if (EditorManager.instance.cameraManager.isSceneCameraActive)
@@ -37,13 +46,20 @@ namespace Ichni.Editor
} }
} }
/// <summary>
/// 重命名选中元素
/// </summary>
public static void ReName(string message) public static void ReName(string message)
{ {
inspector.connectedGameElement.elementName = message; inspector.connectedGameElement.elementName = message;
inspector.connectedGameElement.Refresh(); inspector.connectedGameElement.Refresh();
} }
#endregion
#region PathNode Generation ()
/// <summary>
/// 直线路径节点生成 (Line PathNode Generator)
/// </summary>
public static void Lgp(int loop, Vector3 start, Vector3 end, bool Clear = false, bool offsetOrigin = false) public static void Lgp(int loop, Vector3 start, Vector3 end, bool Clear = false, bool offsetOrigin = false)
{ {
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track)) if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
@@ -88,35 +104,8 @@ namespace Ichni.Editor
} }
/// <summary> /// <summary>
/// 将原有 PathNode 的变换(位置、旋转、缩放)迁移到新生成的最近 PathNode /// 主轴方向的螺旋线式 PathNode
/// </summary> /// </summary>
public static bool AdjustPathNodesToNearest(Track track, List<PathNode> newNodes, List<PathNode> oldNodes)
{
foreach (var oldNode in oldNodes)
{
// 找到距离 oldNode 最近的新节点
PathNode nearest = newNodes
.OrderBy(n => Vector3.Distance(n.transformSubmodule.originalPosition, oldNode.transformSubmodule.originalPosition))
.FirstOrDefault();
if (nearest != null)
{
// 计算 oldNode 的变换(直接用欧拉角,不用四元数)
Vector3 deltaPos = oldNode.transformSubmodule.originalPosition - oldNode.transformSubmodule.originalPosition;
Vector3 deltaEuler = oldNode.transformSubmodule.originalEulerAngles - oldNode.transformSubmodule.originalEulerAngles;
Vector3 deltaScale = oldNode.transformSubmodule.originalScale - oldNode.transformSubmodule.originalScale;
// 将变换应用到新节点
nearest.transformSubmodule.originalPosition += deltaPos;
nearest.transformSubmodule.originalEulerAngles += deltaEuler;
nearest.transformSubmodule.originalScale += deltaScale;
}
}
return true;
}
// 支持主轴方向的螺旋线式 PathNode
public static void Spiral(int loop, Vector3 center, float r, float h, int pointsPerTurn, string axis = "y") 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)) if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
@@ -160,7 +149,9 @@ namespace Ichni.Editor
} }
} }
// 任意方向的螺旋线式 PathNode中心点和方向均为Vector3 /// <summary>
/// 任意方向的螺旋线式 PathNode中心点和方向均为Vector3
/// </summary>
public static void Spiral(int loop, Vector3 center, float r, float h, int pointsPerTurn, Vector3 dir) 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)) if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
@@ -189,6 +180,41 @@ namespace Ichni.Editor
node.transformSubmodule.originalPosition = pos; node.transformSubmodule.originalPosition = pos;
} }
} }
#endregion
#region PathNode/Track Utilities (/)
/// <summary>
/// 将原有 PathNode 的变换(位置、旋转、缩放)迁移到新生成的最近 PathNode 上
/// </summary>
public static bool AdjustPathNodesToNearest(Track track, List<PathNode> newNodes, List<PathNode> oldNodes)
{
foreach (var oldNode in oldNodes)
{
// 找到距离 oldNode 最近的新节点
PathNode nearest = newNodes
.OrderBy(n => Vector3.Distance(n.transformSubmodule.originalPosition, oldNode.transformSubmodule.originalPosition))
.FirstOrDefault();
if (nearest != null)
{
// 计算 oldNode 的变换(直接用欧拉角,不用四元数)
Vector3 deltaPos = oldNode.transformSubmodule.originalPosition - oldNode.transformSubmodule.originalPosition;
Vector3 deltaEuler = oldNode.transformSubmodule.originalEulerAngles - oldNode.transformSubmodule.originalEulerAngles;
Vector3 deltaScale = oldNode.transformSubmodule.originalScale - oldNode.transformSubmodule.originalScale;
// 将变换应用到新节点
nearest.transformSubmodule.originalPosition += deltaPos;
nearest.transformSubmodule.originalEulerAngles += deltaEuler;
nearest.transformSubmodule.originalScale += deltaScale;
}
}
return true;
}
/// <summary>
/// 删除父元素下所有与当前选中元素类型相同的其他元素,最后删除当前选中元素
/// </summary>
public static void DelSameInParent() public static void DelSameInParent()
{ {
Type type = inspector.connectedGameElement.GetType(); Type type = inspector.connectedGameElement.GetType();
@@ -206,6 +232,213 @@ namespace Ichni.Editor
} }
/// <summary>
/// 将选中轨道下所有音符附着到最近的 Trail 上
/// </summary>
public static void AttachNoteInNearestTrail()
{
Track track = inspector.connectedGameElement as Track;
if (track == null)
{
LogWindow.Log("Please select a Track first!", Color.red);
return;
}
List<NoteBase> noteBases = track.childElementList.OfType<NoteBase>().ToList();
List<IHaveTrail> trails = track.GetAllGameElementsFromThis().OfType<IHaveTrail>().ToList();
if (trails.Count == 0)
{
LogWindow.Log("The Track has no Trail!", Color.red);
return;
}
foreach (var note in noteBases)
{
IHaveTrail nearestTrail = null;
Vector3 FinalPos = Vector3.positiveInfinity;
foreach (var trail in trails)
{
if (trail is IHaveTransformSubmodule haveTransform && trail is GameElement gameElement)
{
Vector3 pos = haveTransform.transformSubmodule.originalPosition;
GameElement gameElement1 = gameElement;
while (gameElement1 != track)
{
if (gameElement1 is not IHaveTransformSubmodule)
{
gameElement1 = gameElement1.parentElement;
continue;
}
List<Displacement> animationBases = gameElement1.childElementList.OfType<Displacement>().ToList();
foreach (var displacement in animationBases)
{
pos += displacement.getValue(note.exactJudgeTime);
}
gameElement1 = gameElement1.parentElement;
}
if (Vector3.Distance(pos, (note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition) <=
Vector3.Distance(FinalPos, (note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition))
{
nearestTrail = trail;
FinalPos = pos;
}
}
}
if (nearestTrail != null)
{
(note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition = FinalPos;
note.Refresh();
(note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).Refresh();//捏妈妈滴为什么notevisual的TransformSubmodule不刷新
}
}
}
/// <summary>
/// 调整路径节点的 Z 坐标(可用于多轨道)
/// </summary>
public static void AdjustPathnodeZ(float OriginZpoint, float scale)
{
if (inspector.connectedGameElement == null)
{
LogWindow.Log($"please select a element (folder or track)", Color.red);
return;
}
if (inspector.connectedGameElement.GetType() != typeof(Track))
{
foreach (var i in inspector.connectedGameElement.childElementList.OfType<Track>())
{
inspector.connectedGameElement = i;
AdjustPathnodeZ(OriginZpoint, scale);
}
return;
}
Track track = (Track)inspector.connectedGameElement;
var pathnodes = track.trackPathSubmodule.pathNodeList;
foreach (var pathnode in pathnodes)
{
if (pathnode.childElementList.OfType<Displacement>().Count() > 0)
{
LogWindow.Log($"PathNode {pathnode.elementName} has Displacement, which may cause issues", Color.yellow);
}
float worldZ = pathnode.transform.position.z;
float deltaZ = worldZ - OriginZpoint;
float newZ = OriginZpoint + deltaZ * scale;
pathnode.transform.position = new Vector3(pathnode.transform.position.x, pathnode.transform.position.y, newZ);
pathnode.transformSubmodule.originalPosition = pathnode.transform.localPosition;
pathnode.transformSubmodule.Refresh();
pathnode.Refresh();
}
foreach (var i in track.childElementList.OfType<Track>())
{
inspector.connectedGameElement = i;
AdjustPathnodeZ(OriginZpoint, scale);
}
}
/// <summary>
/// 将 Hold Note 拆分为具有路径节点的 Track
/// </summary>
public static void SplitHoldToTrack(int PathnodesCount)
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Hold))
{
LogWindow.Log("Please select a Hold first!");
return;
}
Hold hold = (Hold)inspector.connectedGameElement;
Track parentTrack = hold.parentElement as Track;
if (parentTrack == null || parentTrack.trackTimeSubmodule is not TrackTimeSubmoduleMovable)
{
LogWindow.Log("Track Illegal (Only Movable)", Color.red);
return;
}
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = hold.track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
if (PathnodesCount < 2)
{
LogWindow.Log("PathnodesCount must be greater than 1!", Color.red);
return;
}
float startTime = hold.exactJudgeTime;
float endTime = hold.holdEndTime;
float interval = 1f / (PathnodesCount - 1);
hold.UpdateNoteInMovableTrack();
Vector3 HoldStartPos = default;
Vector3 HoldEndPos = default;
if (hold.noteVisual is DTMNoteVisualHold dTMNoteVisualHold)
{
dTMNoteVisualHold.headPoint.SetPercent(trackTimeSubmoduleMovable.GetTrackPercent(hold.exactJudgeTime));
dTMNoteVisualHold.tailPoint.SetPercent(trackTimeSubmoduleMovable.GetTrackPercent(hold.holdEndTime));
HoldStartPos = dTMNoteVisualHold.headPoint.transform.position;
HoldEndPos = dTMNoteVisualHold.tailPoint.transform.position;
}
else
{
LogWindow.Log("The selected Hold's NoteVisual is not DTMNoteVisualHold!", Color.red);
return;
}
if (hold.track.trackPathSubmodule.pathNodeList.Count > 2)
{
LogWindow.Log("the Hold may not be split currently", Color.yellow);
return;
}
hold.UpdateNoteInMovableTrack();
Track NewTrack = Track.GenerateElement(hold.elementName + "_SplitTrack", Guid.NewGuid(), new List<string>(), true, parentTrack);
new TrackTimeSubmoduleMovable(NewTrack, startTime, endTime, 1, AnimationCurveType.Linear);
for (int i = 0; i < PathnodesCount; i++)
{
PathNode j = PathNode.GenerateElement("PathNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, NewTrack, true);
j.transform.position = Vector3.Lerp(HoldStartPos, HoldEndPos, i * interval);
j.transformSubmodule.originalPosition = j.transform.localPosition;
}
EditorManager.instance.operationManager.CopyPasteDeleteModule.CopyElement(hold);
EditorManager.instance.operationManager.CopyPasteDeleteModule.PasteElement(NewTrack);
EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(hold);
Hold newHold = NewTrack.childElementList.OfType<Hold>().First();
newHold.noteVisual.transformSubmodule.originalPosition = Vector3.zero;
NewTrack.Refresh();
Observable.Timer(TimeSpan.FromSeconds(0.3f)).Subscribe(_ =>
{
NewTrack?.trackPathSubmodule.path.RebuildImmediate(true, true);
DTMNoteVisualHold dTMNoteVisualHold = newHold.noteVisual as DTMNoteVisualHold;
dTMNoteVisualHold.meshGenerator.Rebuild();
});
}
/// <summary>
/// 将选中轨道下所有 Hold Note 拆分为具有路径节点的 Track
/// </summary>
public static void SplitAllHoldToTrack(int PathnodesCount)
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
{
LogWindow.Log("Please select a Track first!");
return;
}
Track track = (Track)inspector.connectedGameElement;
var holds = track.childElementList.OfType<Hold>().ToList();
if (track.trackPathSubmodule.pathNodeList.Count > 2)
{
LogWindow.Log("the Hold may not be split currently", Color.yellow);
return;
}
foreach (var hold in holds)
{
inspector.connectedGameElement = hold;
SplitHoldToTrack(PathnodesCount);
}
}
#endregion
#region Note Import/Export (/)
/// <summary>
/// 从正则格式文本导入音符数据
/// </summary>
public static void SamplerImport(string inputData) public static void SamplerImport(string inputData)
{ {
if (!EditorManager.instance.useNotePrefab) if (!EditorManager.instance.useNotePrefab)
@@ -316,6 +549,61 @@ namespace Ichni.Editor
} }
Debug.Log("===== ====="); Debug.Log("===== =====");
} }
/// <summary>
/// 导出选中轨道下所有音符为正则格式文本(复制到剪贴板)
/// </summary>
public static void ExportNotesFromTrack()
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
{
LogWindow.Log("Please select a Track first!");
return;
}
Track track = (Track)inspector.connectedGameElement;
var notes = track.childElementList.OfType<NoteBase>().OrderBy(n => n.exactJudgeTime).ToList();
List<string> lines = new List<string>();
foreach (var note in notes)
{
string type = note switch
{
Tap => "Tap",
Stay => "Stay",
Hold => "Hold",
Flick => "Flick",
_ => "Unknown"
};
string id = track.elementName;
float time = note.exactJudgeTime;
float x = 0f;
// 获取X值
if (note.noteVisual.submoduleList.FirstOrDefault(i => i is TransformSubmodule) is TransformSubmodule ts)
{
x = ts.originalPosition.x;
}
if (note is Hold hold)
{
float duration = hold.holdEndTime - hold.exactJudgeTime;
lines.Add($"({type}, {id}, {time:0.###}, {x:0.###}, {duration:0.###})");
}
else
{
lines.Add($"({type}, {id}, {time:0.###}, {x:0.###})");
}
}
string result = string.Join("\n", lines);
Debug.Log(result);
//LogWindow.Log(result, Color.green);
// 复制到剪贴板
GUIUtility.systemCopyBuffer = result;
LogWindow.Log("Colped Done!", Color.green);
}
#endregion
#region Highlighting/Visuals (/)
/// <summary>
/// 在游戏内设置时间相同的音符高亮显示
/// </summary>
public static void SetNoteHLInGame(bool forceSetOff = false, bool SameTheme = false) public static void SetNoteHLInGame(bool forceSetOff = false, bool SameTheme = false)
{ {
var noteBases = EditorManager.instance.beatmapContainer.gameElementList.OfType<NoteBase>().ToList(); var noteBases = EditorManager.instance.beatmapContainer.gameElementList.OfType<NoteBase>().ToList();
@@ -369,6 +657,9 @@ namespace Ichni.Editor
} }
} }
/// <summary>
/// 在选中元素下设置时间相同的音符高亮显示
/// </summary>
public static void SetNoteHLInElement(bool forceSetOff = false, bool SameTheme = false) public static void SetNoteHLInElement(bool forceSetOff = false, bool SameTheme = false)
{ {
var noteBases = inspector.connectedGameElement.GetAllGameElementsFromThis().OfType<NoteBase>().ToList(); var noteBases = inspector.connectedGameElement.GetAllGameElementsFromThis().OfType<NoteBase>().ToList();
@@ -422,6 +713,12 @@ namespace Ichni.Editor
} }
} }
} }
#endregion
#region Animation Swaps ()
/// <summary>
/// 交换 Displacement 动画值的正负号
/// </summary>
public static void swapDisplacement() public static void swapDisplacement()
{ {
Displacement displacement = inspector.connectedGameElement as Displacement; Displacement displacement = inspector.connectedGameElement as Displacement;
@@ -446,6 +743,10 @@ namespace Ichni.Editor
anim.startValue = -anim.startValue; anim.startValue = -anim.startValue;
} }
} }
/// <summary>
/// 交换 Swirl 动画值的正负号
/// </summary>
public static void swapSwirl() public static void swapSwirl()
{ {
Swirl swirl = inspector.connectedGameElement as Swirl; Swirl swirl = inspector.connectedGameElement as Swirl;
@@ -470,6 +771,10 @@ namespace Ichni.Editor
anim.startValue = -anim.startValue; anim.startValue = -anim.startValue;
} }
} }
/// <summary>
/// 交换 Scale 动画值的正负号
/// </summary>
public static void swapScale() public static void swapScale()
{ {
Scale scale = inspector.connectedGameElement as Scale; Scale scale = inspector.connectedGameElement as Scale;
@@ -494,147 +799,12 @@ namespace Ichni.Editor
anim.startValue = -anim.startValue; anim.startValue = -anim.startValue;
} }
} }
public static void AttachNoteInNearestTrail() #endregion
{
Track track = inspector.connectedGameElement as Track;
if (track == null)
{
LogWindow.Log("Please select a Track first!", Color.red);
return;
}
List<NoteBase> noteBases = track.childElementList.OfType<NoteBase>().ToList();
List<IHaveTrail> trails = track.GetAllGameElementsFromThis().OfType<IHaveTrail>().ToList();
if (trails.Count == 0)
{
LogWindow.Log("The Track has no Trail!", Color.red);
return;
}
foreach (var note in noteBases)
{
IHaveTrail nearestTrail = null;
Vector3 FinalPos = Vector3.positiveInfinity;
foreach (var trail in trails)
{
if (trail is IHaveTransformSubmodule haveTransform && trail is GameElement gameElement)
{
Vector3 pos = haveTransform.transformSubmodule.originalPosition;
GameElement gameElement1 = gameElement;
while (gameElement1 != track)
{
if (gameElement1 is not IHaveTransformSubmodule)
{
gameElement1 = gameElement1.parentElement;
continue;
}
List<Displacement> animationBases = gameElement1.childElementList.OfType<Displacement>().ToList();
foreach (var displacement in animationBases) #region Global Utilities ()
{ /// <summary>
pos += displacement.getValue(note.exactJudgeTime); /// 确保所有动画的起始时间为 0 时有关键帧
} /// </summary>
gameElement1 = gameElement1.parentElement;
}
if (Vector3.Distance(pos, (note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition) <=
Vector3.Distance(FinalPos, (note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition))
{
nearestTrail = trail;
FinalPos = pos;
}
}
}
if (nearestTrail != null)
{
(note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).originalPosition = FinalPos;
note.Refresh();
(note.noteVisual.submoduleList.First(i => i is TransformSubmodule) as TransformSubmodule).Refresh();//捏妈妈滴为什么notevisual的TransformSubmodule不刷新
}
}
}
// 导出Track下所有Note为正则格式文本
public static void ExportNotesFromTrack()
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
{
LogWindow.Log("Please select a Track first!");
return;
}
Track track = (Track)inspector.connectedGameElement;
var notes = track.childElementList.OfType<NoteBase>().OrderBy(n => n.exactJudgeTime).ToList();
List<string> lines = new List<string>();
foreach (var note in notes)
{
string type = note switch
{
Tap => "Tap",
Stay => "Stay",
Hold => "Hold",
Flick => "Flick",
_ => "Unknown"
};
string id = track.elementName;
float time = note.exactJudgeTime;
float x = 0f;
// 获取X值
if (note.noteVisual.submoduleList.FirstOrDefault(i => i is TransformSubmodule) is TransformSubmodule ts)
{
x = ts.originalPosition.x;
}
if (note is Hold hold)
{
float duration = hold.holdEndTime - hold.exactJudgeTime;
lines.Add($"({type}, {id}, {time:0.###}, {x:0.###}, {duration:0.###})");
}
else
{
lines.Add($"({type}, {id}, {time:0.###}, {x:0.###})");
}
}
string result = string.Join("\n", lines);
Debug.Log(result);
//LogWindow.Log(result, Color.green);
// 复制到剪贴板
GUIUtility.systemCopyBuffer = result;
LogWindow.Log("Colped Done!", Color.green);
}
public static void AdjustPathnodeZ(float OriginZpoint, float scale)
{
if (inspector.connectedGameElement == null)
{
LogWindow.Log($"please select a element (folder or track)", Color.red);
return;
}
if (inspector.connectedGameElement.GetType() != typeof(Track))
{
foreach (var i in inspector.connectedGameElement.childElementList.OfType<Track>())
{
inspector.connectedGameElement = i;
AdjustPathnodeZ(OriginZpoint, scale);
}
return;
}
Track track = (Track)inspector.connectedGameElement;
var pathnodes = track.trackPathSubmodule.pathNodeList;
foreach (var pathnode in pathnodes)
{
if (pathnode.childElementList.OfType<Displacement>().Count() > 0)
{
LogWindow.Log($"PathNode {pathnode.elementName} has Displacement, which may cause issues", Color.yellow);
}
float worldZ = pathnode.transform.position.z;
float deltaZ = worldZ - OriginZpoint;
float newZ = OriginZpoint + deltaZ * scale;
pathnode.transform.position = new Vector3(pathnode.transform.position.x, pathnode.transform.position.y, newZ);
pathnode.transformSubmodule.originalPosition = pathnode.transform.localPosition;
pathnode.transformSubmodule.Refresh();
pathnode.Refresh();
}
foreach (var i in track.childElementList.OfType<Track>())
{
inspector.connectedGameElement = i;
AdjustPathnodeZ(OriginZpoint, scale);
}
}
public static void FloorAnim() public static void FloorAnim()
{ {
if (inspector.connectedGameElement == null) if (inspector.connectedGameElement == null)
@@ -681,97 +851,10 @@ namespace Ichni.Editor
} }
} }
} }
public static void SplitHoldToTrack(int PathnodesCount)
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Hold))
{
LogWindow.Log("Please select a Hold first!");
return;
}
Hold hold = (Hold)inspector.connectedGameElement;
Track parentTrack = hold.parentElement as Track;
if (parentTrack == null || parentTrack.trackTimeSubmodule is not TrackTimeSubmoduleMovable)
{
LogWindow.Log("Track Illegal (Only Movable)", Color.red);
return;
}
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = hold.track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
if (PathnodesCount < 2)
{
LogWindow.Log("PathnodesCount must be greater than 1!", Color.red);
return;
}
float startTime = hold.exactJudgeTime;
float endTime = hold.holdEndTime;
float interval = 1f / (PathnodesCount - 1);
hold.UpdateNoteInMovableTrack();
Vector3 HoldStartPos = default;
Vector3 HoldEndPos = default;
if (hold.noteVisual is DTMNoteVisualHold dTMNoteVisualHold)
{
dTMNoteVisualHold.headPoint.SetPercent(trackTimeSubmoduleMovable.GetTrackPercent(hold.exactJudgeTime));
dTMNoteVisualHold.tailPoint.SetPercent(trackTimeSubmoduleMovable.GetTrackPercent(hold.holdEndTime));
HoldStartPos = dTMNoteVisualHold.headPoint.transform.position;
HoldEndPos = dTMNoteVisualHold.tailPoint.transform.position;
}
else
{
LogWindow.Log("The selected Hold's NoteVisual is not DTMNoteVisualHold!", Color.red);
return;
}
if (hold.track.trackPathSubmodule.pathNodeList.Count > 2)
{
LogWindow.Log("the Hold may not be split currently", Color.yellow);
return;
}
hold.UpdateNoteInMovableTrack();
Track NewTrack = Track.GenerateElement(hold.elementName + "_SplitTrack", Guid.NewGuid(), new List<string>(), true, parentTrack);
new TrackTimeSubmoduleMovable(NewTrack, startTime, endTime, 1, AnimationCurveType.Linear);
for (int i = 0; i < PathnodesCount; i++)
{
PathNode j = PathNode.GenerateElement("PathNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, NewTrack, true);
j.transform.position = Vector3.Lerp(HoldStartPos, HoldEndPos, i * interval);
j.transformSubmodule.originalPosition = j.transform.localPosition;
}
EditorManager.instance.operationManager.CopyPasteDeleteModule.CopyElement(hold);
EditorManager.instance.operationManager.CopyPasteDeleteModule.PasteElement(NewTrack);
EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(hold);
Hold newHold = NewTrack.childElementList.OfType<Hold>().First();
newHold.noteVisual.transformSubmodule.originalPosition = Vector3.zero;
NewTrack.Refresh();
Observable.Timer(TimeSpan.FromSeconds(0.3f)).Subscribe(_ =>
{
NewTrack?.trackPathSubmodule.path.RebuildImmediate(true, true);
DTMNoteVisualHold dTMNoteVisualHold = newHold.noteVisual as DTMNoteVisualHold;
dTMNoteVisualHold.meshGenerator.Rebuild();
});
}
public static void SplitAllHoldToTrack(int PathnodesCount)
{
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
{
LogWindow.Log("Please select a Track first!");
return;
}
Track track = (Track)inspector.connectedGameElement;
var holds = track.childElementList.OfType<Hold>().ToList();
if (track.trackPathSubmodule.pathNodeList.Count > 2)
{
LogWindow.Log("the Hold may not be split currently", Color.yellow);
return;
}
foreach (var hold in holds)
{
inspector.connectedGameElement = hold;
SplitHoldToTrack(PathnodesCount);
}
}
/// <summary>
/// 全局刷新所有元素和轨道路径
/// </summary>
public static void Rebuild() public static void Rebuild()
{ {
foreach (GameElement element in EditorManager.instance.beatmapContainer.gameElementList) foreach (GameElement element in EditorManager.instance.beatmapContainer.gameElementList)
@@ -789,6 +872,10 @@ namespace Ichni.Editor
UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
#endif #endif
} }
/// <summary>
/// 添加 Tag Matcher 到 TagManager
/// </summary>
public static void AddTagMatcher(string name, string parameterName) public static void AddTagMatcher(string name, string parameterName)
{ {
@@ -796,102 +883,67 @@ namespace Ichni.Editor
IBaseElement element = inspector.connectedGameElement; IBaseElement element = inspector.connectedGameElement;
tagManager.AddTagMatcher(name, element.GetType(), parameterName); tagManager.AddTagMatcher(name, element.GetType(), parameterName);
} }
public static void FindParameterName(float value)
/// <summary>
/// 查找元素中匹配给定值的参数名称
/// </summary>
public static void FindParameterName(object value)
{ {
// 假设 inspector.connectedGameElement 存在且是你希望搜索的对象
var element = inspector.connectedGameElement; var element = inspector.connectedGameElement;
foreach (var i in element.GetType().GetFields()) if (element == null || value == null) return;
string o = FindParameterName(element, value);
if (!string.IsNullOrEmpty(o)) LogWindow.Log(o);
foreach (var i in element.GetType().GetProperties(DeepMatchFlags))
{ {
if (i.FieldType == typeof(float) && (float)i.GetValue(element) == value)//获取对应变量的值) if (i == null) continue;
{ var propertyInfo = element.GetType().GetProperty(i.Name);
Debug.Log($"Found parameter: {i.Name}"); if (propertyInfo == null) continue;
LogWindow.Log($"Found parameter: {i.Name}", Color.green); var propertyValue = propertyInfo.GetValue(element);
} var p = FindParameterName(propertyValue as IBaseElement, value);
if (!string.IsNullOrEmpty(p))
LogWindow.Log($"{i.Name}.{p}");
} }
} }
public static void FindParameterName(Vector3 value) public static string FindParameterName(IBaseElement element, object value)
{ {
var element = inspector.connectedGameElement; // 假设 inspector.connectedGameElement 存在且是你希望搜索的对象
foreach (var field in element.GetType().GetFields())
if (element == null || value == null) return "";
// 1. 获取目标类型
Type targetType = value.GetType();
// 如果是 Nullable<T>,获取其基础类型
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
{ {
if (field.FieldType == typeof(Vector3)) targetType = Nullable.GetUnderlyingType(targetType);
}
// 2. 遍历 GameElement 的所有字段
foreach (var field in element.GetType().GetFields(DeepMatchFlags))
{
// 检查字段类型是否匹配
if (field.FieldType == targetType)
{ {
Vector3 fieldValue = (Vector3)field.GetValue(element); // 获取字段的值 (作为 object)
if (Vector3.Distance(fieldValue, value) < 0.001f) // 使用容差比较Vector3 object fieldValue = field.GetValue(element);
if (IsValueMatch(fieldValue, value, field.FieldType))
{ {
Debug.Log($"Found Vector3 parameter: {field.Name}"); Debug.Log($"Found parameter: {field.Name} (Type: {targetType.Name})");
LogWindow.Log($"Found Vector3 parameter: {field.Name}", Color.green); // 假设 LogWindow 可用
return field.Name;
} }
} }
} }
return "";
} }
public static void FindParameterName(Vector2 value) /// <summary>
{ /// 同步标签元素
var element = inspector.connectedGameElement; /// </summary>
foreach (var field in element.GetType().GetFields())
{
if (field.FieldType == typeof(Vector2))
{
Vector2 fieldValue = (Vector2)field.GetValue(element);
if (Vector2.Distance(fieldValue, value) < 0.001f) // 使用容差比较Vector2
{
Debug.Log($"Found Vector2 parameter: {field.Name}");
LogWindow.Log($"Found Vector2 parameter: {field.Name}", Color.green);
}
}
}
}
public static void FindParameterName(Color value)
{
var element = inspector.connectedGameElement;
foreach (var field in element.GetType().GetFields())
{
if (field.FieldType == typeof(Color))
{
Color fieldValue = (Color)field.GetValue(element);
if (fieldValue == value) // Color可以直接比较
{
Debug.Log($"Found Color parameter: {field.Name}");
LogWindow.Log($"Found Color parameter: {field.Name}", Color.green);
}
}
}
}
public static void FindParameterName(int value)
{
var element = inspector.connectedGameElement;
foreach (var field in element.GetType().GetFields())
{
if (field.FieldType == typeof(int))
{
int fieldValue = (int)field.GetValue(element);
if (fieldValue == value) // int可以直接比较
{
Debug.Log($"Found int parameter: {field.Name}");
LogWindow.Log($"Found int parameter: {field.Name}", Color.green);
}
}
}
}
public static void FindParameterName(string value)
{
var element = inspector.connectedGameElement;
foreach (var field in element.GetType().GetFields())
{
if (field.FieldType == typeof(string))
{
string fieldValue = (string)field.GetValue(element);
if (fieldValue == value) // string可以直接比较
{
Debug.Log($"Found string parameter: {field.Name}");
LogWindow.Log($"Found string parameter: {field.Name}", Color.green);
}
}
}
}
public static void SyncTagedElement() public static void SyncTagedElement()
{ {
var q = inspector.connectedGameElement; var q = inspector.connectedGameElement;
@@ -899,5 +951,98 @@ namespace Ichni.Editor
var tagManager = EditorManager.instance.projectInformation.tagManager; var tagManager = EditorManager.instance.projectInformation.tagManager;
tagManager.SyncTagedElement((q)); tagManager.SyncTagedElement((q));
} }
#endregion
#region Internal Helpers ()
private const BindingFlags DeepMatchFlags = BindingFlags.Instance | BindingFlags.Public;
private const float FloatEpsilon = 0.0001f; // 定义浮点数容差
/// <summary>
/// 比较两个值是否匹配,对浮点数使用容差比较
/// </summary>
private static bool IsValueMatch(object fieldVal, object targetVal, Type t)
{
if (fieldVal == null || targetVal == null)
{
return fieldVal == targetVal;
}
// 1. 类型是 float
if (t == typeof(float))
{
// 必须进行类型转换
float f1 = (float)fieldVal;
float f2 = (float)targetVal;
return Mathf.Abs(f1 - f2) < FloatEpsilon;
}
// 2. 类型是 Vector3
if (t == typeof(Vector3))
{
Vector3 v1 = (Vector3)fieldVal;
Vector3 v2 = (Vector3)targetVal;
// 使用 Unity 的 Distance 容差比较
return Vector3.Distance(v1, v2) < FloatEpsilon;
}
// 3. 类型是 Color
if (t == typeof(Color))
{
Color c1 = (Color)fieldVal;
Color c2 = (Color)targetVal;
// 手动解构 Color 的四个 float 分量,使用容差
return Mathf.Abs(c1.r - c2.r) < FloatEpsilon &&
Mathf.Abs(c1.g - c2.g) < FloatEpsilon &&
Mathf.Abs(c1.b - c2.b) < FloatEpsilon &&
Mathf.Abs(c1.a - c2.a) < FloatEpsilon;
}
// 4. 其他包含 float 的复杂 Struct/Class 的浅层解构
if (!t.IsPrimitive && t != typeof(string) && (t.IsClass || t.IsValueType))
{
// 如果字段值是复杂类型,并且我们想比较它的内部 float 字段 (浅层)
// 这里只能进行浅层比较,因为深层递归需要辅助函数来管理栈。
// 遍历所有顶层字段,检查是否有 float
foreach (var field in t.GetFields(DeepMatchFlags))
{
object fieldValMember = field.GetValue(fieldVal);
object targetValMember = field.GetValue(targetVal);
if (field.FieldType == typeof(float))
{
// 对 float 成员进行容差比较
if (fieldValMember != null && targetValMember != null)
{
float f1 = (float)fieldValMember;
float f2 = (float)targetValMember;
if (Mathf.Abs(f1 - f2) >= FloatEpsilon)
{
return false; // 找到不匹配的 float
}
}
else if (fieldValMember != targetValMember) // 检查是否一个为 null另一个不为 null
{
return false;
}
}
else
{
// 对其他类型使用默认 Equals
if (!fieldValMember.Equals(targetValMember))
{
return false;
}
}
}
// 所有字段都匹配
return true;
}
// 5. 默认路径对于所有其他类型int, string, bool, etc.),使用默认的 Equals 比较
return fieldVal.Equals(targetVal);
}
#endregion
} }
} }

View File

@@ -113,21 +113,19 @@ namespace Ichni.RhythmGame
} }
namespace Ichni.Editor namespace Ichni.Editor
{ {
public class TagManager : IBaseElement//这玩意大概不需要分BM的 public class TagManager : IBaseElement
{ {
// ... (你的原有代码: matchedBM, 构造函数等保持不变) ...
public BaseElement_BM matchedBM { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public BaseElement_BM matchedBM { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public List<TagMatcher> tagMatchers; public List<TagMatcher> tagMatchers;
public TagManager() public TagManager()
{ {
tagMatchers = new List<TagMatcher>(); tagMatchers = new List<TagMatcher>();
tempTagMatcherName = ""; // ...
tempElementTypeName = "";
tempParameterName = "";
} }
// ... (Add/Remove 方法保持不变) ...
public void AddTagMatcher(string name, Type elementType, string parameterName) public void AddTagMatcher(string name, Type elementType, string parameterName)
{ {
//check //check
@@ -161,51 +159,53 @@ namespace Ichni.Editor
{ {
RemoveTagMatcher(tagMatchers.First(i => i.name == o)); RemoveTagMatcher(tagMatchers.First(i => i.name == o));
} }
// ... 其他 Add/Remove ...
public List<IBaseElement> GetMachedElements(TagMatcher o) public List<IBaseElement> GetMachedElements(TagMatcher o)
{ {
return EditorManager.instance.beatmapContainer.gameElementList return EditorManager.instance.beatmapContainer.gameElementList
.Where(p => o.Match(p)).Cast<IBaseElement>().ToList(); .Where(p => o.Match(p)).Cast<IBaseElement>().ToList();
} }
public List<TagMatcher> GetMatcher(GameElement baseElement) public List<TagMatcher> GetMatcher(GameElement baseElement)
{ {
return tagMatchers.Where(p => p.Match(baseElement)).ToList(); return tagMatchers.Where(p => p.Match(baseElement)).ToList();
} }
// --- 修改 1: 使用 ReflectionHelper 设置值 ---
public void SetMatchedElements(TagMatcher o, object value) public void SetMatchedElements(TagMatcher o, object value)
{ {
foreach (var i in GetMachedElements(o)) foreach (var i in GetMachedElements(o))
{ {
// 直接调用修改后的 SetValue
o.SetValue(i, value); o.SetValue(i, value);
} }
} }
// --- 修改 2: 使用 ReflectionHelper 同步值 ---
public void SyncTagedElement(GameElement gameElement) public void SyncTagedElement(GameElement gameElement)
{ {
foreach (var matcher in GetMatcher(gameElement)) foreach (var matcher in GetMatcher(gameElement))
{ {
var matchedElements = GetMachedElements(matcher); var matchedElements = GetMachedElements(matcher);
// A. 获取源值 (使用 ReflectionHelper 以支持嵌套路径,如 "transform.position")
var value = ReflectionHelper.GetDeepValue(gameElement, matcher.parameterName);
foreach (var element in matchedElements) foreach (var element in matchedElements)
{ {
var value = gameElement.GetType().GetField(matcher.parameterName).GetValue(gameElement); // B. 设置目标值 (TagMatcher 内部现在使用 ReflectionHelper)
matcher.SetValue(element, value); matcher.SetValue(element, value);
element.Refresh(); element.Refresh();
} }
} }
} }
internal void SetUpInspector()
public string tempTagMatcherName = "";
public string tempElementTypeName = "";
public string tempParameterName = "";
public void SetUpInspector()
{ {
tempTagMatcherName = ""; // tempTagMatcherName = "";
tempElementTypeName = ""; // tempElementTypeName = "";
tempParameterName = ""; // tempParameterName = "";
IHaveInspection inspector = EditorManager.instance.uiManager.inspector; IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector; Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Tag Manager"); var container = inspector.GenerateContainer("Tag Manager");
@@ -217,7 +217,11 @@ namespace Ichni.Editor
var sub = container.GenerateSubcontainer(2); var sub = container.GenerateSubcontainer(2);
inspector.GenerateHintText(this, sub, $"Name: {matcher.name}"); inspector.GenerateHintText(this, sub, $"Name: {matcher.name}");
inspector.GenerateHintText(this, sub, $"Type: {matcher.ElementType?.Name ?? "<null>"}"); inspector.GenerateHintText(this, sub, $"Type: {matcher.ElementType?.Name ?? "<null>"}");
inspector.GenerateHintText(this, sub, $"Param: {matcher.parameterName}"); var e = inspector.GenerateInputField(sub, "Parameter", matcher.parameterName);
e.AddListenerFunction(() =>
{
matcher.parameterName = e.inputField.text;
});
inspector.GenerateButton(this, sub, "Remove", () => inspector.GenerateButton(this, sub, "Remove", () =>
{ {
RemoveTagMatcher(matcher); RemoveTagMatcher(matcher);
@@ -225,86 +229,96 @@ namespace Ichni.Editor
}); });
} }
// 新增TagMatcher区域 // // 新增TagMatcher区域
var addSub = container.GenerateSubcontainer(3); // var addSub = container.GenerateSubcontainer(3);
// 输入Tag名称 // // 输入Tag名称
var nameInput = inspector.GenerateInputField(this, addSub, "Tag Name", nameof(tempTagMatcherName)); // var nameInput = inspector.GenerateInputField(this, addSub, "Tag Name", nameof(tempTagMatcherName));
// 下拉选择类型 // // 下拉选择类型
List<Type> typeList = TypeHelper.GetInheritedTypes<GameElement>(); // List<Type> typeList = TypeHelper.GetInheritedTypes<GameElement>();
List<string> typeNames = typeList.ConvertAll(t => t.FullName); // List<string> typeNames = typeList.ConvertAll(t => t.FullName);
var typeDropdown = inspector.GenerateDropdown(this, addSub, "Element Type", typeNames, nameof(tempElementTypeName)) // var typeDropdown = inspector.GenerateDropdown(this, addSub, "Element Type", typeNames, nameof(tempElementTypeName))
.AddListenerFunction(() => // .AddListenerFunction(() =>
{ // {
// 选择类型后刷新参数下拉 // // 选择类型后刷新参数下拉
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName); // Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
List<string> paramNames = selectedType != null // List<string> paramNames = selectedType != null
? selectedType.GetFields().Select(f => f.Name).ToList() // ? selectedType.GetFields().Select(f => f.Name).ToList()
: new List<string>(); // : new List<string>();
//inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName)); // //inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
}); // });
// 参数下拉(初始为空,随类型变化刷新) // 参数下拉(初始为空,随类型变化刷新)
if (!string.IsNullOrEmpty(tempElementTypeName)) // if (!string.IsNullOrEmpty(tempElementTypeName))
{ // {
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName); // Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
List<string> paramNames = selectedType != null // List<string> paramNames = selectedType != null
? selectedType.GetFields().Select(f => f.Name).ToList() // ? selectedType.GetFields().Select(f => f.Name).ToList()
: new List<string>(); // : new List<string>();
inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName)); // inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
} // }
else // else
{ // {
inspector.GenerateDropdown(this, addSub, "Parameter", new List<string>(), nameof(tempParameterName)); // inspector.GenerateDropdown(this, addSub, "Parameter", new List<string>(), nameof(tempParameterName));
} // }
// 添加按钮 // // 添加按钮
var addButton = inspector.GenerateButton(this, addSub, "Add TagMatcher", () => // var addButton = inspector.GenerateButton(this, addSub, "Add TagMatcher", () =>
{ // {
if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName)) // if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
{ // {
Debug.LogWarning("请填写完整信息再添加TagMatcher。"); // Debug.LogWarning("请填写完整信息再添加TagMatcher。");
return; // return;
} // }
if (tagMatchers.Any(t => t.name == tempTagMatcherName)) // if (tagMatchers.Any(t => t.name == tempTagMatcherName))
{ // {
Debug.LogWarning("TagMatcher's name is repeated!"); // Debug.LogWarning("TagMatcher's name is repeated!");
return; // return;
} // }
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName); // Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
TagMatcher matcher = new TagMatcher // TagMatcher matcher = new TagMatcher
{ // {
name = tempTagMatcherName, // name = tempTagMatcherName,
ElementType = selectedType, // ElementType = selectedType,
parameterName = tempParameterName // parameterName = tempParameterName
}; // };
AddTagMatcher(matcher); // AddTagMatcher(matcher);
inspectorMain.SetInspector(EditorManager.instance.projectInformation); // inspectorMain.SetInspector(EditorManager.instance.projectInformation);
}); // });
// 按需禁用添加按钮 // // 按需禁用添加按钮
if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName)) // if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
{ // {
addButton.button.interactable = false; // addButton.button.interactable = false;
} // }
} }
// ... (Inspector 变量保持不变) ...
public struct TagMatcher public struct TagMatcher
{ {
public string name; public string name;
public Type ElementType; public Type ElementType;
public string parameterName; public string parameterName; // 现在可以填 "transform.position.x" 这种路径了
public readonly bool Match(GameElement gameElement) public readonly bool Match(GameElement gameElement)
{ {
string o = name; string o = name;
return gameElement.tags.Any(i => i == o); // 注意:这里建议加空检查,防止 gameElement.tags 为 null
return gameElement.tags != null && gameElement.tags.Any(i => i == o);
} }
// --- 修改 3: TagMatcher 内部逻辑更新 ---
public readonly void SetValue(IBaseElement baseElement, object value) public readonly void SetValue(IBaseElement baseElement, object value)
{ {
if (ElementType != baseElement.GetType()) return; // 原有逻辑:严格检查类型
ElementType.GetField(parameterName).SetValue(baseElement, value); // if (ElementType != baseElement.GetType()) return;
// 新逻辑建议:
// 1. 既然是用 Tag 匹配,不同类可能有相同的字段名 (鸭子类型),去掉严格类型检查可能更灵活。
// 2. 如果必须检查,保留上面那行。
// 使用 ReflectionHelper 处理赋值 (自动处理 Struct 回写和嵌套)
ReflectionHelper.SetDeepValue(baseElement, parameterName, value);
} }
}; };
} }

View File

@@ -83,6 +83,13 @@ namespace Ichni.RhythmGame
new List<string>(), true, this, 1000f)); new List<string>(), true, this, 1000f));
} }
public override void OnDelete()
{
if (cameraManager.gameCamera == this)
{
cameraManager.SwitchCamera();
}
}
} }
public partial class GameCamera public partial class GameCamera

View File

@@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
public static class ReflectionHelper
{
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
// --- 设置值 (支持 object) ---
public static void SetDeepValue(object target, string path, object newValue)
{
if (target == null || string.IsNullOrEmpty(path)) return;
string[] parts = path.Split('.');
SetDeepValueRecursive(target, parts, 0, newValue);
}
private static void SetDeepValueRecursive(object currentObj, string[] pathParts, int index, object newValue)
{
string memberName = pathParts[index];
Type type = currentObj.GetType();
FieldInfo field = type.GetField(memberName, Flags);
PropertyInfo prop = type.GetProperty(memberName, Flags);
if (field == null && prop == null)
{
// Debug.LogWarning($"找不到成员: {memberName}"); // 可选:调试用
return;
}
bool isLast = index == pathParts.Length - 1;
if (isLast)
{
// 到达终点:直接设置值
// 注意:这里可能需要处理类型转换,取决于你的 newValue 类型是否严格匹配
try
{
if (field != null) field.SetValue(currentObj, newValue);
else if (prop != null && prop.CanWrite) prop.SetValue(currentObj, newValue);
}
catch (Exception e) { Debug.LogError($"设置值失败 {memberName}: {e.Message}"); }
}
else
{
// 中间节点
object nextObj = field != null ? field.GetValue(currentObj) : prop.GetValue(currentObj);
if (nextObj == null) return;
SetDeepValueRecursive(nextObj, pathParts, index + 1, newValue);
// Struct 回写逻辑 (关键)
if (nextObj.GetType().IsValueType)
{
if (field != null) field.SetValue(currentObj, nextObj);
else if (prop != null && prop.CanWrite) prop.SetValue(currentObj, nextObj);
}
}
}
// --- 获取值 (支持 object) ---
public static object GetDeepValue(object target, string path)
{
object current = target;
foreach (string part in path.Split('.'))
{
if (current == null) return null;
Type type = current.GetType();
FieldInfo field = type.GetField(part, Flags);
if (field != null)
{
current = field.GetValue(current);
continue;
}
PropertyInfo prop = type.GetProperty(part, Flags);
if (prop != null)
{
current = prop.GetValue(current);
continue;
}
return null; // 路径中断
}
return current;
}
/// <summary>
/// 遍历对象的所有字段和属性(递归地),查找值与目标值匹配的参数路径。
/// </summary>
/// <param name="target">要搜索的对象实例。</param>
/// <param name="targetValue">要匹配的目标值。</param>
/// <param name="maxDepth">递归搜索的最大深度,防止无限循环。</param>
/// <returns>返回匹配参数的完整路径列表 (例如: "position.x")。</returns>
public static List<string> FindParametersByValue(object target, object targetValue, int maxDepth = 10)
{
if (target == null || targetValue == null) return new List<string>();
// 用于存储找到的路径
var results = new List<string>();
// 用于防止循环引用(比如类 A 内部引用了类 B类 B 内部又引用了类 A
var visited = new HashSet<object>();
// 启动递归搜索
FindRecursive(target, targetValue, "", 0, results, visited, maxDepth);
return results;
}
private static void FindRecursive(
object currentObject,
object targetValue,
string currentPath,
int depth,
List<string> results,
HashSet<object> visited,
int maxDepth)
{
if (currentObject == null || depth >= maxDepth) return;
// 避免无限循环和重复搜索
// 对于值类型 (Struct) 不需要加入 visited因为它们是副本
if (!currentObject.GetType().IsValueType)
{
// 如果对象已经被搜索过,则跳过
if (visited.Contains(currentObject)) return;
visited.Add(currentObject);
}
Type currentType = currentObject.GetType();
// 1. 遍历 Field 字段
foreach (var field in currentType.GetFields(Flags))
{
// 跳过内部字段,如编译器生成的 backing fields
if (field.IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false)) continue;
object value = field.GetValue(currentObject);
string newPath = string.IsNullOrEmpty(currentPath) ? field.Name : $"{currentPath}.{field.Name}";
CheckAndRecurse(field.FieldType, value, targetValue, newPath, depth, results, visited, maxDepth);
}
// 2. 遍历 Property 属性
foreach (var prop in currentType.GetProperties(Flags).Where(p => p.CanRead))
{
// 跳过索引器
if (prop.GetIndexParameters().Length > 0) continue;
object value = prop.GetValue(currentObject);
string newPath = string.IsNullOrEmpty(currentPath) ? prop.Name : $"{currentPath}.{prop.Name}";
CheckAndRecurse(prop.PropertyType, value, targetValue, newPath, depth, results, visited, maxDepth);
}
}
/// <summary>
/// 检查当前值是否匹配,如果不是基础类型则继续递归
/// </summary>
private static void CheckAndRecurse(
Type valueType,
object value,
object targetValue,
string newPath,
int depth,
List<string> results,
HashSet<object> visited,
int maxDepth)
{
if (value == null) return;
// 【值匹配检查】
if (value.Equals(targetValue))
{
results.Add(newPath);
return;
}
// 【递归检查】
// 只有当值是一个复杂类型Class 或 Struct时才需要递归
// 排除字符串和集合List, Array等如果你需要搜索集合内部逻辑会更复杂
if (valueType.IsClass || valueType.IsValueType && !valueType.IsPrimitive)
{
// 排除 String (虽然是 Class但我们视其为基础值)
if (valueType == typeof(string)) return;
// 排除集合(如果需要支持 List<T> 的内部搜索,你需要在这里添加处理逻辑)
if (valueType.IsArray || valueType.IsGenericType && valueType.GetInterfaces().Any(i => i == typeof(System.Collections.IEnumerable))) return;
// 递归进入下一层
FindRecursive(value, targetValue, newPath, depth + 1, results, visited, maxDepth);
}
}
}
public class FastReflection
{
// 定义一个节点,用来缓存每一层的 Field 或 Property 信息
private class MemberNode
{
public FieldInfo Field;
public PropertyInfo Property;
public bool IsField => Field != null;
public MemberNode(MemberInfo info)
{
if (info is FieldInfo f) Field = f;
else if (info is PropertyInfo p) Property = p;
}
// 快速获取值
public object GetValue(object target)
{
return IsField ? Field.GetValue(target) : Property.GetValue(target);
}
// 快速设置值
public void SetValue(object target, object value)
{
if (IsField) Field.SetValue(target, value);
else if (Property != null && Property.CanWrite) Property.SetValue(target, value);
}
// 判断这一层是否是 Struct (值类型),如果是,修改后需要回写
public bool IsStructType()
{
return IsField ? Field.FieldType.IsValueType : Property.PropertyType.IsValueType;
}
}
// 访问器链条
private readonly List<MemberNode> _nodes = new List<MemberNode>();
private bool _isValid = false;
/// <summary>
/// 构造函数:初始化时进行昂贵的解析操作(只做一次)
/// </summary>
public FastReflection(object rootTarget, string path)
{
if (rootTarget == null || string.IsNullOrEmpty(path)) return;
Type currentType = rootTarget.GetType();
string[] parts = path.Split('.');
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var part in parts)
{
// 查找字段或属性
FieldInfo field = currentType.GetField(part, flags);
PropertyInfo prop = currentType.GetProperty(part, flags);
if (field == null && prop == null)
{
Debug.LogError($"[FastReflection] 路径中断: 找不到成员 '{part}' 在类型 '{currentType.Name}' 中");
return;
}
// 创建节点并添加到链条
MemberNode node = new MemberNode(field ?? (MemberInfo)prop);
_nodes.Add(node);
// 更新 currentType 为下一层的类型
currentType = field != null ? field.FieldType : prop.PropertyType;
}
_isValid = true;
}
/// <summary>
/// 获取值(运行时极快)
/// </summary>
public float GetValue(object rootTarget)
{
if (!_isValid) return 0f;
object current = rootTarget;
for (int i = 0; i < _nodes.Count; i++)
{
current = _nodes[i].GetValue(current);
if (current == null) return 0f;
}
return (float)current; // 假设最后一定是 float
}
/// <summary>
/// 设置值(运行时极快,自动处理 Struct 回写)
/// </summary>
public void SetValue(object rootTarget, float newValue)
{
if (!_isValid) return;
// 开始递归处理回写
SetRecursive(rootTarget, 0, newValue);
}
// 递归函数:处理“获取-修改-回写”逻辑
private void SetRecursive(object currentObj, int index, float finalValue)
{
MemberNode node = _nodes[index];
// 1. 如果是链条的最后一个节点(即那个 float 变量)
if (index == _nodes.Count - 1)
{
node.SetValue(currentObj, finalValue);
return;
}
// 2. 如果是中间节点,先获取下一层对象
object nextObj = node.GetValue(currentObj);
if (nextObj == null) return;
// 3. 递归进入下一层
SetRecursive(nextObj, index + 1, finalValue);
// 4. 【关键】回写阶段
// 如果 nextObj 是 Struct值类型比如 Vector3
// 我们刚才在递归里修改了 nextObj 的副本,现在必须把它赋值回 currentObj
if (node.IsStructType())
{
node.SetValue(currentObj, nextObj);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d8465d62ddf65c945924e35a0c1851ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -40,8 +40,7 @@ namespace Ichni.RhythmGame
if (shouldBeActive && !isActive) if (shouldBeActive && !isActive)
{ {
note.gameObject.SetActive(true); note.gameObject.SetActive(true);
note.Update(); if (currentTime < note.exactJudgeTime) note.noteVisual?.Recover();
if (!note.isFirstJudged) note.noteVisual?.Recover();
} }
else if (!shouldBeActive && isActive) else if (!shouldBeActive && isActive)
{ {

View File

@@ -45,7 +45,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -115,7 +115,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : true, "useWorldLight" : true,
"fakeLightDir" : { "fakeLightDir" : {
@@ -185,7 +185,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -492,7 +492,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -562,7 +562,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -632,7 +632,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -702,7 +702,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -772,7 +772,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -842,7 +842,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -1264,8 +1264,8 @@
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp", "__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : { "originalPosition" : {
"x" : 2.2, "x" : 2.2,
"y" : 15, "y" : 0,
"z" : 100 "z" : 0
}, },
"originalEulerAngles" : { "originalEulerAngles" : {
"x" : 0, "x" : 0,
@@ -1307,6 +1307,186 @@
"attachedElementGuid" : { "attachedElementGuid" : {
"value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46" "value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46"
} }
},{
"__type" : "Ichni.RhythmGame.Beatmap.ElementFolder_BM,Assembly-CSharp",
"elementName" : "Folder",
"tags" : [
],
"elementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
},
"attachedElementGuid" : {
"value" : "00000000-0000-0000-0000-000000000000"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : -15,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : 0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 0,
"y" : 2.222,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : -0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 5,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 0.956280768,
"g" : 0.676615953,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0.3649238,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
} }
], ],
"attachedElementGuid" : { "attachedElementGuid" : {

View File

@@ -45,7 +45,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -115,7 +115,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : true, "useWorldLight" : true,
"fakeLightDir" : { "fakeLightDir" : {
@@ -185,7 +185,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -492,7 +492,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -562,7 +562,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -632,7 +632,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -702,7 +702,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -772,7 +772,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -842,7 +842,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -1264,8 +1264,8 @@
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp", "__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : { "originalPosition" : {
"x" : 2.2, "x" : 2.2,
"y" : 15, "y" : 0,
"z" : 100 "z" : 0
}, },
"originalEulerAngles" : { "originalEulerAngles" : {
"x" : 0, "x" : 0,
@@ -1307,6 +1307,186 @@
"attachedElementGuid" : { "attachedElementGuid" : {
"value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46" "value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46"
} }
},{
"__type" : "Ichni.RhythmGame.Beatmap.ElementFolder_BM,Assembly-CSharp",
"elementName" : "Folder",
"tags" : [
],
"elementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
},
"attachedElementGuid" : {
"value" : "00000000-0000-0000-0000-000000000000"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : -15,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : 0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 0,
"y" : 2.222,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : -0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 5,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 0.956280768,
"g" : 0.676615953,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0.3649238,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
} }
], ],
"attachedElementGuid" : { "attachedElementGuid" : {

View File

@@ -45,7 +45,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -115,7 +115,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : true, "useWorldLight" : true,
"fakeLightDir" : { "fakeLightDir" : {
@@ -185,7 +185,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 0.5, "shadowSmoothness" : 0.5,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -492,7 +492,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -562,7 +562,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -632,7 +632,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -702,7 +702,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -772,7 +772,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -842,7 +842,7 @@
} }
},{ },{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp", "__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2, "shadowThreshold" : 0.1,
"shadowSmoothness" : 1, "shadowSmoothness" : 1,
"useWorldLight" : false, "useWorldLight" : false,
"fakeLightDir" : { "fakeLightDir" : {
@@ -1264,8 +1264,8 @@
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp", "__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : { "originalPosition" : {
"x" : 2.2, "x" : 2.2,
"y" : 15, "y" : 0,
"z" : 100 "z" : 0
}, },
"originalEulerAngles" : { "originalEulerAngles" : {
"x" : 0, "x" : 0,
@@ -1307,6 +1307,186 @@
"attachedElementGuid" : { "attachedElementGuid" : {
"value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46" "value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46"
} }
},{
"__type" : "Ichni.RhythmGame.Beatmap.ElementFolder_BM,Assembly-CSharp",
"elementName" : "Folder",
"tags" : [
],
"elementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
},
"attachedElementGuid" : {
"value" : "00000000-0000-0000-0000-000000000000"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : -15,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : 0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 0,
"y" : 2.222,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : -0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 0,
"y" : 2.222,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 0.956280768,
"g" : 0.676615953,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0.3649238,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
} }
], ],
"attachedElementGuid" : { "attachedElementGuid" : {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1307,6 +1307,186 @@
"attachedElementGuid" : { "attachedElementGuid" : {
"value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46" "value" : "5166eb6a-fbee-4c1a-a6d8-d8e263516e46"
} }
},{
"__type" : "Ichni.RhythmGame.Beatmap.ElementFolder_BM,Assembly-CSharp",
"elementName" : "Folder",
"tags" : [
],
"elementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
},
"attachedElementGuid" : {
"value" : "00000000-0000-0000-0000-000000000000"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : -15,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : 0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 0,
"y" : 2.222,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 1,
"g" : 1,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "bc6aed7f-bb86-43da-a59c-b1a7bfe99dea"
}
},{
"__type" : "Beatmap.BasicEnvironmentObject_BM,Assembly-CSharp",
"shadowThreshold" : 0.2,
"shadowSmoothness" : 0.5,
"useWorldLight" : true,
"fakeLightDir" : {
"x" : -0.5,
"y" : 1,
"z" : -0.5
},
"isStatic" : false,
"themeBundleName" : "basic",
"objectName" : "Capsule",
"elementName" : "New Environment Object",
"tags" : [
"sad"
],
"elementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
},
"attachedElementGuid" : {
"value" : "f9731a32-4e6d-4fb4-8d69-0fddc1cab743"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TransformSubmodule_BM,Assembly-CSharp",
"originalPosition" : {
"x" : 5,
"y" : 0,
"z" : 0
},
"originalEulerAngles" : {
"x" : 0,
"y" : 0,
"z" : 0
},
"originalScale" : {
"x" : 1,
"y" : 1,
"z" : 1
},
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.TimeDurationSubmodule_BM,Assembly-CSharp",
"isOverridingDuration" : false,
"startTime" : -32767,
"endTime" : 32767,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
},{
"__type" : "Ichni.RhythmGame.Beatmap.ColorSubmodule_BM,Assembly-CSharp",
"originalBaseColor" : {
"r" : 0.956280768,
"g" : 0.676615953,
"b" : 1,
"a" : 1
},
"emissionEnabled" : false,
"originalEmissionColor" : {
"r" : 0.3649238,
"g" : 0,
"b" : 0,
"a" : 1
},
"originalEmissionIntensity" : 0,
"attachedElementGuid" : {
"value" : "3826be52-7d25-4648-a2fb-a718c01f64c8"
}
} }
], ],
"attachedElementGuid" : { "attachedElementGuid" : {

View File

@@ -25,10 +25,7 @@
}, },
"parameterName" : "shadowSmoothness" "parameterName" : "shadowSmoothness"
} }
], ]
"tempTagMatcherName" : "",
"tempElementTypeName" : "",
"tempParameterName" : ""
}, },
"attachedElementGuid" : { "attachedElementGuid" : {
"value" : "00000000-0000-0000-0000-000000000000" "value" : "00000000-0000-0000-0000-000000000000"

File diff suppressed because one or more lines are too long

View File

@@ -83,7 +83,8 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public override void Adjust() public override void Adjust()
{ {
breathParticle?.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); if (breathParticle != null)
breathParticle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
} }
public override EffectBase_BM ConvertToBM() public override EffectBase_BM ConvertToBM()

View File

@@ -21,8 +21,11 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
} }
public override void Recover() public override void Recover()
{ {
noteVisual.noteMain.SetActive(true); try
{
noteVisual.noteMain.SetActive(true);
}
catch { }
if (note is Hold && noteVisual.isHighlighted) if (note is Hold && noteVisual.isHighlighted)
{ {
noteVisual.extraPartList[0].gameObject.SetActive(true); noteVisual.extraPartList[0].gameObject.SetActive(true);
@@ -37,7 +40,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
effectParticle.Play(); effectParticle.Play();
// effectParticle.transform.DOMove(noteVisual.noteVisualPosition, 0.2f); // effectParticle.transform.DOMove(noteVisual.noteVisualPosition, 0.2f);
if (note is Hold && noteVisual.isHighlighted) if (note is Hold && noteVisual.isHighlighted)
{ {
noteVisual.extraPartList[0].gameObject.SetActive(false); noteVisual.extraPartList[0].gameObject.SetActive(false);