大修
This commit is contained in:
@@ -25,6 +25,9 @@ namespace Ichni.Editor
|
||||
public GameObject ConsoleUI;
|
||||
public TMP_Text cueText;
|
||||
bool isHide = true;
|
||||
|
||||
|
||||
|
||||
private string FillCueCommand(MethodInfo method)
|
||||
{
|
||||
if (method == null)
|
||||
@@ -115,7 +118,15 @@ namespace Ichni.Editor
|
||||
private void Update()
|
||||
{
|
||||
UIscale();
|
||||
if (InputCommand.isFocused) InputDect();
|
||||
if (InputCommand.isFocused)
|
||||
{
|
||||
|
||||
InputDect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("未聚焦输入框");
|
||||
}
|
||||
}
|
||||
private void UIscale()
|
||||
{
|
||||
@@ -177,6 +188,8 @@ namespace Ichni.Editor
|
||||
//这是史,不要看
|
||||
private void InputDect()
|
||||
{
|
||||
Debug.Log("输入指令中");
|
||||
|
||||
// 向下翻历史命令
|
||||
if (Keyboard.current.downArrowKey.wasPressedThisFrame)
|
||||
{
|
||||
@@ -192,6 +205,8 @@ namespace Ichni.Editor
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("输入指令中 - 1");
|
||||
|
||||
// 向上翻历史命令
|
||||
if (Keyboard.current.upArrowKey.wasPressedThisFrame && historycount != 0)
|
||||
@@ -200,32 +215,11 @@ namespace Ichni.Editor
|
||||
InputCommand.text = historyCommand[historycount];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Debug.Log("输入指令中 - 2");
|
||||
|
||||
// 提交命令
|
||||
if (Keyboard.current.enterKey.wasPressedThisFrame)
|
||||
{
|
||||
string input = InputCommand.text; // 原始命令文本
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
InputCommand.text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// 【修改点】:调用新方法获取最终执行的命令(已包含修正逻辑和 TransformCommand)
|
||||
string ExpoCommand = GetFinalCommandForExecution(input);
|
||||
|
||||
// print(ExpoCommand); // 调试语句,可选
|
||||
GetCommand(ExpoCommand);
|
||||
|
||||
// 记录历史命令,使用原始命令 input
|
||||
if (historyCommand.ContainsKey(historycount))
|
||||
historyCommand[historycount] = input;
|
||||
else
|
||||
historyCommand.Add(historycount, input);
|
||||
|
||||
historycount++;
|
||||
InputCommand.text = "";
|
||||
}
|
||||
|
||||
CheckCtrlNumberShortcut();
|
||||
|
||||
}
|
||||
@@ -328,11 +322,41 @@ namespace Ichni.Editor
|
||||
{
|
||||
|
||||
SetUpFunctions();
|
||||
|
||||
|
||||
InputCommand.onSubmit.AddListener(OnSubmitCommand);
|
||||
|
||||
//Test
|
||||
// functionInterpreter.Eval("print(\"Hello World!\")");
|
||||
// functionInterpreter.Eval("log(\"Hello World but debug!\")");
|
||||
}
|
||||
|
||||
private void OnSubmitCommand(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
InputCommand.text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行转换和提交命令
|
||||
string ExpoCommand = GetFinalCommandForExecution(input);
|
||||
GetCommand(ExpoCommand);
|
||||
|
||||
// 记录历史
|
||||
if (historyCommand.ContainsKey(historycount))
|
||||
historyCommand[historycount] = input;
|
||||
else
|
||||
historyCommand.Add(historycount, input);
|
||||
|
||||
historycount++;
|
||||
|
||||
// 提交后清零输入框文本
|
||||
InputCommand.text = "";
|
||||
|
||||
// 核心体验优化:回车后立刻强制重新激活聚焦光标,以便用户紧接着顺畅丝滑地连续敲下一条指令
|
||||
InputCommand.ActivateInputField();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public partial class EditorConsole
|
||||
|
||||
@@ -365,7 +365,7 @@ namespace Ichni.Editor
|
||||
float endTime = hold.holdEndTime;
|
||||
float interval = 1f / (PathnodesCount - 1);
|
||||
|
||||
hold.UpdateNoteInMovableTrack();
|
||||
hold.UpdateNoteInMovableTrack(CoreServices.TimeProvider.SongTime);
|
||||
Vector3 HoldStartPos = default;
|
||||
Vector3 HoldEndPos = default;
|
||||
if (hold.noteVisual is DTMNoteVisualHold dTMNoteVisualHold)
|
||||
@@ -385,7 +385,7 @@ namespace Ichni.Editor
|
||||
LogWindow.Log("the Hold may not be split currently", Color.yellow);
|
||||
return;
|
||||
}
|
||||
hold.UpdateNoteInMovableTrack();
|
||||
hold.UpdateNoteInMovableTrack(CoreServices.TimeProvider.SongTime);
|
||||
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++)
|
||||
|
||||
@@ -14,18 +14,16 @@ namespace Ichni.Editor
|
||||
{
|
||||
public GameObject logTextPrefab;
|
||||
|
||||
List<string> savedTexts;
|
||||
public List<string> savedTexts = new List<string>();
|
||||
public RectTransform textRect;
|
||||
public Button copyAllTextsButton;
|
||||
public Button removeAllTextsButton;
|
||||
public List<LogText> logTexts; // 改为 List
|
||||
public List<LogText> logTexts = new List<LogText>(); // 改为 List
|
||||
public int logTextCapacity = 4;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
savedTexts = new List<string>();
|
||||
logTexts = new List<LogText>(); // 初始化为 List
|
||||
copyAllTextsButton.onClick.AddListener(CopyAllText);
|
||||
removeAllTextsButton.onClick.AddListener(RemoveAllText);
|
||||
}
|
||||
|
||||
@@ -53,11 +53,9 @@ namespace Ichni.Editor
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
if (EditorManager.instance.musicPlayer.isPlaying)
|
||||
if (CoreServices.TimeProvider.IsPlaying)
|
||||
{
|
||||
UpdateTime();
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (RectTransformUtility.RectangleContainsScreenPoint(GetinputArea, Mouse.current.position.ReadValue()))
|
||||
|
||||
BIN
Assets/Scripts/EditorGame/.DS_Store
vendored
BIN
Assets/Scripts/EditorGame/.DS_Store
vendored
Binary file not shown.
@@ -1,153 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class BaseColorChange : AnimationBase
|
||||
{
|
||||
private ColorSubmodule targetColorSubmodule;
|
||||
public FlexibleFloat colorR, colorG, colorB, colorA;
|
||||
|
||||
public static BaseColorChange GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
|
||||
FlexibleFloat colorR, FlexibleFloat colorG, FlexibleFloat colorB, FlexibleFloat colorA)
|
||||
{
|
||||
BaseColorChange baseColorChange = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<BaseColorChange>();
|
||||
|
||||
baseColorChange.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
|
||||
baseColorChange.animatedObject = animatedObject;
|
||||
|
||||
baseColorChange.colorR = colorR;
|
||||
baseColorChange.colorG = colorG;
|
||||
baseColorChange.colorB = colorB;
|
||||
baseColorChange.colorA = colorA;
|
||||
baseColorChange.animationReturnType = FlexibleReturnType.Before;
|
||||
|
||||
baseColorChange.targetColorSubmodule = (animatedObject as IHaveColorSubmodule).colorSubmodule;
|
||||
|
||||
//baseColorChange.timeDurationSubmodule.SetDuration(colorR, colorG, colorB, colorA);
|
||||
|
||||
return baseColorChange;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
colorR.UpdateFlexibleFloat(songTime);
|
||||
colorG.UpdateFlexibleFloat(songTime);
|
||||
colorB.UpdateFlexibleFloat(songTime);
|
||||
colorA.UpdateFlexibleFloat(songTime);
|
||||
|
||||
if ((colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
|
||||
(colorG.returnType is FlexibleReturnType.MiddleExecuting || colorG.isSwitchingReturnType) ||
|
||||
(colorB.returnType is FlexibleReturnType.MiddleExecuting || colorB.isSwitchingReturnType) ||
|
||||
(colorA.returnType is FlexibleReturnType.MiddleExecuting || colorA.isSwitchingReturnType))
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
|
||||
targetColorSubmodule.currentBaseColor = new Color(colorR.value, colorG.value, colorB.value, colorA.value);
|
||||
targetColorSubmodule.baseColorDirtyMark = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyTimeOffset(float offset)
|
||||
{
|
||||
base.ApplyTimeOffset(offset);
|
||||
colorR.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorG.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorB.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorA.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Base Color Change");
|
||||
var subcontainer = container.GenerateSubcontainer(3);
|
||||
var colorRButton = inspector.GenerateButton(this, subcontainer, "Color R", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color R", nameof(colorR)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorGButton = inspector.GenerateButton(this, subcontainer, "Color G", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color G", nameof(colorG)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorBButton = inspector.GenerateButton(this, subcontainer, "Color B", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color B", nameof(colorB)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorAButton = inspector.GenerateButton(this, subcontainer, "Color A", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color A", nameof(colorA)).SetAsFlexibleFloat();
|
||||
});
|
||||
var graphicEditor = inspector.GenerateButton(this, subcontainer, "GraphicEditor", () =>
|
||||
{
|
||||
inspector.GenerateGraphicalFlexibleFloatWindow(this, "Base Color",
|
||||
new FlexibleFloat[] { colorR, colorG, colorB, colorA }, new string[] { "R", "G", "B", "A" });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BaseColorChange
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new BaseColorChange_BM(elementName, elementGuid, tags,
|
||||
animatedObject.matchedBM as GameElement_BM, colorR.ConvertToBM(),
|
||||
colorG.ConvertToBM(), colorB.ConvertToBM(), colorA.ConvertToBM());
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class BaseColorChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM colorR, colorG, colorB, colorA;
|
||||
|
||||
public BaseColorChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BaseColorChange_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM colorR, FlexibleFloat_BM colorG,
|
||||
FlexibleFloat_BM colorB, FlexibleFloat_BM colorA) :
|
||||
base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.colorR = colorR;
|
||||
this.colorG = colorG;
|
||||
this.colorB = colorB;
|
||||
this.colorA = colorA;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = BaseColorChange.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), colorR.ConvertToGameType(),
|
||||
colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return BaseColorChange.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent, colorR.ConvertToGameType(), colorG.ConvertToGameType(),
|
||||
colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class EmissionColorChange : AnimationBase
|
||||
{
|
||||
private ColorSubmodule targetColorSubmodule;
|
||||
public FlexibleFloat colorR, colorG, colorB, colorI;
|
||||
|
||||
public static EmissionColorChange GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
|
||||
FlexibleFloat colorR, FlexibleFloat colorG, FlexibleFloat colorB, FlexibleFloat colorI)
|
||||
{
|
||||
EmissionColorChange emissionColorChange = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<EmissionColorChange>();
|
||||
|
||||
emissionColorChange.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
|
||||
emissionColorChange.animatedObject = animatedObject;
|
||||
|
||||
emissionColorChange.colorR = colorR;
|
||||
emissionColorChange.colorG = colorG;
|
||||
emissionColorChange.colorB = colorB;
|
||||
emissionColorChange.colorI = colorI;
|
||||
emissionColorChange.animationReturnType = FlexibleReturnType.Before;
|
||||
|
||||
emissionColorChange.targetColorSubmodule = (animatedObject as IHaveColorSubmodule).colorSubmodule;
|
||||
|
||||
|
||||
//emissionColorChange.timeDurationSubmodule.SetDuration(colorR, colorG, colorB, colorI);
|
||||
|
||||
return emissionColorChange;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
colorR.UpdateFlexibleFloat(songTime);
|
||||
colorG.UpdateFlexibleFloat(songTime);
|
||||
colorB.UpdateFlexibleFloat(songTime);
|
||||
colorI.UpdateFlexibleFloat(songTime);
|
||||
|
||||
if ((colorR.returnType is FlexibleReturnType.MiddleExecuting || colorR.isSwitchingReturnType) ||
|
||||
(colorG.returnType is FlexibleReturnType.MiddleExecuting || colorG.isSwitchingReturnType) ||
|
||||
(colorB.returnType is FlexibleReturnType.MiddleExecuting || colorB.isSwitchingReturnType) ||
|
||||
(colorI.returnType is FlexibleReturnType.MiddleExecuting || colorI.isSwitchingReturnType))
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
|
||||
targetColorSubmodule.currentEmissionColor = new Color(colorR.value, colorG.value, colorB.value, 1);
|
||||
targetColorSubmodule.currentEmissionIntensity = colorI.value;
|
||||
targetColorSubmodule.emissionColorDirtyMark = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyTimeOffset(float offset)
|
||||
{
|
||||
base.ApplyTimeOffset(offset);
|
||||
colorR.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorG.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorB.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
colorI.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class EmissionColorChange
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new EmissionColorChange_BM(elementName, elementGuid, tags, animatedObject.matchedBM as GameElement_BM,
|
||||
colorR.ConvertToBM(), colorG.ConvertToBM(), colorB.ConvertToBM(), colorI.ConvertToBM());
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Base Color Change");
|
||||
var subcontainer = container.GenerateSubcontainer(3);
|
||||
var colorRButton = inspector.GenerateButton(this, subcontainer, "Color R", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color R", nameof(colorR)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorGButton = inspector.GenerateButton(this, subcontainer, "Color G", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color G", nameof(colorG)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorBButton = inspector.GenerateButton(this, subcontainer, "Color B", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color B", nameof(colorB)).SetAsFlexibleFloat();
|
||||
});
|
||||
var colorAButton = inspector.GenerateButton(this, subcontainer, "Color A", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Color I", nameof(colorI)).SetAsFlexibleFloat();
|
||||
});
|
||||
var graphicEditor = inspector.GenerateButton(this, subcontainer, "GraphicEditor", () =>
|
||||
{
|
||||
inspector.GenerateGraphicalFlexibleFloatWindow(this, "Emission Color",
|
||||
new FlexibleFloat[] { colorR, colorG, colorB, colorI }, new string[] { "R", "G", "B", "I" });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class EmissionColorChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM colorR, colorG, colorB, colorI;
|
||||
|
||||
public EmissionColorChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EmissionColorChange_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM parentElement,
|
||||
FlexibleFloat_BM colorR, FlexibleFloat_BM colorG, FlexibleFloat_BM colorB, FlexibleFloat_BM colorI) :
|
||||
base(elementName, elementGuid, tags, parentElement)
|
||||
{
|
||||
this.colorR = colorR;
|
||||
this.colorG = colorG;
|
||||
this.colorB = colorB;
|
||||
this.colorI = colorI;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = EmissionColorChange.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return EmissionColorChange.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TrackTotalTimeChange : AnimationBase
|
||||
{
|
||||
public FlexibleFloat totalTime;
|
||||
public TrackTimeSubmoduleStatic targetTrackTimeSubmoduleStatic;
|
||||
|
||||
public static TrackTotalTimeChange GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, Track animatedTrack, FlexibleFloat totalTime)
|
||||
{
|
||||
TrackTotalTimeChange trackTotalTimeChange = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<TrackTotalTimeChange>();
|
||||
trackTotalTimeChange.Initialize(elementName, id, tags, isFirstGenerated, animatedTrack);
|
||||
|
||||
trackTotalTimeChange.animatedObject = animatedTrack;
|
||||
|
||||
trackTotalTimeChange.targetTrackTimeSubmoduleStatic = animatedTrack.trackTimeSubmodule as TrackTimeSubmoduleStatic;
|
||||
|
||||
trackTotalTimeChange.totalTime = totalTime;
|
||||
trackTotalTimeChange.animationReturnType = FlexibleReturnType.Before;
|
||||
//trackTotalTimeChange.timeDurationSubmodule.SetDuration(totalTime);
|
||||
|
||||
return trackTotalTimeChange;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
totalTime.UpdateFlexibleFloat(songTime);
|
||||
|
||||
if (totalTime.returnType == FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
targetTrackTimeSubmoduleStatic.trackTotalTime = totalTime.value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyTimeOffset(float offset)
|
||||
{
|
||||
base.ApplyTimeOffset(offset);
|
||||
totalTime.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TrackTotalTimeChange
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackTotalTimeChange_BM(elementName, elementGuid, tags, animatedObject.matchedBM as Track_BM, totalTime.ConvertToBM());
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Displacement");
|
||||
var subcontainer = container.GenerateSubcontainer(3);
|
||||
var positionXButton = inspector.GenerateButton(this, subcontainer, "Total Time", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Total Time", nameof(totalTime)).SetAsFlexibleFloat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackTotalTimeChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM totalTime;
|
||||
|
||||
public TrackTotalTimeChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackTotalTimeChange_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM totalTime) :
|
||||
base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = TrackTotalTimeChange.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, totalTime.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return TrackTotalTimeChange.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as Track, totalTime.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
/// <summary>
|
||||
/// 将物体的z轴指向目标物体,注意,LookAt的启用期间,物体的旋转将被锁定
|
||||
/// </summary>
|
||||
public partial class LookAt : AnimationBase
|
||||
{
|
||||
public GameCamera gameCamera;
|
||||
public TransformSubmodule targetTransformSubmodule;
|
||||
public GameElement lookAtObject;
|
||||
public FlexibleBool enabling;
|
||||
|
||||
public static LookAt GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
|
||||
GameElement lookAtTarget, FlexibleBool enabling)
|
||||
{
|
||||
LookAt look = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<LookAt>();
|
||||
|
||||
look.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
|
||||
|
||||
look.animatedObject = animatedObject;
|
||||
look.lookAtObject = lookAtTarget;
|
||||
look.enabling = enabling;
|
||||
look.animationReturnType = FlexibleReturnType.Before;
|
||||
|
||||
look.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
|
||||
look.targetTransformSubmodule.lookAt = look;
|
||||
look.gameCamera = EditorManager.instance.cameraManager.gameCamera;
|
||||
return look;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (enabling.value) (animatedObject as IHaveTransformSubmodule)?.UpdateLookAt(this);
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
if (lookAtObject == null) return;
|
||||
|
||||
enabling.UpdateFlexibleBool(songTime);
|
||||
|
||||
if (!targetTransformSubmodule.eulerAnglesOffsetLock || enabling.value)
|
||||
{
|
||||
targetTransformSubmodule.eulerAnglesOffsetLock = enabling.value;
|
||||
}
|
||||
|
||||
if (enabling.value)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
targetTransformSubmodule.eulerAnglesDirtyMark = true;
|
||||
|
||||
}
|
||||
else if (animationReturnType != FlexibleReturnType.MiddleInterval)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
targetTransformSubmodule.eulerAnglesDirtyMark = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new LookAt_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
enabling.ConvertToBM(), lookAtObject.elementGuid);
|
||||
}
|
||||
|
||||
public override void ApplyTimeOffset(float offset)
|
||||
{
|
||||
base.ApplyTimeOffset(offset);
|
||||
enabling.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
|
||||
}
|
||||
public void OnDestroy()
|
||||
{
|
||||
targetTransformSubmodule.eulerAnglesDirtyMark = true;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class LookAt
|
||||
{
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Enable Control");
|
||||
var effectSettings = container.GenerateSubcontainer(2);
|
||||
var connectedGameElementInputField = inspector.GenerateInputField(effectSettings, "Try Get Element");
|
||||
var connectGameElementButton = inspector.GenerateButton(this, effectSettings, "Connect Game Element", () =>
|
||||
{
|
||||
GameElement targetElement = EditorManager.instance.beatmapContainer.gameElementList
|
||||
.First(e => e.elementName == connectedGameElementInputField.GetValue<string>());
|
||||
|
||||
if (targetElement == null)
|
||||
{
|
||||
LogWindow.Log("Game Element not found.", Color.yellow);
|
||||
}
|
||||
|
||||
lookAtObject = targetElement;
|
||||
//targetTransformSubmodule = (targetElement as IHaveTransformSubmodule).transformSubmodule;
|
||||
|
||||
inspectorMain.SetInspector(this);
|
||||
});
|
||||
string ShowConnection() => lookAtObject == null ? "No Game Element Connected" : "Connected With: " + lookAtObject.elementName;
|
||||
var connectHintText = inspector.GenerateHintText(this, effectSettings, ShowConnection);
|
||||
|
||||
var enablingButton = inspector.GenerateButton(this, effectSettings, "Enabling", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Enabling", nameof(enabling)).SetAsFlexibleBool();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class LookAt_BM : GameElement_BM
|
||||
{
|
||||
public FlexibleBool_BM enabling;
|
||||
public Guid lookAtObjectGuid;
|
||||
|
||||
public LookAt_BM()
|
||||
{
|
||||
}
|
||||
|
||||
public LookAt_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleBool_BM enabling, Guid lookAtObjectGuid)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.enabling = enabling;
|
||||
this.lookAtObjectGuid = lookAtObjectGuid;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = LookAt.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), GetElement(lookAtObjectGuid), enabling.ConvertToGameType());
|
||||
matchedElement.matchedBM = this;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return LookAt.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
GetElement(lookAtObjectGuid), enabling.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override void AfterExecute()
|
||||
{
|
||||
(matchedElement as LookAt).lookAtObject = GetElement(lookAtObjectGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Assets/Scripts/EditorGame/Base/.DS_Store
vendored
BIN
Assets/Scripts/EditorGame/Base/.DS_Store
vendored
Binary file not shown.
@@ -1,145 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
[System.Serializable]
|
||||
public class AnimatedBool
|
||||
{
|
||||
public bool value; //bool值
|
||||
public float time; //当前时间
|
||||
|
||||
public AnimatedBool(float time, bool value)
|
||||
{
|
||||
this.value = value;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public void ApplyTimeOffset(float offset)
|
||||
{
|
||||
time += offset;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class FlexibleBool
|
||||
{
|
||||
public bool value;
|
||||
public List<AnimatedBool> animations;
|
||||
|
||||
public FlexibleBool()
|
||||
{
|
||||
animations = new List<AnimatedBool>();
|
||||
}
|
||||
|
||||
public FlexibleBool(List<AnimatedBool> anim)
|
||||
{
|
||||
this.animations = anim;
|
||||
}
|
||||
|
||||
public void Add(AnimatedBool animatedBool)
|
||||
{
|
||||
animations.Add(animatedBool);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在动画脚本的Update中更新Bool Value
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
public FlexibleReturnType UpdateFlexibleBool(float nowTime)
|
||||
{
|
||||
AnimatedBool nowAnimatedBool = GetAnimatedBool(nowTime); //获取当前时间点对应的AnimatedBool
|
||||
value = nowAnimatedBool.value; //更新value
|
||||
return FlexibleReturnType.MiddleExecuting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取songTime对应的AnimatedBool的时间段
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
/// <returns>返回距离当前时间最近的前一个AnimatedBool</returns>
|
||||
AnimatedBool GetAnimatedBool(float nowTime)
|
||||
{
|
||||
if (animations.Count == 0)
|
||||
{
|
||||
return new AnimatedBool(0, false);
|
||||
}
|
||||
if (nowTime < animations[0].time)
|
||||
{
|
||||
return animations[0];
|
||||
}
|
||||
|
||||
if (nowTime > animations[animations.Count - 1].time)
|
||||
{
|
||||
return animations[animations.Count - 1];
|
||||
}
|
||||
|
||||
for (int i = 0; i < animations.Count; i++)
|
||||
{
|
||||
if (nowTime < animations[i].time)
|
||||
{
|
||||
return animations[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return new AnimatedBool(0, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为Beatmap存档类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public FlexibleBool_BM ConvertToBM()
|
||||
{
|
||||
FlexibleBool_BM flexibleBool_BM = new FlexibleBool_BM();
|
||||
|
||||
foreach (AnimatedBool animatedBool in animations)
|
||||
{
|
||||
flexibleBool_BM.animatedBoolList.Add(new AnimatedBool(animatedBool.time, animatedBool.value));
|
||||
}
|
||||
|
||||
return flexibleBool_BM;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class FlexibleBool_BM
|
||||
{
|
||||
public List<AnimatedBool> animatedBoolList;
|
||||
|
||||
public FlexibleBool_BM()
|
||||
{
|
||||
this.animatedBoolList = new List<AnimatedBool>();
|
||||
}
|
||||
|
||||
public FlexibleBool_BM(List<AnimatedBool> animatedBoolList)
|
||||
{
|
||||
this.animatedBoolList = animatedBoolList;
|
||||
}
|
||||
|
||||
public FlexibleBool ConvertToGameType()
|
||||
{
|
||||
FlexibleBool flexibleBool;
|
||||
|
||||
if (this.animatedBoolList.Count == 0)
|
||||
{
|
||||
flexibleBool = new FlexibleBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AnimatedBool> animations = new List<AnimatedBool>();
|
||||
foreach (AnimatedBool animatedBool in animatedBoolList)
|
||||
{
|
||||
animations.Add(new AnimatedBool(animatedBool.time, animatedBool.value));
|
||||
}
|
||||
|
||||
flexibleBool = new FlexibleBool(animations);
|
||||
}
|
||||
|
||||
return flexibleBool;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
[System.Serializable]
|
||||
public class AnimatedFloat : IComparable<AnimatedFloat>
|
||||
{
|
||||
public float startValue, endValue; //起止值
|
||||
public float startTime, endTime; //起止时间
|
||||
public AnimationCurveType animationCurveType; //动画曲线类型
|
||||
|
||||
public float differenceValue => endValue - startValue; //差值
|
||||
public float totalTime => endTime - startTime; //总时间
|
||||
|
||||
|
||||
public AnimatedFloat(float startTime, float endTime, float startValue, float endValue,
|
||||
AnimationCurveType animationCurveType)
|
||||
{
|
||||
this.startValue = startValue;
|
||||
this.endValue = endValue;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.animationCurveType = animationCurveType;
|
||||
}
|
||||
|
||||
public void ApplyTimeOffset(float offset)
|
||||
{
|
||||
startTime += offset;
|
||||
endTime += offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照起始时间排序
|
||||
/// </summary>
|
||||
public int CompareTo(AnimatedFloat obj)
|
||||
{
|
||||
return startTime.CompareTo(obj.startTime);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class FlexibleFloat
|
||||
{
|
||||
public float value;
|
||||
public int currentAnimationIndex;
|
||||
public List<AnimatedFloat> animations;
|
||||
public bool isSwitchingReturnType;
|
||||
public FlexibleReturnType lastReturnType;
|
||||
public FlexibleReturnType returnType;
|
||||
public event Action OnDataChanged;
|
||||
|
||||
public FlexibleFloat(bool withFirstAnimation = false)
|
||||
{
|
||||
animations = new List<AnimatedFloat>();
|
||||
if (withFirstAnimation)
|
||||
{
|
||||
animations.Add(new AnimatedFloat(0f, 1f, 0f, 0f, AnimationCurveType.Linear));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public FlexibleFloat(List<AnimatedFloat> anim)
|
||||
{
|
||||
animations = anim;
|
||||
}
|
||||
|
||||
public void Add(AnimatedFloat animatedFloat)
|
||||
{
|
||||
animations.Add(animatedFloat);
|
||||
OnDataChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Sort()
|
||||
{
|
||||
animations.Sort();
|
||||
OnDataChanged?.Invoke();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 在动画脚本的Update中更新value
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
public void UpdateFlexibleFloat(float nowTime)
|
||||
{
|
||||
if (isSwitchingReturnType) isSwitchingReturnType = false;
|
||||
|
||||
AnimatedFloat nowAnimatedFloat = GetAnimatedFloat(nowTime); //获取当前时间点对应的AnimatedFloat
|
||||
if (nowAnimatedFloat != null) //如果能获取到,表明当前时间点存在动画
|
||||
{
|
||||
|
||||
if (currentAnimationIndex == animations.Count - 1 && nowTime + Time.deltaTime >= nowAnimatedFloat.endTime)
|
||||
{
|
||||
value = nowAnimatedFloat.endValue;
|
||||
returnType = FlexibleReturnType.After;
|
||||
if (lastReturnType != returnType) isSwitchingReturnType = true;
|
||||
lastReturnType = returnType;
|
||||
return;
|
||||
}
|
||||
//获取songTime时间点时,基于动画曲线的AnimatedFloat比例点->(0,1)。
|
||||
float nowPercent = AnimationCurveEvaluator.Evaluate(nowAnimatedFloat.animationCurveType,
|
||||
(nowTime - nowAnimatedFloat.startTime) / nowAnimatedFloat.totalTime);
|
||||
value = nowAnimatedFloat.startValue + nowPercent * nowAnimatedFloat.differenceValue; //计算value
|
||||
|
||||
returnType = FlexibleReturnType.MiddleExecuting;
|
||||
if (lastReturnType != returnType) isSwitchingReturnType = true;
|
||||
lastReturnType = returnType;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (animations.Count > 0) //如果当前时间点没有动画
|
||||
{
|
||||
float finalStartTime = animations[0].startTime;
|
||||
float finalEndTime = animations[animations.Count - 1].endTime;
|
||||
|
||||
if (nowTime < finalStartTime) //如果当前时间小于第一个动画的开始时间
|
||||
{
|
||||
nowAnimatedFloat = animations[0];
|
||||
//nowPercent = 0;
|
||||
|
||||
if (nowAnimatedFloat != null)
|
||||
{
|
||||
value = nowAnimatedFloat.startValue;
|
||||
}
|
||||
|
||||
returnType = FlexibleReturnType.Before;
|
||||
if (lastReturnType != returnType) isSwitchingReturnType = true;
|
||||
lastReturnType = returnType;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (nowTime > finalEndTime) //如果当前时间大于最后一个动画的结束时间
|
||||
{
|
||||
nowAnimatedFloat = animations[animations.Count - 1];
|
||||
//nowPercent = 1;
|
||||
|
||||
if (nowAnimatedFloat != null)
|
||||
{
|
||||
value = nowAnimatedFloat.endValue;
|
||||
}
|
||||
|
||||
returnType = FlexibleReturnType.After;
|
||||
if (lastReturnType != returnType) isSwitchingReturnType = true;
|
||||
lastReturnType = returnType;
|
||||
|
||||
return;
|
||||
}
|
||||
SetLateAnimatedFloat(nowTime); //如果当前时间点在动画之间,设置currentAnimationIndex
|
||||
if (currentAnimationIndex >= 0) //如果当前时间点在动画之间
|
||||
{
|
||||
value = animations[currentAnimationIndex].endValue;
|
||||
}
|
||||
|
||||
returnType = FlexibleReturnType.MiddleInterval;
|
||||
if (lastReturnType != returnType) isSwitchingReturnType = true;
|
||||
lastReturnType = returnType;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//如果没有动画
|
||||
value = 0;
|
||||
returnType = FlexibleReturnType.None;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取songTime对应的AnimatedFloat的时间段
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
/// <returns></returns>
|
||||
AnimatedFloat GetAnimatedFloat(float nowTime)
|
||||
{
|
||||
for (int i = 0; i < animations.Count; i++)
|
||||
{
|
||||
if (nowTime >= animations[i].startTime && nowTime < animations[i].endTime)
|
||||
{
|
||||
currentAnimationIndex = i;
|
||||
return animations[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
void SetLateAnimatedFloat(float nowTime)
|
||||
{
|
||||
for (int i = 0; i < animations.Count - 1; i++)
|
||||
{
|
||||
if (nowTime >= animations[i].startTime && nowTime < animations[i + 1].startTime)
|
||||
{
|
||||
currentAnimationIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
currentAnimationIndex = 0;
|
||||
return;
|
||||
}
|
||||
public float GetValue(float songtime)
|
||||
{
|
||||
UpdateFlexibleFloat(songtime);
|
||||
float a = value;
|
||||
return a;
|
||||
}
|
||||
public (FlexibleReturnType, bool) getReturnType(float Songtime)
|
||||
{
|
||||
UpdateFlexibleFloat(Songtime);
|
||||
return (returnType, isSwitchingReturnType);
|
||||
}
|
||||
public (FlexibleReturnType, bool, float) GetReturnTypeAndValue(float songtime)
|
||||
{
|
||||
UpdateFlexibleFloat(songtime);
|
||||
return (returnType, isSwitchingReturnType, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// 转换为Beatmap存档类型
|
||||
/// </summary>
|
||||
public FlexibleFloat_BM ConvertToBM()
|
||||
{
|
||||
FlexibleFloat_BM flexibleFloat_BM = new FlexibleFloat_BM();
|
||||
|
||||
foreach (AnimatedFloat animatedFloat in animations)
|
||||
{
|
||||
flexibleFloat_BM.animatedFloatList.Add(new AnimatedFloat(animatedFloat.startTime, animatedFloat.endTime,
|
||||
animatedFloat.startValue, animatedFloat.endValue, animatedFloat.animationCurveType));
|
||||
}
|
||||
|
||||
return flexibleFloat_BM;
|
||||
}
|
||||
public void ApplyTimeOffset(float OffsetTime)
|
||||
{
|
||||
animations.ForEach(i =>
|
||||
{
|
||||
i.ApplyTimeOffset(OffsetTime);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class FlexibleFloat_BM
|
||||
{
|
||||
public List<AnimatedFloat> animatedFloatList;
|
||||
|
||||
public FlexibleFloat_BM()
|
||||
{
|
||||
this.animatedFloatList = new List<AnimatedFloat>();
|
||||
}
|
||||
|
||||
public FlexibleFloat_BM(List<AnimatedFloat> animatedFloatList)
|
||||
{
|
||||
this.animatedFloatList = animatedFloatList;
|
||||
}
|
||||
|
||||
public FlexibleFloat ConvertToGameType()
|
||||
{
|
||||
FlexibleFloat flexibleFloat;
|
||||
|
||||
if (animatedFloatList.Count == 0)
|
||||
{
|
||||
flexibleFloat = new FlexibleFloat();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AnimatedFloat> animatedFloatList = new List<AnimatedFloat>();
|
||||
foreach (AnimatedFloat animatedFloat in this.animatedFloatList)
|
||||
{
|
||||
animatedFloatList.Add(new AnimatedFloat(
|
||||
animatedFloat.startTime, animatedFloat.endTime,
|
||||
animatedFloat.startValue, animatedFloat.endValue,
|
||||
animatedFloat.animationCurveType));
|
||||
}
|
||||
|
||||
flexibleFloat = new FlexibleFloat(animatedFloatList);
|
||||
}
|
||||
|
||||
return flexibleFloat;
|
||||
}
|
||||
public FlexibleFloat_BM DeepCopyBM()
|
||||
{
|
||||
FlexibleFloat_BM copy = new FlexibleFloat_BM();
|
||||
foreach (AnimatedFloat animatedFloat in animatedFloatList)
|
||||
{
|
||||
copy.animatedFloatList.Add(new AnimatedFloat(
|
||||
animatedFloat.startTime, animatedFloat.endTime,
|
||||
animatedFloat.startValue, animatedFloat.endValue,
|
||||
animatedFloat.animationCurveType));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
public void ApplyTimeOffset(float OffsetTime)
|
||||
{
|
||||
animatedFloatList.ForEach(i =>
|
||||
{
|
||||
i.ApplyTimeOffset(OffsetTime);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
[System.Serializable]
|
||||
public class AnimatedInt
|
||||
{
|
||||
public int value; //值
|
||||
public float time;
|
||||
|
||||
public AnimatedInt()
|
||||
{
|
||||
}
|
||||
|
||||
public AnimatedInt(float time, int value)
|
||||
{
|
||||
this.value = value;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public void ApplyTimeOffset(float offset)
|
||||
{
|
||||
time += offset;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class FlexibleInt
|
||||
{
|
||||
public int value;
|
||||
public List<AnimatedInt> animations;
|
||||
|
||||
public FlexibleInt()
|
||||
{
|
||||
animations = new List<AnimatedInt>();
|
||||
}
|
||||
|
||||
public FlexibleInt(List<AnimatedInt> anim)
|
||||
{
|
||||
this.animations = anim;
|
||||
}
|
||||
|
||||
public void Add(AnimatedInt animatedInt)
|
||||
{
|
||||
animations.Add(animatedInt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在动画脚本的Update中更新Int Value
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
public FlexibleReturnType UpdateFlexibleInt(float nowTime)
|
||||
{
|
||||
AnimatedInt nowAnimatedInt = GetAnimatedInt(nowTime); //获取当前时间点对应的AnimatedInt
|
||||
value = nowAnimatedInt.value; //更新value
|
||||
return FlexibleReturnType.MiddleExecuting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取songTime对应的AnimatedInt的时间段
|
||||
/// </summary>
|
||||
/// <param name="歌曲时间"></param>
|
||||
/// <returns>返回距离当前时间最近的前一个AnimatedInt</returns>
|
||||
AnimatedInt GetAnimatedInt(float nowTime)
|
||||
{
|
||||
if (nowTime < animations[0].time)
|
||||
{
|
||||
return animations[0];
|
||||
}
|
||||
|
||||
if (nowTime > animations[animations.Count - 1].time)
|
||||
{
|
||||
return animations[animations.Count - 1];
|
||||
}
|
||||
|
||||
for (int i = 0; i < animations.Count; i++)
|
||||
{
|
||||
if (nowTime < animations[i].time)
|
||||
{
|
||||
return animations[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return new AnimatedInt(0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为Beatmap存档类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public FlexibleInt_BM ConvertToBM()
|
||||
{
|
||||
FlexibleInt_BM flexibleInt_BM = new FlexibleInt_BM();
|
||||
|
||||
foreach (AnimatedInt animatedInt in animations)
|
||||
{
|
||||
flexibleInt_BM.animatedIntList.Add(new AnimatedInt(animatedInt.time, animatedInt.value));
|
||||
}
|
||||
|
||||
return flexibleInt_BM;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
[System.Serializable]
|
||||
public class FlexibleInt_BM
|
||||
{
|
||||
public List<AnimatedInt> animatedIntList;
|
||||
|
||||
public FlexibleInt_BM()
|
||||
{
|
||||
this.animatedIntList = new List<AnimatedInt>();
|
||||
}
|
||||
|
||||
public FlexibleInt_BM(List<AnimatedInt> animatedIntList)
|
||||
{
|
||||
this.animatedIntList = animatedIntList;
|
||||
}
|
||||
|
||||
public FlexibleInt ConvertToGameType()
|
||||
{
|
||||
FlexibleInt flexibleInt;
|
||||
|
||||
if (animatedIntList.Count == 0)
|
||||
{
|
||||
flexibleInt = new FlexibleInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AnimatedInt> animations = new List<AnimatedInt>();
|
||||
|
||||
foreach (AnimatedInt animatedInt in animatedIntList)
|
||||
{
|
||||
animations.Add(new AnimatedInt(animatedInt.time, animatedInt.value));
|
||||
}
|
||||
|
||||
flexibleInt = new FlexibleInt(animations);
|
||||
}
|
||||
|
||||
return flexibleInt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
/// <summary>
|
||||
/// 含有颜色属性的次级模块,包括基础颜色(透明度)、发光颜色和发光强度
|
||||
/// </summary>
|
||||
public partial class ColorSubmodule : SubmoduleBase
|
||||
{
|
||||
public Color originalBaseColor;
|
||||
public bool emissionEnabled;
|
||||
public Color originalEmissionColor;
|
||||
public float originalEmissionIntensity;
|
||||
|
||||
public Color currentBaseColor;
|
||||
public Color currentEmissionColor;
|
||||
public float currentEmissionIntensity;
|
||||
|
||||
public bool baseColorDirtyMark;
|
||||
public bool emissionColorDirtyMark;
|
||||
|
||||
public Color GetCurrentEmissionColor()
|
||||
{
|
||||
float intensity = Mathf.Pow(2, currentEmissionIntensity);
|
||||
Color emissionColor = currentEmissionColor * intensity;
|
||||
emissionColor.a = 1;
|
||||
return emissionColor;
|
||||
}
|
||||
|
||||
public ColorSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
|
||||
{
|
||||
this.originalBaseColor = Color.white;
|
||||
this.emissionEnabled = false;
|
||||
this.originalEmissionColor = Color.black;
|
||||
this.originalEmissionIntensity = 0;
|
||||
|
||||
this.currentBaseColor = Color.white;
|
||||
this.currentEmissionColor = Color.black;
|
||||
this.currentEmissionIntensity = 0;
|
||||
|
||||
this.baseColorDirtyMark = false;
|
||||
this.emissionColorDirtyMark = false;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveColorSubmodule).colorSubmodule = this;
|
||||
(attachedGameElement as IHaveColorSubmodule).SetColorObserver();
|
||||
}
|
||||
}
|
||||
|
||||
public ColorSubmodule(GameElement attachedGameElement, Color originalBaseColor) : base(attachedGameElement)
|
||||
{
|
||||
this.originalBaseColor = originalBaseColor;
|
||||
this.emissionEnabled = false;
|
||||
this.originalEmissionColor = Color.black;
|
||||
this.originalEmissionIntensity = 0;
|
||||
|
||||
this.currentBaseColor = originalBaseColor;
|
||||
this.currentEmissionColor = Color.black;
|
||||
this.currentEmissionIntensity = 0;
|
||||
|
||||
this.baseColorDirtyMark = false;
|
||||
this.emissionColorDirtyMark = false;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveColorSubmodule).colorSubmodule = this;
|
||||
(attachedGameElement as IHaveColorSubmodule).SetColorObserver();
|
||||
}
|
||||
}
|
||||
|
||||
public ColorSubmodule(GameElement attachedGameElement, Color originalBaseColor, bool emissionEnabled,
|
||||
Color originalEmissionColor, float originalEmissionIntensity) : base(attachedGameElement)
|
||||
{
|
||||
this.originalBaseColor = originalBaseColor;
|
||||
this.emissionEnabled = emissionEnabled;
|
||||
this.originalEmissionColor = originalEmissionColor;
|
||||
this.originalEmissionIntensity = originalEmissionIntensity;
|
||||
|
||||
this.currentBaseColor = originalBaseColor;
|
||||
this.currentEmissionColor = originalEmissionColor;
|
||||
this.currentEmissionIntensity = originalEmissionIntensity;
|
||||
|
||||
this.baseColorDirtyMark = false;
|
||||
this.emissionColorDirtyMark = false;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveColorSubmodule).colorSubmodule = this;
|
||||
(attachedGameElement as IHaveColorSubmodule).SetColorObserver();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new ColorSubmodule_BM(attachedGameElement);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Color");
|
||||
var subcontainer = container.GenerateSubcontainer(1, 300f);
|
||||
|
||||
if ((attachedGameElement as IHaveColorSubmodule).haveBaseColor)
|
||||
{
|
||||
var baseColor = inspector.GenerateBaseColorPicker(this, subcontainer, "Base Color", nameof(originalBaseColor));
|
||||
baseColor.AddListenerFunction(Refresh);
|
||||
// // 新增:HSV轮盘
|
||||
var hsvDrawer = inspector.GenerateHsvDrawer(this, subcontainer, "HSV", nameof(originalBaseColor));
|
||||
hsvDrawer.AddListenerFunction(Refresh);
|
||||
baseColor.hsvDrawer = hsvDrawer;
|
||||
hsvDrawer.baseColorPicker = baseColor;
|
||||
if (attachedGameElement.childElementList.Exists(x => x is BaseColorChange))
|
||||
{
|
||||
baseColor.title.text += " (Occupied by Animation)";
|
||||
baseColor.canvasGroup.interactable = false;
|
||||
hsvDrawer.title.text += " (Occupied by Animation)";
|
||||
hsvDrawer.gameObject.SetActive(false); // 隐藏HSV轮盘
|
||||
}
|
||||
}
|
||||
|
||||
if ((attachedGameElement as IHaveColorSubmodule).haveEmissionColor)
|
||||
{
|
||||
var emissionColor = inspector.GenerateEmissionColorPicker(this, subcontainer, "Emission Color",
|
||||
nameof(emissionEnabled), nameof(originalEmissionColor), nameof(originalEmissionIntensity));
|
||||
emissionColor.AddListenerFunction(Refresh);
|
||||
|
||||
if (attachedGameElement.childElementList.Exists(x => x is EmissionColorChange))
|
||||
{
|
||||
emissionColor.title.text += " (Occupied by Animation)";
|
||||
emissionColor.canvasGroup.interactable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
currentBaseColor = originalBaseColor;
|
||||
currentEmissionColor = originalEmissionColor;
|
||||
currentEmissionIntensity = originalEmissionIntensity;
|
||||
baseColorDirtyMark = true;
|
||||
emissionColorDirtyMark = true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHaveColorSubmodule
|
||||
{
|
||||
public ColorSubmodule colorSubmodule { get; set; }
|
||||
public virtual bool haveBaseColor => true;
|
||||
public virtual bool haveEmissionColor => false;
|
||||
|
||||
public void SetColorObserver()
|
||||
{
|
||||
GameElement attachedGameElement = colorSubmodule.attachedGameElement;
|
||||
|
||||
Observable.EveryUpdate().Subscribe(_ =>
|
||||
{
|
||||
if (colorSubmodule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool willRefresh = false;
|
||||
|
||||
if (colorSubmodule.baseColorDirtyMark)
|
||||
{
|
||||
//在动画物体中改变currentColor
|
||||
colorSubmodule.baseColorDirtyMark = false;
|
||||
willRefresh = true;
|
||||
}
|
||||
|
||||
if (colorSubmodule.emissionColorDirtyMark)
|
||||
{
|
||||
//在动画物体中改变currentColor
|
||||
colorSubmodule.emissionColorDirtyMark = false;
|
||||
willRefresh = true;
|
||||
}
|
||||
|
||||
if (willRefresh)
|
||||
{
|
||||
attachedGameElement.Refresh();
|
||||
}
|
||||
}).AddTo(attachedGameElement);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class ColorSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public Color originalBaseColor;
|
||||
public bool emissionEnabled;
|
||||
public Color originalEmissionColor;
|
||||
public float originalEmissionIntensity;
|
||||
|
||||
public ColorSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ColorSubmodule_BM(GameElement attachedElement) : base(attachedElement)
|
||||
{
|
||||
ColorSubmodule colorSubmodule = (attachedElement as IHaveColorSubmodule).colorSubmodule;
|
||||
this.originalBaseColor = colorSubmodule.originalBaseColor;
|
||||
this.emissionEnabled = colorSubmodule.emissionEnabled;
|
||||
this.originalEmissionColor = colorSubmodule.originalEmissionColor;
|
||||
this.originalEmissionIntensity = colorSubmodule.originalEmissionIntensity;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attachedElement,
|
||||
originalBaseColor, emissionEnabled, originalEmissionColor, originalEmissionIntensity);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attached,
|
||||
originalBaseColor, emissionEnabled, originalEmissionColor, originalEmissionIntensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class NoteJudgeTriggerSubmodule : SubmoduleBase
|
||||
{
|
||||
public List<NoteBase> connectedNotes;
|
||||
|
||||
public NoteJudgeTriggerSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
|
||||
{
|
||||
connectedNotes = new List<NoteBase>();
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveNoteJudgeTriggerSubmodule).noteJudgeTriggerSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new NoteJudgeTriggerSubmodule_BM(attachedGameElement);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHaveNoteJudgeTriggerSubmodule
|
||||
{
|
||||
public NoteJudgeTriggerSubmodule noteJudgeTriggerSubmodule { get; set; }
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class NoteJudgeTriggerSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public NoteJudgeTriggerSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteJudgeTriggerSubmodule_BM(GameElement attachedElement) : base(attachedElement)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as IHaveNoteJudgeTriggerSubmodule).noteJudgeTriggerSubmodule = new NoteJudgeTriggerSubmodule(attachedElement);
|
||||
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as IHaveNoteJudgeTriggerSubmodule).noteJudgeTriggerSubmodule = new NoteJudgeTriggerSubmodule(attached);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UniRx;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TimeDurationSubmodule : SubmoduleBase
|
||||
{
|
||||
public bool isOverridingDuration; //是否手动设置了时间区间,开启时,子物体的时间区间将被忽略,且在自动计算区间时跳过此模块
|
||||
public float startTime, endTime; //起止时间
|
||||
public IDisposable timeObserver;
|
||||
|
||||
public TimeDurationSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
|
||||
{
|
||||
isOverridingDuration = false;
|
||||
startTime = -32767; //TODO: 换为-delay
|
||||
endTime = 32767; //TODO: 换为songLength
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeDurationSubmodule(GameElement attachedGameElement, bool isOverridingDuration, float startTime, float endTime) :
|
||||
base(attachedGameElement)
|
||||
{
|
||||
this.isOverridingDuration = isOverridingDuration;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckTimeInDuration(float time, float offset = 0.1f)
|
||||
{
|
||||
return time >= startTime - offset && time <= endTime + offset;
|
||||
}
|
||||
|
||||
public void SetDuration(float startTime, float endTime)
|
||||
{
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.isOverridingDuration = true;
|
||||
}
|
||||
|
||||
public void SetDuration(params FlexibleFloat[] flexibleFloats)
|
||||
{
|
||||
List<float> startTimes = new List<float>();
|
||||
List<float> endTimes = new List<float>();
|
||||
|
||||
foreach (FlexibleFloat flexibleFloat in flexibleFloats)
|
||||
{
|
||||
flexibleFloat.Sort();
|
||||
|
||||
if (flexibleFloat.animations.Count > 0)
|
||||
{
|
||||
startTimes.Add(flexibleFloat.animations[0].startTime);
|
||||
endTimes.Add(flexibleFloat.animations[^1].endTime);
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
if (startTimes.Count == 0 || endTimes.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
startTime = startTimes.Min();
|
||||
endTime = endTimes.Max();
|
||||
}
|
||||
|
||||
public void SetDurationFromChildren(List<TimeDurationSubmodule> children)
|
||||
{
|
||||
List<float2> durations = new List<float2>();
|
||||
|
||||
if (children.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var child in children)
|
||||
{
|
||||
durations.Add(new float2(child.startTime, child.endTime));
|
||||
}
|
||||
|
||||
startTime = durations.Min(duration => duration.x);
|
||||
endTime = durations.Max(duration => duration.y);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TimeDurationSubmodule
|
||||
{
|
||||
public void SetUpObserver(UnityAction enableAction, UnityAction disableAction = null)
|
||||
{
|
||||
timeObserver?.Dispose();
|
||||
timeObserver = Observable.EveryUpdate().Subscribe(_ =>
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
if (CheckTimeInDuration(songTime, 0f) && !attachedGameElement.gameObject.activeSelf)
|
||||
{
|
||||
attachedGameElement.gameObject.SetActive(true);
|
||||
enableAction?.Invoke();
|
||||
Debug.Log($"TimeDurationSubmodule: {attachedGameElement.elementName} is active at time {songTime}, duration: [{startTime}, {endTime}]");
|
||||
}
|
||||
else if (!CheckTimeInDuration(songTime, 0f) && attachedGameElement.gameObject.activeSelf)
|
||||
{
|
||||
attachedGameElement.gameObject.SetActive(false);
|
||||
disableAction?.Invoke();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TimeDurationSubmodule
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TimeDurationSubmodule_BM(attachedGameElement);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Time Duration");
|
||||
var subcontainer = container.GenerateSubcontainer(3);
|
||||
var overrideToggle = inspector.GenerateToggle(this, subcontainer, "Override Duration", nameof(isOverridingDuration));
|
||||
var startTimeInputField = inspector.GenerateInputField(this, subcontainer, "Start Time", nameof(startTime));
|
||||
var endTimeInputField = inspector.GenerateInputField(this, subcontainer, "End Time", nameof(endTime));
|
||||
|
||||
void SetInputFieldInteractable(bool interactable)
|
||||
{
|
||||
startTimeInputField.inputField.interactable = interactable;
|
||||
endTimeInputField.inputField.interactable = interactable;
|
||||
}
|
||||
|
||||
SetInputFieldInteractable(isOverridingDuration);
|
||||
overrideToggle.AddListenerFunction(() => SetInputFieldInteractable(isOverridingDuration));
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHaveTimeDurationSubmodule
|
||||
{
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TimeDurationSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public bool isOverridingDuration;
|
||||
public float startTime, endTime;
|
||||
|
||||
public TimeDurationSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TimeDurationSubmodule_BM(GameElement attachedElement) : base(attachedElement)
|
||||
{
|
||||
TimeDurationSubmodule timeDurationSubmodule = (attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule;
|
||||
isOverridingDuration = timeDurationSubmodule.isOverridingDuration;
|
||||
startTime = timeDurationSubmodule.startTime;
|
||||
endTime = timeDurationSubmodule.endTime;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attachedElement, isOverridingDuration, startTime, endTime);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attached, isOverridingDuration, startTime, endTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UniRx;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class TransformSubmodule : SubmoduleBase
|
||||
{
|
||||
public Vector3 originalPosition;
|
||||
public Vector3 originalEulerAngles;
|
||||
public Vector3 originalScale;
|
||||
|
||||
public Vector3 positionOffset;
|
||||
public Vector3 eulerAnglesOffset;
|
||||
public Vector3 scaleOffset;
|
||||
|
||||
public Vector3 currentPosition;
|
||||
public Vector3 currentEulerAngles;
|
||||
public Vector3 currentScale;
|
||||
|
||||
public bool positionDirtyMark;
|
||||
public bool eulerAnglesDirtyMark;
|
||||
public bool scaleDirtyMark;
|
||||
|
||||
public LookAt lookAt;
|
||||
public bool eulerAnglesOffsetLock;
|
||||
|
||||
public TransformSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
|
||||
{
|
||||
this.originalPosition = Vector3.zero;
|
||||
this.originalEulerAngles = Vector3.zero;
|
||||
this.originalScale = Vector3.one;
|
||||
|
||||
positionOffset = Vector3.zero;
|
||||
eulerAnglesOffset = Vector3.zero;
|
||||
scaleOffset = Vector3.zero;
|
||||
|
||||
currentPosition = Vector3.zero;
|
||||
currentEulerAngles = Vector3.zero;
|
||||
currentScale = Vector3.one;
|
||||
|
||||
positionDirtyMark = true;
|
||||
eulerAnglesDirtyMark = true;
|
||||
scaleDirtyMark = true;
|
||||
|
||||
eulerAnglesOffsetLock = false;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveTransformSubmodule).transformSubmodule = this;
|
||||
(attachedGameElement as IHaveTransformSubmodule).SetTransformObserver();
|
||||
}
|
||||
}
|
||||
|
||||
public TransformSubmodule(GameElement attachedGameElement,
|
||||
Vector3 originalPosition, Vector3 originalEulerAngles, Vector3 originalScale) : base(attachedGameElement)
|
||||
{
|
||||
this.originalPosition = originalPosition;
|
||||
this.originalEulerAngles = originalEulerAngles;
|
||||
this.originalScale = originalScale;
|
||||
|
||||
positionOffset = Vector3.zero;
|
||||
eulerAnglesOffset = Vector3.zero;
|
||||
scaleOffset = Vector3.zero;
|
||||
|
||||
currentPosition = originalPosition;
|
||||
currentEulerAngles = originalEulerAngles;
|
||||
currentScale = originalScale;
|
||||
|
||||
positionDirtyMark = true;
|
||||
eulerAnglesDirtyMark = true;
|
||||
scaleDirtyMark = true;
|
||||
|
||||
eulerAnglesOffsetLock = false;
|
||||
|
||||
attachedGameElement.transform.localScale = currentScale;
|
||||
attachedGameElement.transform.localEulerAngles = currentEulerAngles;
|
||||
attachedGameElement.transform.localPosition = currentPosition;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
(attachedGameElement as IHaveTransformSubmodule).transformSubmodule = this;
|
||||
(attachedGameElement as IHaveTransformSubmodule).SetTransformObserver();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TransformSubmodule_BM(attachedGameElement);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Transform");
|
||||
var subcontainer = container.GenerateSubcontainer(1);
|
||||
var originalPosInputField =
|
||||
inspector.GenerateVector3InputField(this, subcontainer, "Start Position", nameof(originalPosition), true);
|
||||
var originalRotInputField =
|
||||
inspector.GenerateVector3InputField(this, subcontainer, "Start Rotation", nameof(originalEulerAngles), true);
|
||||
var originalScaleInputField =
|
||||
inspector.GenerateVector3InputField(this, subcontainer, "Start Scale", nameof(originalScale), true);
|
||||
var currentPosText =
|
||||
inspector.GenerateParameterText(this, subcontainer, "Current Position", nameof(currentPosition), true);
|
||||
var currentRotText =
|
||||
inspector.GenerateParameterText(this, subcontainer, "Current Rotation", nameof(currentEulerAngles), true);
|
||||
|
||||
if (attachedGameElement is PathNode or Trail) // 如果是PathNode,显示法线方向
|
||||
{
|
||||
var currentNormalText =
|
||||
inspector.GenerateHintText(this, subcontainer, () => "Normal: " + attachedGameElement.transform.forward);
|
||||
}
|
||||
|
||||
var currentScaleText =
|
||||
inspector.GenerateParameterText(this, subcontainer, "Current Scale", nameof(currentScale), true);
|
||||
|
||||
originalPosInputField.AddListenerFunction(Refresh);
|
||||
originalRotInputField.AddListenerFunction(Refresh);
|
||||
originalScaleInputField.AddListenerFunction(Refresh);
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
positionDirtyMark = true;
|
||||
eulerAnglesDirtyMark = true;
|
||||
scaleDirtyMark = true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHaveTransformSubmodule
|
||||
{
|
||||
TransformSubmodule transformSubmodule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置物体Transform的监听,顺序为Scale -> EulerAngles -> Position
|
||||
/// 如果有一些特殊的物体(例如Camera,ElementFolder),需要自定义监听,可以重写这个方法
|
||||
/// </summary>
|
||||
public void SetTransformObserver()
|
||||
{
|
||||
GameElement attachedGameElement = transformSubmodule.attachedGameElement;
|
||||
|
||||
Observable.EveryUpdate().Subscribe(_ =>
|
||||
{
|
||||
if (transformSubmodule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool willRefresh = false;
|
||||
|
||||
if (transformSubmodule.scaleDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentScale = transformSubmodule.originalScale + transformSubmodule.scaleOffset;
|
||||
attachedGameElement.transform.localScale = transformSubmodule.currentScale;
|
||||
transformSubmodule.scaleDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.scaleOffset = Vector3.zero;
|
||||
}
|
||||
|
||||
if (!transformSubmodule.eulerAnglesOffsetLock && transformSubmodule.eulerAnglesDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + transformSubmodule.eulerAnglesOffset;
|
||||
attachedGameElement.transform.localEulerAngles = transformSubmodule.currentEulerAngles;
|
||||
transformSubmodule.eulerAnglesDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.eulerAnglesOffset = Vector3.zero;
|
||||
}
|
||||
|
||||
if (transformSubmodule.positionDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentPosition = transformSubmodule.originalPosition + transformSubmodule.positionOffset;
|
||||
attachedGameElement.transform.localPosition = transformSubmodule.currentPosition;
|
||||
transformSubmodule.positionDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.positionOffset = Vector3.zero;
|
||||
}
|
||||
|
||||
if (willRefresh)
|
||||
{
|
||||
attachedGameElement.Refresh();
|
||||
}
|
||||
|
||||
}).AddTo(attachedGameElement);
|
||||
}
|
||||
|
||||
public void UpdateLookAt(LookAt lookAt) // 处理LookAt
|
||||
{
|
||||
Transform target = lookAt.lookAtObject.transform;
|
||||
Transform self = transformSubmodule.attachedGameElement.transform;
|
||||
|
||||
if (transformSubmodule.eulerAnglesOffsetLock && transformSubmodule.eulerAnglesDirtyMark)
|
||||
{
|
||||
Vector3 lookingDirection = (target.position - self.position).normalized;
|
||||
|
||||
Vector3 eulerAnglesOffset = Quaternion.LookRotation(lookingDirection).eulerAngles;
|
||||
|
||||
transformSubmodule.eulerAnglesOffset += eulerAnglesOffset;
|
||||
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + transformSubmodule.eulerAnglesOffset;
|
||||
|
||||
self.localEulerAngles = transformSubmodule.currentEulerAngles;
|
||||
|
||||
transformSubmodule.eulerAnglesDirtyMark = false;
|
||||
transformSubmodule.eulerAnglesOffsetLock = false;
|
||||
transformSubmodule.eulerAnglesOffset = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TransformSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public Vector3 originalPosition;
|
||||
public Vector3 originalEulerAngles;
|
||||
public Vector3 originalScale;
|
||||
|
||||
public TransformSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TransformSubmodule_BM(GameElement attachedElement) : base(attachedElement)
|
||||
{
|
||||
TransformSubmodule transformSubmodule = (attachedElement as IHaveTransformSubmodule).transformSubmodule;
|
||||
this.originalPosition = transformSubmodule.originalPosition;
|
||||
this.originalEulerAngles = transformSubmodule.originalEulerAngles;
|
||||
this.originalScale = transformSubmodule.originalScale;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as IHaveTransformSubmodule).transformSubmodule = new TransformSubmodule(attachedElement, originalPosition, originalEulerAngles, originalScale);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as IHaveTransformSubmodule).transformSubmodule = new TransformSubmodule(attached, originalPosition, originalEulerAngles, originalScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Ichni
|
||||
{
|
||||
public class PooledObject : MonoBehaviour, IPoolable
|
||||
{
|
||||
public UnityAction onSpawn;
|
||||
public UnityAction onDespawn;
|
||||
|
||||
public void OnSpawn()
|
||||
{
|
||||
onSpawn?.Invoke();
|
||||
}
|
||||
|
||||
public void OnDespawn()
|
||||
{
|
||||
onDespawn?.Invoke();
|
||||
}
|
||||
|
||||
public void SetOnSpawn(UnityAction action, bool isOverride = false, bool isAdditive = false)
|
||||
{
|
||||
if (isOverride)
|
||||
{
|
||||
onSpawn = action;
|
||||
}
|
||||
else if (isAdditive)
|
||||
{
|
||||
onSpawn += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
onSpawn ??= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOnDespawn(UnityAction action, bool isOverride = false, bool isAdditive = false)
|
||||
{
|
||||
if (isOverride)
|
||||
{
|
||||
onDespawn = action;
|
||||
}
|
||||
else if (isAdditive)
|
||||
{
|
||||
onDespawn += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
onDespawn ??= action;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6ba0e915cddec743a29f85a93f12594
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,203 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Beatmap;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class BeatmapContainer : IBaseElement, IBeChangeInExport
|
||||
{
|
||||
public List<GameElement> gameElementList;
|
||||
|
||||
[NonSerialized]
|
||||
public List<UnityAction> lowPriorityActions;
|
||||
|
||||
public BaseElement_BM matchedBM { get; set; }
|
||||
public BaseElement_BM MatchingExportElement { get; set; }
|
||||
|
||||
public BeatmapContainer()
|
||||
{
|
||||
gameElementList = new List<GameElement>();
|
||||
lowPriorityActions = new List<UnityAction>();
|
||||
Observable.EveryUpdate().Subscribe(_ => ExecuteLowPriorityActions());
|
||||
}
|
||||
|
||||
public void ExecuteLowPriorityActions()
|
||||
{
|
||||
if (lowPriorityActions.Count > 0)
|
||||
{
|
||||
lowPriorityActions.ForEach(low => low.Invoke());
|
||||
lowPriorityActions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveBM()
|
||||
{
|
||||
matchedBM = new BeatmapContainer_BM(gameElementList);
|
||||
}
|
||||
|
||||
public void SetUpInspector()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
public IEnumerator AfterLoadSet()
|
||||
{
|
||||
Trail.FreezeAllTrails(true);
|
||||
foreach (var element in gameElementList)
|
||||
{
|
||||
element.gameObject.SetActive(false);
|
||||
if (element is IHaveTransformSubmodule haveTransform)
|
||||
{
|
||||
TransformSubmodule transformSubmodule = haveTransform.transformSubmodule;
|
||||
foreach (AnimationBase i in element.childElementList.OfType<AnimationBase>())
|
||||
{
|
||||
i.InvokeUpdate();
|
||||
}
|
||||
transformSubmodule.Refresh();
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
foreach (var element in gameElementList)
|
||||
{
|
||||
element.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void SaveExportBM()
|
||||
{
|
||||
MatchingExportElement = new BeatmapContainer_BM(gameElementList, true);
|
||||
if (((BeatmapContainer_BM)MatchingExportElement).elementList.Any(i => i is ICanNotInExport))
|
||||
{
|
||||
Debug.LogError("Export Error!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public partial class BeatmapContainer_BM : BaseElement_BM
|
||||
{
|
||||
public List<BaseElement_BM> elementList;
|
||||
|
||||
|
||||
public BeatmapContainer_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BeatmapContainer_BM(List<GameElement> gameElementList, bool forExport = false)
|
||||
{
|
||||
elementList = new List<BaseElement_BM>();
|
||||
|
||||
gameElementList.ForEach(e =>
|
||||
{
|
||||
e.SaveBM();
|
||||
e.submoduleList.RemoveAll(s => s == null);
|
||||
e.submoduleList.ForEach(s => s.SaveBM());
|
||||
if (forExport && e is IBeChangeInExport changeInExport)
|
||||
{
|
||||
changeInExport.SaveExportBM();
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var gameElement in gameElementList)
|
||||
{
|
||||
if (gameElement.matchedBM != null)
|
||||
{
|
||||
if (forExport && gameElement is IBeChangeInExport changeInExport)
|
||||
{
|
||||
if (changeInExport.MatchingExportElement != null)
|
||||
{
|
||||
elementList.Add(changeInExport.MatchingExportElement);
|
||||
List<BaseElement_BM> submodules = gameElement.submoduleList.ConvertAll(s => s.matchedBM);
|
||||
submodules.RemoveAll(s => s == null);
|
||||
submodules.ForEach(e => { e.attachedElementGuid = ((GameElement_BM)changeInExport.MatchingExportElement).elementGuid; });
|
||||
elementList.AddRange(submodules);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementList.Add(gameElement.matchedBM);
|
||||
List<BaseElement_BM> submodules = gameElement.submoduleList.ConvertAll(s => s.matchedBM);
|
||||
submodules.RemoveAll(s => s == null);
|
||||
elementList.AddRange(submodules);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
EditorManager.instance.beatmapContainer = new BeatmapContainer();
|
||||
EditorManager.instance.beatmapContainer.matchedBM = this;
|
||||
GameElement_BM.identifier.Clear();
|
||||
|
||||
elementList.ForEach(element =>
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
Debug.LogError("Null element detected in elementList. Skipping execution.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (LowPriorityGameElementTypes.Contains(element.GetType()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (element is GameElement_BM gameElement)
|
||||
{
|
||||
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
|
||||
}
|
||||
|
||||
element.ExecuteBM();
|
||||
});
|
||||
|
||||
elementList.ForEach(element =>
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
Debug.LogError("Null element detected in elementList during low-priority execution. Skipping execution.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (LowPriorityGameElementTypes.Contains(element.GetType()))
|
||||
{
|
||||
element.ExecuteBM();
|
||||
}
|
||||
});
|
||||
|
||||
EditorManager.instance.beatmapContainer.ExecuteLowPriorityActions();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BeatmapContainer_BM : BaseElement_BM
|
||||
{
|
||||
public static readonly List<Type> LowPriorityGameElementTypes = new()
|
||||
{
|
||||
//typeof(NoteJudgeSubmodule_BM),
|
||||
};
|
||||
|
||||
public static readonly List<Type> LowPriorityDataTypes = new()
|
||||
{
|
||||
typeof(EnableControlEffect_BM),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class CommandScripts : IBaseElement
|
||||
{
|
||||
List<string> commandList;
|
||||
public BaseElement_BM matchedBM { get; set; }
|
||||
|
||||
public CommandScripts(List<string> commandList)
|
||||
{
|
||||
this.commandList = commandList;
|
||||
}
|
||||
|
||||
public void SaveBM()
|
||||
{
|
||||
matchedBM = new CommandScripts_BM(commandList);
|
||||
}
|
||||
|
||||
public void SetUpInspector()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class CommandScripts_BM : BaseElement_BM
|
||||
{
|
||||
public List<string> commandList;
|
||||
|
||||
public CommandScripts_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public CommandScripts_BM(List<string> commandList)
|
||||
{
|
||||
this.commandList = commandList;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
EditorManager.instance.commandScripts = new CommandScripts(commandList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Assets/Scripts/EditorGame/GameElements/.DS_Store
vendored
BIN
Assets/Scripts/EditorGame/GameElements/.DS_Store
vendored
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56a4c0ac4ed204fcfb16a22f625230cd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,189 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class GameCamera : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule
|
||||
{
|
||||
[FormerlySerializedAs("camera")]
|
||||
public Camera gameCamera;
|
||||
public Transform rotationPoint;
|
||||
public Transform positionPoint;
|
||||
public Transform cameraTransform;
|
||||
|
||||
public CameraViewType cameraViewType;
|
||||
public float perspectiveAngle;
|
||||
public float orthographicSize;
|
||||
|
||||
public TransformSubmodule transformSubmodule { get; set; }
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
private static CameraManager cameraManager => EditorManager.instance.cameraManager;
|
||||
|
||||
public static GameCamera GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement parentElement,
|
||||
CameraViewType cameraViewType, float perspectiveAngle, float orthographicSize)
|
||||
{
|
||||
if (EditorManager.instance.cameraManager.haveGameCamera)
|
||||
{
|
||||
LogWindow.Log("Only one GameCamera can be created", Color.red);
|
||||
return null;
|
||||
}
|
||||
|
||||
GameCamera gameCamera =
|
||||
Instantiate(EditorManager.instance.basePrefabs.gameCamera).GetComponent<GameCamera>();
|
||||
|
||||
gameCamera.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
||||
|
||||
cameraManager.gameCamera = gameCamera;
|
||||
gameCamera.gameCamera.GetComponent<UniversalAdditionalCameraData>().cameraStack.Add(cameraManager.backgroundCamera);
|
||||
if (cameraManager.isSceneCameraActive) gameCamera.gameCamera.enabled = false;
|
||||
|
||||
|
||||
gameCamera.parentElement = parentElement;
|
||||
gameCamera.cameraViewType = cameraViewType;
|
||||
gameCamera.gameCamera.orthographic = cameraViewType == CameraViewType.Orthographic;
|
||||
gameCamera.perspectiveAngle = perspectiveAngle;
|
||||
gameCamera.orthographicSize = orthographicSize;
|
||||
gameCamera.cameraTransform = gameCamera.transform;
|
||||
|
||||
return gameCamera;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
transformSubmodule = new TransformSubmodule(this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Generate");
|
||||
StandardInspectionElement.GenerateForTransform(this, container); //关于有Transform的元素
|
||||
|
||||
var generateAnimation = container.GenerateSubcontainer(3);
|
||||
var fovAnimationButton = inspector.GenerateButton(this, generateAnimation, "Field of View",
|
||||
() => CameraFieldOfView.GenerateElement("New Field of View", Guid.NewGuid(),
|
||||
new List<string>(), true, this, new FlexibleFloat(new List<AnimatedFloat>
|
||||
{
|
||||
new AnimatedFloat(0f, 1f, 60f, 60f, AnimationCurveType.Linear)
|
||||
})));
|
||||
var extensionButton = inspector.GenerateButton(this, generateAnimation, "Extension",
|
||||
() => GameCameraExtension.GenerateElement("New Extension", Guid.NewGuid(),
|
||||
new List<string>(), true, this, 1000f));
|
||||
|
||||
}
|
||||
public override void OnDelete()
|
||||
{
|
||||
if (cameraManager.gameCamera == this)
|
||||
{
|
||||
cameraManager.SwitchCamera();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class GameCamera
|
||||
{
|
||||
public enum CameraViewType
|
||||
{
|
||||
Perspective = 0,
|
||||
Orthographic = 1
|
||||
}
|
||||
}
|
||||
|
||||
public partial class GameCamera
|
||||
{
|
||||
public void SetTransformObserver()
|
||||
{
|
||||
Observable.EveryLateUpdate().Subscribe(_ =>
|
||||
{
|
||||
if (transformSubmodule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool willRefresh = false;
|
||||
|
||||
if (!transformSubmodule.eulerAnglesOffsetLock && transformSubmodule.eulerAnglesDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + transformSubmodule.eulerAnglesOffset;
|
||||
transform.localEulerAngles = transformSubmodule.currentEulerAngles;
|
||||
transformSubmodule.eulerAnglesDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.eulerAnglesOffset = Vector3.zero;
|
||||
}
|
||||
|
||||
if (transformSubmodule.positionDirtyMark)
|
||||
{
|
||||
transformSubmodule.currentPosition = transformSubmodule.originalPosition + transformSubmodule.positionOffset;
|
||||
transform.localPosition = transformSubmodule.currentPosition;
|
||||
transformSubmodule.positionDirtyMark = false;
|
||||
willRefresh = true;
|
||||
transformSubmodule.positionOffset = Vector3.zero;
|
||||
}
|
||||
|
||||
if (willRefresh)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
}).AddTo(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class GameCamera
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new GameCamera_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM, cameraViewType, perspectiveAngle, orthographicSize);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class GameCamera_BM : GameElement_BM
|
||||
{
|
||||
public GameCamera.CameraViewType cameraViewType;
|
||||
public float perspectiveAngle;
|
||||
public float orthographicSize;
|
||||
|
||||
public GameCamera_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameCamera_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, GameCamera.CameraViewType cameraViewType,
|
||||
float perspectiveAngle, float orthographicSize)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.cameraViewType = cameraViewType;
|
||||
this.perspectiveAngle = perspectiveAngle;
|
||||
this.orthographicSize = orthographicSize;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = GameCamera.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), cameraViewType, perspectiveAngle, orthographicSize);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return GameCamera.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent, cameraViewType, perspectiveAngle, orthographicSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class GameCameraExtension : GameElement
|
||||
{
|
||||
public GameCamera gameCamera;
|
||||
public SceneCamera sceneCamera => EditorManager.instance.cameraManager.sceneCamera;
|
||||
|
||||
public float farClipRange = 1000f;
|
||||
|
||||
public static GameCameraExtension GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement parentElement, float farClipRange)
|
||||
{
|
||||
GameCameraExtension gameCameraExtension = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<GameCameraExtension>();
|
||||
gameCameraExtension.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
||||
gameCameraExtension.gameCamera = parentElement as GameCamera;
|
||||
gameCameraExtension.farClipRange = farClipRange;
|
||||
gameCameraExtension.ApplyExtension();
|
||||
return gameCameraExtension;
|
||||
}
|
||||
|
||||
public void ApplyExtension()
|
||||
{
|
||||
gameCamera.gameCamera.farClipPlane = farClipRange;
|
||||
sceneCamera.sceneCamera.farClipPlane = farClipRange;
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Settings");
|
||||
var settingsSubcontainer = container.GenerateSubcontainer(3);
|
||||
var farClipRangeButton = inspector.GenerateInputField(this, settingsSubcontainer, "Far Clip Range",
|
||||
nameof(farClipRange)).AddListenerFunction(ApplyExtension);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class GameCameraExtension
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new GameCameraExtension_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM, farClipRange);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class GameCameraExtension_BM : GameElement_BM
|
||||
{
|
||||
public float farClipRange;
|
||||
|
||||
public GameCameraExtension_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameCameraExtension_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, float farClipRange)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.farClipRange = farClipRange;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = GameCameraExtension.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), farClipRange);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return GameCameraExtension.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent, farClipRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract partial class GameElement : SerializedMonoBehaviour, IBaseElement, IComparable<GameElement>
|
||||
{
|
||||
//物体名
|
||||
public string elementName;
|
||||
|
||||
//标识 GUID
|
||||
public Guid elementGuid;
|
||||
|
||||
//标签
|
||||
public List<string> tags;
|
||||
|
||||
//父游戏物体
|
||||
public GameElement parentElement;
|
||||
|
||||
//与游戏物体连接的Tab
|
||||
public HierarchyTab connectedTab;
|
||||
|
||||
//子物体列表
|
||||
public List<GameElement> childElementList = new List<GameElement>();
|
||||
|
||||
//次级模块
|
||||
public List<SubmoduleBase> submoduleList = new List<SubmoduleBase>();
|
||||
|
||||
//存档类
|
||||
public BaseElement_BM matchedBM { get; set; }
|
||||
|
||||
public virtual int HierarchyPriority => 0;
|
||||
|
||||
/// <summary>
|
||||
/// 首次初始化
|
||||
/// </summary>
|
||||
/// <param name="name">物体名</param>
|
||||
public virtual void Initialize(string name, Guid elementGuid, List<string> tags,
|
||||
bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
this.elementName = name;
|
||||
this.elementGuid = elementGuid;
|
||||
this.tags = tags;
|
||||
EditorManager.instance.beatmapContainer.gameElementList.Add(this);
|
||||
submoduleList = new List<SubmoduleBase>();
|
||||
|
||||
if (isFirstGenerated)
|
||||
{
|
||||
SetDefaultSubmodules();
|
||||
}
|
||||
|
||||
SetParent(parentElement);
|
||||
if (parentElement == null || parentElement.connectedTab != null) EditorManager.instance.uiManager.hierarchy.GenerateTab(this, parentElement);
|
||||
gameObject.name = elementName;
|
||||
//GameManager.beatMapContainer.beatMapElementList.Add(this);
|
||||
//serialNumber = totalSerialNumber++;
|
||||
//SetTransformObserver();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置次级模块
|
||||
/// </summary>
|
||||
public virtual void SetDefaultSubmodules()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void SetEditorSubmodules()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在所有物体生成完毕后,执行的初始化方法
|
||||
/// </summary>
|
||||
public virtual void AfterInitialize()
|
||||
{
|
||||
matchedBM?.AfterExecute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置父物体
|
||||
/// </summary>
|
||||
/// <param name="parentElement">父物体</param>
|
||||
public void SetParent(GameElement parentElement)
|
||||
{
|
||||
if (parentElement != null)
|
||||
{
|
||||
parentElement.childElementList.Add(this);
|
||||
this.parentElement = parentElement;
|
||||
transform.SetParent(parentElement.transform);
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(GameElement other)
|
||||
{
|
||||
return HierarchyPriority.CompareTo(other.HierarchyPriority);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class GameElement //存档,删除,复制,粘贴
|
||||
{
|
||||
public virtual void Refresh()
|
||||
{
|
||||
if (connectedTab != null) connectedTab.tabButtonText.text = this.elementName;
|
||||
gameObject.name = elementName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于生成存档
|
||||
/// </summary>
|
||||
public virtual void SaveBM()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当物体被删除时执行的方法
|
||||
/// </summary>
|
||||
public virtual void OnDelete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 删除物体,包括所有子物体
|
||||
/// </summary>
|
||||
public virtual void Delete()
|
||||
{
|
||||
if (childElementList is { Count: > 0 })
|
||||
{
|
||||
for (int i = 0; i < childElementList.Count; i++)
|
||||
{
|
||||
childElementList[i].Delete(); //删除子GameElement、
|
||||
}
|
||||
}
|
||||
|
||||
OnDelete();
|
||||
|
||||
//LogWindow.Log("Deleted element: " + elementName);
|
||||
|
||||
EditorManager.instance.beatmapContainer.gameElementList.Remove(this); //从保存列表中剔除
|
||||
|
||||
if (connectedTab != null)
|
||||
{
|
||||
Destroy(connectedTab.gameObject);
|
||||
}
|
||||
|
||||
Destroy(gameObject); //销毁
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class GameElement//Editor 专
|
||||
{
|
||||
public class EnableType : IBaseElement
|
||||
{
|
||||
public Type type;
|
||||
public bool enable;
|
||||
|
||||
public BaseElement_BM matchedBM { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
};
|
||||
public List<EnableType> enableTypes;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描childElementList中的类型并加入enableTypes(去重,兼容性好)
|
||||
/// </summary>
|
||||
public void ScanAndAddEnableTypes()
|
||||
{
|
||||
// 初始化enableTypes列表
|
||||
if (enableTypes == null)
|
||||
enableTypes = new List<EnableType>();
|
||||
|
||||
// 记录已存在的类型,避免重复
|
||||
HashSet<Type> existingTypes = new HashSet<Type>();
|
||||
foreach (var et in enableTypes)
|
||||
{
|
||||
if (et != null && et.type != null)
|
||||
existingTypes.Add(et.type);
|
||||
}
|
||||
|
||||
// 遍历所有子元素类型,若未添加则加入enableTypes
|
||||
foreach (var child in childElementList)
|
||||
{
|
||||
var childType = child.GetType();
|
||||
if (!existingTypes.Contains(childType))
|
||||
{
|
||||
enableTypes.Add(new EnableType
|
||||
{
|
||||
type = childType,
|
||||
enable = true
|
||||
});
|
||||
existingTypes.Add(childType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetUpInspector() //被点击时设置第一层Inspector
|
||||
{
|
||||
ScanAndAddEnableTypes();
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Element Info");
|
||||
|
||||
//基础信息
|
||||
var info = container.GenerateSubcontainer(3);
|
||||
var nameInputField = inspector.GenerateInputField(this, info, GetType().Name + "'s Name", nameof(elementName));
|
||||
var guidText = inspector.GenerateParameterText(this, info, "Element GUID", nameof(elementGuid));
|
||||
var tagsListButton = inspector.GenerateButton(this, info, "Tags List", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Tags List", nameof(tags)).SetAsStringList();
|
||||
});
|
||||
|
||||
// 只用反射方式生成enableTypes的UI
|
||||
if (enableTypes != null && enableTypes.Count > 0)
|
||||
{
|
||||
var elcontainer = inspector.GenerateContainer("Enable Children Display");
|
||||
var enableTypeContainer = elcontainer.GenerateSubcontainer(3);
|
||||
var type = enableTypes.GetType().GetGenericArguments()[0];
|
||||
int elcount = 0;
|
||||
for (int idx = 0; idx < enableTypes.Count; idx++)
|
||||
{
|
||||
elcount++;
|
||||
if (elcount > 3)
|
||||
{
|
||||
elcount = 0;
|
||||
enableTypeContainer = elcontainer.GenerateSubcontainer(3);
|
||||
}
|
||||
var et = enableTypes[idx];
|
||||
inspector.GenerateToggle(
|
||||
et,
|
||||
enableTypeContainer,
|
||||
et.type.Name,
|
||||
nameof(et.enable) // 传递字段名字符串
|
||||
);
|
||||
}
|
||||
}
|
||||
//次级模块
|
||||
foreach (var submodule in submoduleList)
|
||||
{
|
||||
submodule.SetUpInspector();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有子GameElement
|
||||
/// </summary>
|
||||
/// <param name="includeThis">是否包括自身</param>
|
||||
public List<GameElement> GetAllGameElementsFromThis(bool includeThis = true)
|
||||
{
|
||||
void GetAllChildrenRecursively(GameElement parent, List<GameElement> elements)
|
||||
{
|
||||
foreach (var child in parent.childElementList)
|
||||
{
|
||||
elements.Add(child);
|
||||
GetAllChildrenRecursively(child, elements);
|
||||
}
|
||||
}
|
||||
|
||||
List<GameElement> gameElements = new List<GameElement> { this };
|
||||
GetAllChildrenRecursively(this, gameElements);
|
||||
|
||||
if (!includeThis) gameElements.Remove(this);
|
||||
|
||||
return gameElements;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据enableTypes筛选子元素(只返回enable为true的类型对应的子元素)
|
||||
/// </summary>
|
||||
public List<GameElement> GetChildrenByTypes()
|
||||
{
|
||||
if (enableTypes == null || enableTypes.Count == 0)
|
||||
return new List<GameElement>();
|
||||
|
||||
var enabledTypes = new HashSet<Type>();
|
||||
foreach (var et in enableTypes)
|
||||
{
|
||||
if (et.enable) enabledTypes.Add(et.type);
|
||||
}
|
||||
// 问题1:只匹配类型本身,不能处理继承关系(如子类/接口)
|
||||
// 问题2:如果childElementList有null元素会抛异常
|
||||
// 问题3:如果enableTypes有重复type,没影响但没必要
|
||||
|
||||
// 更健壮的写法如下(支持继承和接口,避免null):
|
||||
return childElementList.FindAll(child =>
|
||||
child != null && enabledTypes.Any(t => t.IsAssignableFrom(child.GetType()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
[System.Serializable]
|
||||
public abstract class GameElement_BM : BaseElement_BM
|
||||
{
|
||||
[System.NonSerialized]
|
||||
public static Dictionary<Guid, GameElement_BM> identifier = new(); //存档类的标识符
|
||||
|
||||
[System.NonSerialized]
|
||||
public GameElement matchedElement; //存档类对应的游戏物体
|
||||
|
||||
public string elementName;
|
||||
public List<string> tags;
|
||||
public Guid elementGuid;
|
||||
|
||||
public GameElement_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameElement_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement)
|
||||
{
|
||||
this.elementName = elementName;
|
||||
this.elementGuid = elementGuid;
|
||||
this.tags = tags;
|
||||
|
||||
this.attachedElementGuid = attachedElement?.elementGuid ?? Guid.Empty;
|
||||
|
||||
identifier.TryAdd(this.elementGuid, this);
|
||||
}
|
||||
|
||||
public static GameElement_BM GetElementBM(Guid id)
|
||||
{
|
||||
if (identifier.TryGetValue(id, out GameElement_BM element_BM))
|
||||
{
|
||||
return element_BM;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GameElement GetElement(Guid id)
|
||||
{
|
||||
if (identifier.TryGetValue(id, out GameElement_BM element_BM))
|
||||
{
|
||||
return element_BM.matchedElement;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制物体
|
||||
/// </summary>
|
||||
/// <param name="attached">父物体</param>
|
||||
public abstract GameElement DuplicateBM(GameElement attached);
|
||||
|
||||
|
||||
public static List<BaseElement_BM> GetAllAttachedBaseElements(GameElement_BM gameElement, List<BaseElement_BM> clip)
|
||||
{
|
||||
Guid elementGuid = gameElement.elementGuid;
|
||||
List<BaseElement_BM> result = new List<BaseElement_BM>();
|
||||
foreach (BaseElement_BM element in clip)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
|
||||
continue;
|
||||
}
|
||||
if (element.attachedElementGuid == elementGuid)
|
||||
{
|
||||
result.Add(element);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using MoreMountains.Feedbacks;
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class BloomEffect : EffectBase
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public BloomEffect(float duration, float peak, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.bloomEffect).GetComponent<MMF_Player>();
|
||||
effect.GetFeedbackOfType<MMF_Bloom_URP>().ShakeDuration = duration;
|
||||
effect.GetFeedbackOfType<MMF_Bloom_URP>().RemapIntensityOne = peak;
|
||||
effect.GetFeedbackOfType<MMF_Bloom_URP>().ShakeIntensity = intensityCurve;
|
||||
effect.PlayFeedbacks();
|
||||
LeanPool.Despawn(effect.gameObject, duration);
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new BloomEffect_BM(duration, peak, intensityCurve);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Bloom Shake");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var effectTimeField = inspector.GenerateInputField(this, effectSettings, "Bloom Time", nameof(duration));
|
||||
var bloomPeakField = inspector.GenerateInputField(this, effectSettings, "Bloom Peak", nameof(peak));
|
||||
var intensityCurveButton = inspector.GenerateButton(this, effectSettings, "Intensity Curve", () =>
|
||||
{
|
||||
var intensityCurveWindow =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Intensity Curve", nameof(intensityCurve)).SetAsCustomCurve();
|
||||
});
|
||||
SetRemove(effectSettings);
|
||||
|
||||
}
|
||||
|
||||
public override void CopyParametersFrom(EffectBase other)
|
||||
{
|
||||
if (other is BloomEffect o)
|
||||
{
|
||||
this.duration = o.duration;
|
||||
this.peak = o.peak;
|
||||
// 深拷贝曲线,避免引用同一个对象
|
||||
this.intensityCurve = o.intensityCurve != null ? new AnimationCurve(o.intensityCurve.keys) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class BloomEffect_BM : EffectBase_BM
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public BloomEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BloomEffect_BM(float duration, float peak, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new BloomEffect(duration, peak, intensityCurve)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using MoreMountains.Feedbacks;
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class ChromaticAberrationEffect : EffectBase
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public ChromaticAberrationEffect(float duration, float peak, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
public override void CopyParametersFrom(EffectBase other)
|
||||
{
|
||||
if (other is ChromaticAberrationEffect otherEffect)
|
||||
{
|
||||
this.duration = otherEffect.duration;
|
||||
this.peak = otherEffect.peak;
|
||||
this.intensityCurve = otherEffect.intensityCurve != null ? new AnimationCurve(otherEffect.intensityCurve.keys) : null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.chromaticAberrationEffect).GetComponent<MMF_Player>();
|
||||
effect.GetFeedbackOfType<MMF_ChromaticAberration_URP>().Duration = duration;
|
||||
effect.GetFeedbackOfType<MMF_ChromaticAberration_URP>().RemapIntensityOne = peak;
|
||||
effect.GetFeedbackOfType<MMF_ChromaticAberration_URP>().Intensity = intensityCurve;
|
||||
effect.PlayFeedbacks();
|
||||
LeanPool.Despawn(effect.gameObject, duration);
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new ChromaticAberrationEffect_BM(duration, peak, intensityCurve);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Chromatic Aberration");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var effectTimeField = inspector.GenerateInputField(this, effectSettings, "Duration", nameof(duration));
|
||||
var bloomPeakField = inspector.GenerateInputField(this, effectSettings, "Peak Value", nameof(peak));
|
||||
var intensityCurveButton = inspector.GenerateButton(this, effectSettings, "Intensity Curve", () =>
|
||||
{
|
||||
var intensityCurveWindow =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Intensity Curve", nameof(intensityCurve)).SetAsCustomCurve();
|
||||
});
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class ChromaticAberrationEffect_BM : EffectBase_BM
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public ChromaticAberrationEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ChromaticAberrationEffect_BM(float duration, float peak, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new ChromaticAberrationEffect(duration, peak, intensityCurve)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class EnableControlEffect : EffectBase
|
||||
{
|
||||
public GameElement connectedGameElement;
|
||||
public string connectedVariableName;
|
||||
public int enableValue;
|
||||
|
||||
public bool useExpression;
|
||||
public string expression;
|
||||
|
||||
public EnableControlEffect(GameElement connectedGameElement, string connectedVariableName,
|
||||
int enableValue, bool useExpression, string expression)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.connectedGameElement = connectedGameElement;
|
||||
this.connectedVariableName = connectedVariableName;
|
||||
this.enableValue = enableValue;
|
||||
this.useExpression = useExpression;
|
||||
this.expression = expression;
|
||||
}
|
||||
public override void CopyParametersFrom(EffectBase other)
|
||||
{
|
||||
if (other is EnableControlEffect otherEffect)
|
||||
{
|
||||
this.connectedGameElement = otherEffect.connectedGameElement;
|
||||
this.connectedVariableName = otherEffect.connectedVariableName;
|
||||
this.enableValue = otherEffect.enableValue;
|
||||
this.useExpression = otherEffect.useExpression;
|
||||
this.expression = otherEffect.expression;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Recover()
|
||||
{
|
||||
if (connectedGameElement == null) return;
|
||||
|
||||
connectedGameElement.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
if (connectedGameElement == null) return;
|
||||
|
||||
if (!useExpression)
|
||||
{
|
||||
int value = EditorManager.instance.variablesContainer.GetVariable(connectedVariableName);
|
||||
connectedGameElement.gameObject.SetActive(value == enableValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
connectedGameElement.SaveBM();
|
||||
return new EnableControlEffect_BM(connectedGameElement.elementGuid,
|
||||
connectedVariableName, enableValue, useExpression, expression);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Enable Control");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var connectedGameElementInputField = inspector.GenerateInputField(effectSettings, "Game Element Name");
|
||||
var connectGameElementButton = inspector.GenerateButton(this, effectSettings, "Connect Game Element", () =>
|
||||
{
|
||||
connectedGameElement = EditorManager.instance.beatmapContainer.gameElementList
|
||||
.First(e => e.elementName == connectedGameElementInputField.GetValue<string>());
|
||||
|
||||
if (connectedGameElement == null)
|
||||
{
|
||||
LogWindow.Log("Game Element not found.", Color.red);
|
||||
}
|
||||
|
||||
inspectorMain.SetInspector(connectedGameElement);
|
||||
});
|
||||
|
||||
string ShowConnection() => connectedGameElement == null ? "No Game Element Connected" : "Connected With: " + connectedGameElement.elementName;
|
||||
var connectHintText = inspector.GenerateHintText(this, effectSettings, ShowConnection);
|
||||
|
||||
var connectedVariableNameInputField = inspector.GenerateInputField(this, effectSettings, "Connected Variable Name", nameof(connectedVariableName));
|
||||
var enableValueInputField = inspector.GenerateInputField(this, effectSettings, "Enable Value", nameof(enableValue));
|
||||
|
||||
// 自定义表达式暂时不可用
|
||||
var useExpressionToggle = inspector.GenerateToggle(this, effectSettings, "Use Expression", nameof(useExpression));
|
||||
useExpressionToggle.toggle.interactable = false;
|
||||
var expressionInputField = inspector.GenerateInputField(this, effectSettings, "Expression", nameof(expression));
|
||||
expressionInputField.inputField.interactable = false;
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class EnableControlEffect_BM : EffectBase_BM
|
||||
{
|
||||
public Guid connectedGameElementGuid;
|
||||
public string connectedVariableName;
|
||||
public int enableValue;
|
||||
public bool useExpression;
|
||||
public string expression;
|
||||
|
||||
public EnableControlEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EnableControlEffect_BM(Guid connectedGameElementGuid, string connectedVariableName,
|
||||
int enableValue, bool useExpression, string expression)
|
||||
{
|
||||
this.connectedGameElementGuid = connectedGameElementGuid;
|
||||
this.connectedVariableName = connectedVariableName;
|
||||
this.enableValue = enableValue;
|
||||
this.useExpression = useExpression;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new EnableControlEffect(GameElement_BM.GetElement(connectedGameElementGuid), connectedVariableName,
|
||||
enableValue, useExpression, expression)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class PixelateEffect : EffectBase
|
||||
{
|
||||
public float duration;
|
||||
public float bottomX;
|
||||
public float bottomY;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public PixelateEffect(float duration, float bottomX, float bottomY, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = duration;
|
||||
this.duration = duration;
|
||||
this.bottomX = bottomX;
|
||||
this.bottomY = bottomY;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
public override void CopyParametersFrom(EffectBase other)
|
||||
{
|
||||
if (other is PixelateEffect otherEffect)
|
||||
{
|
||||
this.duration = otherEffect.duration;
|
||||
this.bottomX = otherEffect.bottomX;
|
||||
this.bottomY = otherEffect.bottomY;
|
||||
this.intensityCurve = otherEffect.intensityCurve != null ? new AnimationCurve(otherEffect.intensityCurve.keys) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Recover()
|
||||
{
|
||||
EditorManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
|
||||
EditorManager.instance.postProcessingManager.SetFeatureActive(false);
|
||||
}
|
||||
|
||||
public override void Disrupt()
|
||||
{
|
||||
EditorManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
|
||||
EditorManager.instance.postProcessingManager.SetFeatureActive(false);
|
||||
}
|
||||
|
||||
public override void PreExecute()
|
||||
{
|
||||
EditorManager.instance.postProcessingManager.SetFeatureActive(true);
|
||||
EditorManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
float x = Mathf.Lerp(Screen.width, bottomX, intensityCurve.Evaluate(effectProgressPercent));
|
||||
float y = Mathf.Lerp(Screen.height, bottomY, intensityCurve.Evaluate(effectProgressPercent));
|
||||
// Debug.Log(x + ", " + y);
|
||||
|
||||
EditorManager.instance.postProcessingManager.SetPixelateStrength(x, y);
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
EditorManager.instance.postProcessingManager.SetPixelateStrength(Screen.width, Screen.height);
|
||||
EditorManager.instance.postProcessingManager.SetFeatureActive(false);
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new PixelateEffect_BM(duration, bottomX, bottomY, intensityCurve);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Pixelate Effect");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var effectTimeField = inspector.GenerateInputField(this, effectSettings, "Effect Time", nameof(duration));
|
||||
var bottomXField = inspector.GenerateInputField(this, effectSettings, "Bottom X", nameof(bottomX));
|
||||
var bottomYField = inspector.GenerateInputField(this, effectSettings, "Bottom Y", nameof(bottomY));
|
||||
var intensityCurveButton = inspector.GenerateButton(this, effectSettings, "Intensity Curve", () =>
|
||||
{
|
||||
var intensityCurveWindow =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Intensity Curve", nameof(intensityCurve)).SetAsCustomCurve();
|
||||
});
|
||||
|
||||
var clearButton = inspector.GenerateButton(this, effectSettings, "Clear Pixelate", () =>
|
||||
{
|
||||
EditorManager.instance.postProcessingManager.SetFeatureActive(false);
|
||||
});
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class PixelateEffect_BM : EffectBase_BM
|
||||
{
|
||||
public float duration;
|
||||
public float bottomX;
|
||||
public float bottomY;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public PixelateEffect_BM(float duration, float bottomX, float bottomY, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = duration;
|
||||
this.duration = duration;
|
||||
this.bottomX = bottomX;
|
||||
this.bottomY = bottomY;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new PixelateEffect(duration, bottomX, bottomY, intensityCurve)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class RadialBlurEffect : EffectBase
|
||||
{
|
||||
private readonly PostProcessingController nbController;
|
||||
|
||||
public float duration;
|
||||
public int sampleLevel;
|
||||
public float position;
|
||||
public float fadeRange;
|
||||
public float peakIntensity;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public RadialBlurEffect(float duration, int sampleLevel, float position, float fadeRange, float peakIntensity, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = duration;
|
||||
this.duration = duration;
|
||||
this.sampleLevel = sampleLevel;
|
||||
this.position = position;
|
||||
this.fadeRange = fadeRange;
|
||||
this.peakIntensity = peakIntensity;
|
||||
this.intensityCurve = intensityCurve;
|
||||
this.nbController = EditorManager.instance.postProcessingManager.nbController;
|
||||
}
|
||||
|
||||
public override void Recover()
|
||||
{
|
||||
nbController.radialBlurToggle = false;
|
||||
}
|
||||
|
||||
public override void Disrupt()
|
||||
{
|
||||
nbController.radialBlurToggle = false;
|
||||
}
|
||||
|
||||
public override void PreExecute()
|
||||
{
|
||||
nbController.radialBlurToggle = true;
|
||||
nbController.radialBlurSampleCount = sampleLevel;
|
||||
nbController.radialBlurPos = position;
|
||||
nbController.radialBlurRange = fadeRange;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
float intensity = Mathf.Lerp(0, peakIntensity, intensityCurve.Evaluate(effectProgressPercent));
|
||||
nbController.radialBlurIntensity = intensity;
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
nbController.radialBlurToggle = false;
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new RadialBlurEffect_BM(duration, sampleLevel, position, fadeRange, peakIntensity, intensityCurve);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Radial Blur Effect");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var effectTimeField = inspector.GenerateInputField(this, effectSettings, "Effect Time", nameof(duration));
|
||||
var sampleLevelField = inspector.GenerateInputField(this, effectSettings, "Sample Level", nameof(sampleLevel));
|
||||
var positionField = inspector.GenerateInputField(this, effectSettings, "Position", nameof(position));
|
||||
var fadeRangeField = inspector.GenerateInputField(this, effectSettings, "Fade Range", nameof(fadeRange));
|
||||
var peakIntensityField = inspector.GenerateInputField(this, effectSettings, "Peak Intensity", nameof(peakIntensity));
|
||||
var intensityCurveButton = inspector.GenerateButton(this, effectSettings, "Intensity Curve", () =>
|
||||
{
|
||||
var intensityCurveWindow =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Intensity Curve", nameof(intensityCurve)).SetAsCustomCurve();
|
||||
});
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class RadialBlurEffect_BM : EffectBase_BM
|
||||
{
|
||||
public float duration;
|
||||
public int sampleLevel;
|
||||
public float position;
|
||||
public float fadeRange;
|
||||
public float peakIntensity;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public RadialBlurEffect_BM(float duration, int sampleLevel, float position, float fadeRange, float peakIntensity, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = duration;
|
||||
this.duration = duration;
|
||||
this.sampleLevel = sampleLevel;
|
||||
this.position = position;
|
||||
this.fadeRange = fadeRange;
|
||||
this.peakIntensity = peakIntensity;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new RadialBlurEffect(duration, sampleLevel, position, fadeRange, peakIntensity, intensityCurve)
|
||||
{
|
||||
attachedGameElement = attachedGameElement,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class SetIntegerEffect : EffectBase
|
||||
{
|
||||
public string targetVariableName;
|
||||
|
||||
public int targetValue;
|
||||
|
||||
public bool isRandom;
|
||||
public int minValue;
|
||||
public int maxValue;
|
||||
|
||||
public SetIntegerEffect(string targetVariableName, int targetValue, bool isRandom, int minValue, int maxValue)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.targetVariableName = targetVariableName;
|
||||
this.targetValue = targetValue;
|
||||
this.isRandom = isRandom;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
public override void Recover()
|
||||
{
|
||||
EditorManager.instance.variablesContainer.RevertVariable(targetVariableName);
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
EditorManager.instance.variablesContainer.SetVariable(targetVariableName, isRandom ? Random.Range(minValue, maxValue + 1) : targetValue);
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new SetIntegerEffect_BM(targetVariableName, targetValue, isRandom, minValue, maxValue);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Set Integer");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var targetVariableNameInputField = inspector.GenerateInputField(this, effectSettings, "Target Variable Name", nameof(targetVariableName));
|
||||
var targetValueInputField = inspector.GenerateInputField(this, effectSettings, "Target Value", nameof(targetValue));
|
||||
var isRandomToggle = inspector.GenerateToggle(this, effectSettings, "Is Random", nameof(isRandom));
|
||||
var minValueInputField = inspector.GenerateInputField(this, effectSettings, "Min Value", nameof(minValue));
|
||||
var maxValueInputField = inspector.GenerateInputField(this, effectSettings, "Max Value", nameof(maxValue));
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class SetIntegerEffect_BM : EffectBase_BM
|
||||
{
|
||||
public string targetVariableName;
|
||||
public int targetValue;
|
||||
public bool isRandom;
|
||||
public int minValue;
|
||||
public int maxValue;
|
||||
|
||||
public SetIntegerEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SetIntegerEffect_BM(string targetVariableName, int targetValue, bool isRandom, int minValue, int maxValue)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.targetVariableName = targetVariableName;
|
||||
this.targetValue = targetValue;
|
||||
this.isRandom = isRandom;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new SetIntegerEffect(targetVariableName, targetValue, isRandom, minValue, maxValue)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TimeEffectsCollection : GameElement, IHaveTransformSubmodule, IHaveEffectSubmodule
|
||||
{
|
||||
public TransformSubmodule transformSubmodule { get; set; }
|
||||
public EffectSubmodule effectSubmodule { get; set; }
|
||||
public float time; //触发效果的时间
|
||||
|
||||
public static TimeEffectsCollection GenerateElement(string name, Guid guid, List<string> tags,
|
||||
bool isFirstGenerated, GameElement parentElement, float time)
|
||||
{
|
||||
TimeEffectsCollection timeEffectsCollection = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<TimeEffectsCollection>();
|
||||
timeEffectsCollection.Initialize(name, guid, tags, isFirstGenerated, parentElement);
|
||||
timeEffectsCollection.time = time;
|
||||
return timeEffectsCollection;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
transformSubmodule = new TransformSubmodule(this);
|
||||
effectSubmodule = new EffectSubmodule(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
effectSubmodule.effectCollection["Prior"].ForEach(effect => effect.UpdateEffect(time));
|
||||
effectSubmodule.effectCollection["Default"].ForEach(effect => effect.UpdateEffect(time));
|
||||
effectSubmodule.effectCollection["Late"].ForEach(effect => effect.UpdateEffect(time));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TimeEffectsCollection
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TimeEffectsCollection_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Time Effects Collection");
|
||||
var collectionSettings = container.GenerateSubcontainer(3);
|
||||
var timeInputField = inspector.GenerateInputField(this, collectionSettings, "Time", nameof(time));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TimeEffectsCollection_BM : GameElement_BM
|
||||
{
|
||||
public float time;
|
||||
|
||||
public TimeEffectsCollection_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TimeEffectsCollection_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, TimeEffectsCollection timeEffectsCollection)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
time = timeEffectsCollection.time;
|
||||
}
|
||||
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = TimeEffectsCollection.GenerateElement(elementName, Guid.NewGuid(),
|
||||
tags, false, GetElement(attachedElementGuid), time);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return TimeEffectsCollection.GenerateElement(elementName, Guid.NewGuid(),
|
||||
tags, false, attached, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using MoreMountains.Feedbacks;
|
||||
using MoreMountains.FeedbacksForThirdParty;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class VignetteEffect : EffectBase
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public float smoothness;
|
||||
public Color color;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public VignetteEffect(float duration, float peak, float smoothness, Color color, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.smoothness = smoothness;
|
||||
this.color = color;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
public override void CopyParametersFrom(EffectBase other)
|
||||
{
|
||||
if (other is VignetteEffect otherEffect)
|
||||
{
|
||||
this.duration = otherEffect.duration;
|
||||
this.peak = otherEffect.peak;
|
||||
this.smoothness = otherEffect.smoothness;
|
||||
this.color = otherEffect.color;
|
||||
this.intensityCurve = otherEffect.intensityCurve != null ? new AnimationCurve(otherEffect.intensityCurve.keys) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Adjust()
|
||||
{
|
||||
MMF_Player effect = Lean.Pool.LeanPool.Spawn(EditorManager.instance.basePrefabs.vignetteEffect).GetComponent<MMF_Player>();
|
||||
effect.GetFeedbackOfType<MMF_Vignette_URP>().Duration = duration;
|
||||
effect.GetFeedbackOfType<MMF_Vignette_URP>().RemapIntensityOne = peak;
|
||||
effect.GetFeedbackOfType<MMF_Vignette_URP>().Intensity = intensityCurve;
|
||||
if (EditorManager.instance.postProcessingManager.globalVolume.profile.TryGet(out Vignette vignette))
|
||||
{
|
||||
vignette.smoothness.value = smoothness;
|
||||
vignette.color.value = color;
|
||||
}
|
||||
effect.PlayFeedbacks();
|
||||
Lean.Pool.LeanPool.Despawn(effect.gameObject, duration);
|
||||
}
|
||||
|
||||
public override EffectBase_BM ConvertToBM()
|
||||
{
|
||||
return new VignetteEffect_BM(duration, peak, smoothness, color, intensityCurve);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Vignette");
|
||||
var effectSettings = container.GenerateSubcontainer(3);
|
||||
var durationField = inspector.GenerateInputField(this, effectSettings, "Duration", nameof(duration));
|
||||
var peakField = inspector.GenerateInputField(this, effectSettings, "Peak Value", nameof(peak));
|
||||
var smoothnessField = inspector.GenerateInputField(this, effectSettings, "Smoothness", nameof(smoothness));
|
||||
var intensityCurveButton = inspector.GenerateButton(this, effectSettings, "Intensity Curve", () =>
|
||||
{
|
||||
var intensityCurveWindow =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Intensity Curve", nameof(intensityCurve)).SetAsCustomCurve();
|
||||
});
|
||||
|
||||
var colorSettings = container.GenerateSubcontainer(1);
|
||||
var colorField = inspector.GenerateBaseColorPicker(this, colorSettings, "Color", nameof(color));
|
||||
SetRemove(effectSettings);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class VignetteEffect_BM : EffectBase_BM
|
||||
{
|
||||
public float duration;
|
||||
public float peak;
|
||||
public float smoothness;
|
||||
public Color color;
|
||||
public AnimationCurve intensityCurve;
|
||||
|
||||
public VignetteEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public VignetteEffect_BM(float duration, float peak, float smoothness, Color color, AnimationCurve intensityCurve)
|
||||
{
|
||||
this.effectTime = 0;
|
||||
this.duration = duration;
|
||||
this.peak = peak;
|
||||
this.smoothness = smoothness;
|
||||
this.color = color;
|
||||
this.intensityCurve = intensityCurve;
|
||||
}
|
||||
|
||||
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
|
||||
{
|
||||
return new VignetteEffect(duration, peak, smoothness, color, intensityCurve)
|
||||
{
|
||||
attachedGameElement = attachedGameElement
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class BackgroundSetter : GameElement
|
||||
{
|
||||
public bool useSkybox;
|
||||
public string skyboxThemeBundleName;
|
||||
public string skyboxMaterialName;
|
||||
public Material skyboxMaterial;
|
||||
public string backgroundSpriteName;
|
||||
public Sprite backgroundSprite;
|
||||
|
||||
public SkyboxSubsetter skyboxSubsetter;
|
||||
|
||||
public static BackgroundSetter GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, GameElement parentElement, bool useSkybox, string skyboxThemeBundleName,
|
||||
string skyboxMaterialName, string backgroundSpriteName)
|
||||
{
|
||||
if (EditorManager.instance.backgroundSetter != null)
|
||||
{
|
||||
LogWindow.Log("There is already a Background Setter in the scene.", Color.red);
|
||||
return null;
|
||||
}
|
||||
|
||||
BackgroundSetter backgroundSetter = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<BackgroundSetter>();
|
||||
EditorManager.instance.backgroundSetter = backgroundSetter;
|
||||
backgroundSetter.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
||||
backgroundSetter.useSkybox = useSkybox;
|
||||
backgroundSetter.skyboxThemeBundleName = skyboxThemeBundleName;
|
||||
backgroundSetter.skyboxMaterialName = skyboxMaterialName;
|
||||
backgroundSetter.backgroundSpriteName = backgroundSpriteName;
|
||||
return backgroundSetter;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
EditorManager.instance.backgroundController.EnableBackground(!useSkybox);
|
||||
if (useSkybox && skyboxSubsetter == null)
|
||||
{
|
||||
SetSkybox(skyboxThemeBundleName, skyboxMaterialName);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBackgroundSprite(backgroundSpriteName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BackgroundSetter
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new BackgroundSetter_BM(elementName, elementGuid, tags, null,
|
||||
useSkybox, skyboxThemeBundleName, skyboxMaterialName, backgroundSpriteName);
|
||||
}
|
||||
// 新增:用于在 Inspector 中显示的列表数据
|
||||
[HideInInspector] private List<string> themeBundleListForSelection;
|
||||
[HideInInspector] private List<string> skyboxNameListForSelection;
|
||||
private void UpdateSelectionLists()
|
||||
{
|
||||
themeBundleListForSelection = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
||||
skyboxNameListForSelection = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(skyboxThemeBundleName) &&
|
||||
ThemeBundleManager.instance.TryGetThemeBundle(skyboxThemeBundleName, out ThemeBundle themeBundle))
|
||||
{
|
||||
skyboxNameListForSelection = themeBundle.assetList_Material.ConvertAll(x => x.name);
|
||||
}
|
||||
}
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector; // 引用主检查器用于刷新
|
||||
|
||||
var container = inspector.GenerateContainer("Background Setter");
|
||||
var backgroundSettings = container.GenerateSubcontainer(3);
|
||||
|
||||
// 1. 开关
|
||||
var useSkyboxToggle = inspector.GenerateToggle(this, backgroundSettings, "Use Skybox", nameof(useSkybox));
|
||||
|
||||
// 刷新可选列表
|
||||
UpdateSelectionLists();
|
||||
|
||||
// 2. 天空盒资源包下拉框 (同步 SkyboxSubsetter 逻辑)
|
||||
var themeDropdown = inspector.GenerateDropdown(this, backgroundSettings, "Skybox Theme Bundle",
|
||||
themeBundleListForSelection, nameof(skyboxThemeBundleName));
|
||||
|
||||
themeDropdown.AddListenerFunction(() =>
|
||||
{
|
||||
UpdateSelectionLists();
|
||||
inspectorMain.SetInspector(this); // 选择包后刷新 UI 以加载材质列表
|
||||
});
|
||||
|
||||
// 3. 天空盒材质下拉框 (同步 SkyboxSubsetter 逻辑)
|
||||
var materialDropdown = inspector.GenerateDropdown(this, backgroundSettings, "Skybox Material",
|
||||
skyboxNameListForSelection, nameof(skyboxMaterialName));
|
||||
|
||||
if (string.IsNullOrEmpty(skyboxThemeBundleName) || skyboxNameListForSelection.Count == 0)
|
||||
{
|
||||
materialDropdown.dropdown.interactable = false;
|
||||
}
|
||||
|
||||
// 4. 背景图片输入框 (保持原样)
|
||||
var backgroundSpriteField = inspector.GenerateInputField(this, backgroundSettings, "Background Sprite", nameof(backgroundSpriteName));
|
||||
|
||||
// 5. 应用按钮
|
||||
var applyButton = inspector.GenerateButton(this, backgroundSettings, "Apply", Refresh);
|
||||
|
||||
// 控制交互性
|
||||
void SetInputFields(bool value)
|
||||
{
|
||||
themeDropdown.dropdown.interactable = value;
|
||||
materialDropdown.dropdown.interactable = value && !string.IsNullOrEmpty(skyboxThemeBundleName);
|
||||
backgroundSpriteField.inputField.interactable = !value;
|
||||
}
|
||||
|
||||
SetInputFields(useSkybox);
|
||||
|
||||
useSkyboxToggle.AddListenerFunction(() =>
|
||||
{
|
||||
EditorManager.instance.backgroundController.EnableBackground(!useSkybox);
|
||||
SetInputFields(useSkybox);
|
||||
});
|
||||
|
||||
// 生成 Skybox Subsetter 的按钮部分
|
||||
var generateContainer = inspector.GenerateContainer("Advanced Controls");
|
||||
var generateSubContainer = generateContainer.GenerateSubcontainer(3);
|
||||
inspector.GenerateButton(this, generateSubContainer, "Create Skybox Controller", () =>
|
||||
{
|
||||
if (skyboxSubsetter == null)
|
||||
{
|
||||
SkyboxSubsetter.GenerateElement("New Skybox Subsetter", Guid.NewGuid(), new List<string>(), true, this,
|
||||
new List<string>(), new List<string>(), new List<float>(), new List<float>());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWindow.Log("There is already a Skybox Subsetter in the scene.", Color.yellow);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BackgroundSetter
|
||||
{
|
||||
private void SetSkybox(string themeBundleName, string materialName)
|
||||
{
|
||||
skyboxThemeBundleName = themeBundleName;
|
||||
skyboxMaterialName = materialName;
|
||||
skyboxMaterial = ThemeBundleManager.instance.GetObject<Material>(themeBundleName, materialName);
|
||||
if (skyboxMaterial == null) skyboxMaterial = EditorManager.instance.basePrefabs.defaultSkyboxMaterial;
|
||||
EditorManager.instance.backgroundController.SetSkybox(skyboxMaterial);
|
||||
}
|
||||
|
||||
private void SetBackgroundSprite(string spriteName)
|
||||
{
|
||||
string path = EditorManager.instance.projectInformation.projectPath + "/Sprites/" + spriteName + ".png";
|
||||
backgroundSprite = ES3.FileExists(path) ? ES3.Load<Sprite>(path) : EditorManager.instance.basePrefabs.defaultBackground;
|
||||
EditorManager.instance.backgroundController.SetBackground(backgroundSprite);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class BackgroundSetter_BM : GameElement_BM
|
||||
{
|
||||
public bool useSkybox;
|
||||
public string skyboxThemeBundleName;
|
||||
public string skyboxMaterialName;
|
||||
public string backgroundSpriteName;
|
||||
|
||||
public BackgroundSetter_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BackgroundSetter_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
bool useSkybox, string skyboxThemeBundleName, string skyboxMaterialName, string backgroundSpriteName)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.useSkybox = useSkybox;
|
||||
this.skyboxThemeBundleName = skyboxThemeBundleName;
|
||||
this.skyboxMaterialName = skyboxMaterialName;
|
||||
this.backgroundSpriteName = backgroundSpriteName;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = BackgroundSetter.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), useSkybox, skyboxThemeBundleName, skyboxMaterialName, backgroundSpriteName);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return BackgroundSetter.GenerateElement(elementName, Guid.NewGuid(), tags, false, attached,
|
||||
useSkybox, skyboxThemeBundleName, skyboxMaterialName, backgroundSpriteName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class SkyboxSubsetter : GameElement
|
||||
{
|
||||
public SkyboxBlender skyboxBlender;
|
||||
public List<string> skyBoxThemeBundleList;
|
||||
public List<string> skyboxNameList;
|
||||
public List<Material> skyboxMaterialList;
|
||||
public List<float> blendSpeedList;
|
||||
public List<float> blendTimeList;
|
||||
public int currentSkyboxIndex = 0;
|
||||
|
||||
public List<string> themeBundleListForSelection;
|
||||
public List<string> skyboxNameListForSelection;
|
||||
public string selectedThemeBundle;
|
||||
public string selectedSkybox;
|
||||
|
||||
public static SkyboxSubsetter GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, GameElement parentElement, List<string> themeBundleList, List<string> skyboxList,
|
||||
List<float> blendTimeList, List<float> blendSpeedList)
|
||||
{
|
||||
SkyboxSubsetter skyboxSubsetter = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
|
||||
.AddComponent<SkyboxSubsetter>();
|
||||
EditorManager.instance.backgroundSetter.skyboxSubsetter = skyboxSubsetter;
|
||||
skyboxSubsetter.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
||||
skyboxSubsetter.skyBoxThemeBundleList = themeBundleList;
|
||||
skyboxSubsetter.skyboxNameList = skyboxList;
|
||||
skyboxSubsetter.skyboxMaterialList = new List<Material>();
|
||||
skyboxSubsetter.blendTimeList = blendTimeList;
|
||||
skyboxSubsetter.blendSpeedList = blendSpeedList;
|
||||
skyboxSubsetter.SetUpBlender();
|
||||
skyboxSubsetter.themeBundleListForSelection = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
||||
skyboxSubsetter.skyboxNameListForSelection = new List<string>();
|
||||
skyboxSubsetter.selectedThemeBundle = String.Empty;
|
||||
skyboxSubsetter.selectedSkybox = String.Empty;
|
||||
return skyboxSubsetter;
|
||||
}
|
||||
|
||||
private void SetUpBlender()
|
||||
{
|
||||
skyboxBlender = gameObject.AddComponent<SkyboxBlender>();
|
||||
skyboxBlender.loop = false;
|
||||
skyboxBlender.timeToWait = 0f;
|
||||
skyboxBlender.updateLighting = false;
|
||||
skyboxBlender.updateReflections = false;
|
||||
skyboxBlender.skyboxMaterials = new List<Material>();
|
||||
for (int i = 0; i < skyBoxThemeBundleList.Count; i++)
|
||||
{
|
||||
Material skybox = ThemeBundleManager.instance.GetObject<Material>(skyBoxThemeBundleList[i], skyboxNameList[i]);
|
||||
skyboxMaterialList.Add(skybox);
|
||||
skyboxBlender.skyboxMaterials.Add(skybox);
|
||||
}
|
||||
skyboxBlender.makeFirstMaterialSkybox = true;
|
||||
skyboxBlender.InspectorAndAwakeChanges();
|
||||
}
|
||||
|
||||
private void AddSkybox(string skyboxThemeBundleName, string skyboxObjectName)
|
||||
{
|
||||
Material skybox = ThemeBundleManager.instance.GetObject<Material>(skyboxThemeBundleName, skyboxObjectName);
|
||||
if (skybox != null)
|
||||
{
|
||||
skyBoxThemeBundleList.Add(skyboxThemeBundleName);
|
||||
skyboxNameList.Add(skyboxObjectName);
|
||||
skyboxMaterialList.Add(skybox);
|
||||
skyboxBlender.skyboxMaterials.Add(skybox);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (skyBoxThemeBundleList.Count > 1)
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
float delay = EditorManager.instance.songInformation.delay;
|
||||
float finalTime = EditorManager.instance.songInformation.songLength;
|
||||
|
||||
for (var index = 0; index < blendTimeList.Count + 1; index++)
|
||||
{
|
||||
float startTime = index == 0 ? -delay : blendTimeList[index - 1];
|
||||
float endTime = index >= blendTimeList.Count ? finalTime : blendTimeList[index];
|
||||
if (songTime >= startTime && songTime < endTime && currentSkyboxIndex != index)
|
||||
{
|
||||
bool isSmaller = index < currentSkyboxIndex;
|
||||
currentSkyboxIndex = index;
|
||||
if (currentSkyboxIndex != 0) skyboxBlender.blendSpeed = isSmaller ? 9999f : blendSpeedList[currentSkyboxIndex - 1];
|
||||
skyboxBlender.Blend(currentSkyboxIndex, false);
|
||||
DynamicGI.UpdateEnvironment();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new SkyboxSubsetter_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
skyBoxThemeBundleList, skyboxNameList, blendTimeList, blendSpeedList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新 skyboxMaterialList 和 skyboxBlender.skyboxMaterials,使其与 theme/name 列表同步。
|
||||
/// </summary>
|
||||
public void RefreshSkyboxes()
|
||||
{
|
||||
skyboxMaterialList.Clear();
|
||||
skyboxBlender.skyboxMaterials.Clear();
|
||||
for (int i = 0; i < skyBoxThemeBundleList.Count && i < skyboxNameList.Count; i++)
|
||||
{
|
||||
var mat = ThemeBundleManager.instance.GetObject<Material>(skyBoxThemeBundleList[i], skyboxNameList[i]);
|
||||
skyboxMaterialList.Add(mat);
|
||||
skyboxBlender.skyboxMaterials.Add(mat);
|
||||
}
|
||||
skyboxBlender.InspectorAndAwakeChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SkyboxSubsetter
|
||||
{
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Skybox Subsetter");
|
||||
DynamicUISubcontainer mainSettings = container.GenerateSubcontainer(3);
|
||||
|
||||
var blendSpeedListButton = inspector.GenerateButton(this, mainSettings, "Blend Speed List", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Blend Speed List", nameof(blendSpeedList))
|
||||
.SetAsFloatList();
|
||||
});
|
||||
|
||||
var blendTimeListButton = inspector.GenerateButton(this, mainSettings, "Blend Time List", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Blend Time List", nameof(blendTimeList))
|
||||
.SetAsFloatList();
|
||||
});
|
||||
|
||||
DynamicUISubcontainer materialSettings = container.GenerateSubcontainer(3);
|
||||
// 新增:显示skybox配置情况//这他妈是什么
|
||||
|
||||
|
||||
for (int i = 0; i < (skyBoxThemeBundleList?.Count ?? 0); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
DynamicUISubcontainer Textsettings = container.GenerateSubcontainer(3);
|
||||
// 安全访问元素:检查索引是否在所有列表的有效范围内
|
||||
string bundleName = i < skyBoxThemeBundleList.Count ? skyBoxThemeBundleList[i] : "<Missing Bundle>";
|
||||
string name = i < skyboxNameList.Count ? skyboxNameList[i] : "<Missing Name>";
|
||||
if (i > 0)
|
||||
{
|
||||
inspector.GenerateInputField(this, Textsettings, "Time", $"{nameof(blendTimeList)}.{i - 1}");
|
||||
inspector.GenerateInputField(this, Textsettings, "Speed", $"{nameof(blendSpeedList)}.{i - 1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
inspector.GenerateHintText(this, Textsettings, "The First");
|
||||
inspector.GenerateHintText(this, Textsettings, "0");
|
||||
}
|
||||
|
||||
inspector.GenerateHintText(this, Textsettings, $"{i + 1}. {name}");
|
||||
|
||||
|
||||
// inspector.GenerateInputField(this, Textsettings, "B", $"skyBoxThemeBundleList.{i}").AddListenerFunction(RefreshSkyboxes);
|
||||
// inspector.GenerateInputField(this, Textsettings, "N", $"skyboxNameList.{i}").AddListenerFunction(RefreshSkyboxes);
|
||||
inspector.GenerateDropdown(this, Textsettings, "B", themeBundleListForSelection, $"{nameof(skyBoxThemeBundleList)}.{i}")
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
List<string> skyboxNameListForSelection = new List<string>();
|
||||
string selectedThemeBundleL = skyBoxThemeBundleList[i];
|
||||
if (selectedThemeBundleL != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(selectedThemeBundleL, out ThemeBundle themeBundleLoop))
|
||||
{
|
||||
skyboxNameListForSelection = themeBundleLoop.assetList_Material.ConvertAll(x => x.name);
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, Textsettings, "Material Name", skyboxNameListForSelection, $"{nameof(skyboxNameList)}.{i}")
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this))
|
||||
.AddListenerFunction(RefreshSkyboxes);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// var objectNameDropdown =
|
||||
// inspector.GenerateDropdown(this, Textsettings, "Material Name", new List<string>(), $"{nameof(skyboxNameList)}.{i}");
|
||||
// objectNameDropdown.dropdown.interactable = false;
|
||||
// } // 如果没有选择主题包,则材质名称下拉框不可用
|
||||
// inspector.GenerateDropdown(this, Textsettings, "N", skyboxNameListForSelection, $"skyboxNameList.{i}")
|
||||
// .AddListenerFunction(RefreshSkyboxes);
|
||||
|
||||
// 创建局部变量解决闭包问题
|
||||
int index = i;
|
||||
|
||||
inspector.GenerateButton(this, Textsettings, "Remove Skybox", () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 移除前检查所有列表的索引有效性
|
||||
if (index < skyBoxThemeBundleList.Count)
|
||||
skyBoxThemeBundleList.RemoveAt(index);
|
||||
else
|
||||
Debug.LogError($"Cannot remove: skyBoxThemeBundleList index {index} out of range");
|
||||
|
||||
if (index < skyboxNameList.Count)
|
||||
skyboxNameList.RemoveAt(index);
|
||||
else
|
||||
Debug.LogError($"Cannot remove: skyboxNameList index {index} out of range");
|
||||
|
||||
if (index < skyboxMaterialList.Count)
|
||||
skyboxMaterialList.RemoveAt(index);
|
||||
else
|
||||
Debug.LogError($"Cannot remove: skyboxMaterialList index {index} out of range");
|
||||
|
||||
if (index < skyboxBlender.skyboxMaterials.Count)
|
||||
skyboxBlender.skyboxMaterials.RemoveAt(index);
|
||||
else
|
||||
Debug.LogError($"Cannot remove: skyboxMaterials index {index} out of range");
|
||||
|
||||
inspectorMain.SetInspector(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error during removal: {ex.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"Error generating UI for index {i}: {ex.Message}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Debug.Log((mainSettings == null) + " " + (themeBundleListForSelection == null) + " " + (selectedThemeBundle == null));
|
||||
var themeBundleDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Theme Bundle", themeBundleListForSelection, nameof(selectedThemeBundle))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
|
||||
if (selectedThemeBundle != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(selectedThemeBundle, out ThemeBundle themeBundle))
|
||||
{
|
||||
skyboxNameListForSelection = themeBundle.assetList_Material.ConvertAll(x => x.name);
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Material Name", skyboxNameListForSelection, nameof(selectedSkybox))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Material Name", new List<string>(), nameof(selectedSkybox));
|
||||
objectNameDropdown.dropdown.interactable = false;
|
||||
} // 如果没有选择主题包,则材质名称下拉框不可用
|
||||
|
||||
var setMaterialButton = inspector.GenerateButton(this, materialSettings, "Add Skybox", () =>
|
||||
{
|
||||
AddSkybox(selectedThemeBundle, selectedSkybox);
|
||||
inspectorMain.SetInspector(this);
|
||||
|
||||
});
|
||||
|
||||
if (selectedThemeBundle == String.Empty || selectedSkybox == String.Empty)
|
||||
{
|
||||
setMaterialButton.button.interactable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class SkyboxSubsetter_BM : GameElement_BM
|
||||
{
|
||||
public List<string> skyBoxThemeBundleList;
|
||||
public List<string> skyboxNameList;
|
||||
public List<float> blendTimeList;
|
||||
public List<float> blendSpeedList;
|
||||
|
||||
public SkyboxSubsetter_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SkyboxSubsetter_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
List<string> skyBoxThemeBundleList, List<string> skyboxNameList, List<float> blendTimeList, List<float> blendSpeedList)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.skyBoxThemeBundleList = skyBoxThemeBundleList;
|
||||
this.skyboxNameList = skyboxNameList;
|
||||
this.blendTimeList = blendTimeList;
|
||||
this.blendSpeedList = blendSpeedList;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = SkyboxSubsetter.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), skyBoxThemeBundleList, skyboxNameList, blendTimeList, blendSpeedList);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return SkyboxSubsetter.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
attached, skyBoxThemeBundleList, skyboxNameList, blendTimeList, blendSpeedList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class VariablesContainer : GameElement
|
||||
{
|
||||
public Dictionary<string, int> originalVariables;
|
||||
public Dictionary<string, int> currentVariables;
|
||||
|
||||
public static VariablesContainer GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement parentElement, Dictionary<string, int> variables)
|
||||
{
|
||||
if (EditorManager.instance.variablesContainer != null)
|
||||
{
|
||||
LogWindow.Log("There is already a Variables Container in the scene.", Color.red);
|
||||
return null;
|
||||
}
|
||||
|
||||
VariablesContainer variablesContainer =
|
||||
Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<VariablesContainer>();
|
||||
|
||||
EditorManager.instance.variablesContainer = variablesContainer;
|
||||
variablesContainer.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
||||
variablesContainer.originalVariables = new Dictionary<string, int>(variables);
|
||||
variablesContainer.currentVariables = new Dictionary<string, int>(variables);
|
||||
|
||||
return variablesContainer;
|
||||
}
|
||||
|
||||
public void SetVariable(string variableName, int value)
|
||||
{
|
||||
currentVariables[variableName] = value;
|
||||
}
|
||||
|
||||
public int GetVariable(string variableName)
|
||||
{
|
||||
return currentVariables[variableName];
|
||||
}
|
||||
|
||||
public void RevertVariable(string variableName)
|
||||
{
|
||||
currentVariables[variableName] = originalVariables[variableName];
|
||||
}
|
||||
|
||||
public void RevertAllVariables()
|
||||
{
|
||||
currentVariables = new Dictionary<string, int>(originalVariables);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class VariablesContainer
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new VariablesContainer_BM(elementName, elementGuid, tags, null, originalVariables);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Variables Container");
|
||||
var subcontainer = container.GenerateSubcontainer(3);
|
||||
var originalVariablesButton = inspector.GenerateButton(this, subcontainer, "Original Variables", () =>
|
||||
{
|
||||
var ov =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Original Variables List", nameof(originalVariables))
|
||||
.SetAsStringIntDictionary()
|
||||
.AddListenerFunction(RevertAllVariables);
|
||||
});
|
||||
var currentVariablesButton = inspector.GenerateButton(this, subcontainer, "Current Variables", () =>
|
||||
{
|
||||
var cv =
|
||||
inspector.GenerateCompositeParameterWindow(this, "Current Variables List", nameof(currentVariables))
|
||||
.SetAsStringIntDictionary();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class VariablesContainer_BM : GameElement_BM
|
||||
{
|
||||
public Dictionary<string, int> originalVariables;
|
||||
|
||||
public VariablesContainer_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public VariablesContainer_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM parentElement,
|
||||
Dictionary<string, int> originalVariables) : base(elementName, elementGuid, tags, parentElement)
|
||||
{
|
||||
this.originalVariables = new Dictionary<string, int>(originalVariables);
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = VariablesContainer.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), originalVariables);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return VariablesContainer.GenerateElement(elementName, Guid.NewGuid(), tags, false, attached, originalVariables);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3635ae4e7b31f4ae7a942151377c59f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class NoteAudioSubmodule : SubmoduleBase
|
||||
{
|
||||
public List<string> generalJudgeAudioList;
|
||||
public List<string> perfectAudioList;
|
||||
public List<string> goodAudioList;
|
||||
public List<string> badAudioList;
|
||||
public List<string> missAudioList;
|
||||
public List<string> holdStartAudioList;
|
||||
|
||||
private NoteBase note => attachedGameElement as NoteBase;
|
||||
|
||||
public NoteAudioSubmodule(NoteBase attachedGameElement, string defaultAudio) : base(attachedGameElement)
|
||||
{
|
||||
generalJudgeAudioList = new List<string>();
|
||||
perfectAudioList = new List<string>();
|
||||
goodAudioList = new List<string>();
|
||||
badAudioList = new List<string>();
|
||||
missAudioList = new List<string>();
|
||||
holdStartAudioList = new List<string>();
|
||||
|
||||
generalJudgeAudioList.Add(defaultAudio);
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.noteAudioSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public NoteAudioSubmodule(NoteBase attachedGameElement, List<string> generalJudgeAudioList,
|
||||
List<string> perfectAudioList, List<string> goodAudioList, List<string> badAudioList,
|
||||
List<string> missAudioList, List<string> holdStartAudioList) : base(attachedGameElement)
|
||||
{
|
||||
this.generalJudgeAudioList = generalJudgeAudioList;
|
||||
this.perfectAudioList = perfectAudioList;
|
||||
this.goodAudioList = goodAudioList;
|
||||
this.badAudioList = badAudioList;
|
||||
this.missAudioList = missAudioList;
|
||||
this.holdStartAudioList = holdStartAudioList ?? new List<string>();
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.noteAudioSubmodule = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class NoteAudioSubmodule
|
||||
{
|
||||
public void PlayHoldStartAudio()
|
||||
{
|
||||
PlayAudio(holdStartAudioList);
|
||||
}
|
||||
|
||||
public void PlayNoteJudgeAudios(NoteBase.NoteJudgeType judgeType)
|
||||
{
|
||||
PlayAudio(generalJudgeAudioList);
|
||||
|
||||
switch (judgeType)
|
||||
{
|
||||
case NoteBase.NoteJudgeType.Perfect:
|
||||
PlayAudio(perfectAudioList);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Good:
|
||||
PlayAudio(goodAudioList);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Bad:
|
||||
PlayAudio(badAudioList);
|
||||
break;
|
||||
case NoteBase.NoteJudgeType.Miss:
|
||||
PlayAudio(missAudioList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayAudio(List<string> audioList)
|
||||
{
|
||||
foreach (var audio in audioList)
|
||||
{
|
||||
if (EditorManager.instance.noteAudioCollection.audioClips.TryGetValue(audio, out AudioClip clip))
|
||||
{
|
||||
AudioExtension.PlayClipAtPoint2D(clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public partial class NoteAudioSubmodule
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new NoteAudioSubmodule_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Audio Submodule");
|
||||
var submoduleSettings = container.GenerateSubcontainer(3);
|
||||
var generalJudgeAudioListButton = inspector.GenerateButton(this, submoduleSettings, "General Judge", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "General Judge Sound List", nameof(generalJudgeAudioList)).SetAsStringList();
|
||||
});
|
||||
var perfectAudioListButton = inspector.GenerateButton(this, submoduleSettings, "Perfect", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Perfect Sound List", nameof(perfectAudioList)).SetAsStringList();
|
||||
});
|
||||
var goodAudioListButton = inspector.GenerateButton(this, submoduleSettings, "Good", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Good Sound List", nameof(goodAudioList)).SetAsStringList();
|
||||
});
|
||||
var badAudioListButton = inspector.GenerateButton(this, submoduleSettings, "Bad", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Bad Sound List", nameof(badAudioList)).SetAsStringList();
|
||||
});
|
||||
var missAudioListButton = inspector.GenerateButton(this, submoduleSettings, "Miss", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Miss Sound List", nameof(missAudioList)).SetAsStringList();
|
||||
});
|
||||
if (note is Hold)
|
||||
{
|
||||
var holdStartAudioListButton = inspector.GenerateButton(this, submoduleSettings, "Hold Start", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Hold Start Sound List", nameof(holdStartAudioList)).SetAsStringList();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class NoteAudioSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public List<string> generalJudgeAudioList;
|
||||
public List<string> perfectAudioList;
|
||||
public List<string> goodAudioList;
|
||||
public List<string> badAudioList;
|
||||
public List<string> missAudioList;
|
||||
public List<string> holdStartAudioList;
|
||||
|
||||
public NoteAudioSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteAudioSubmodule_BM(GameElement attachedElement, NoteAudioSubmodule noteAudioSubmodule) : base(attachedElement)
|
||||
{
|
||||
generalJudgeAudioList = noteAudioSubmodule.generalJudgeAudioList;
|
||||
perfectAudioList = noteAudioSubmodule.perfectAudioList;
|
||||
goodAudioList = noteAudioSubmodule.goodAudioList;
|
||||
badAudioList = noteAudioSubmodule.badAudioList;
|
||||
missAudioList = noteAudioSubmodule.missAudioList;
|
||||
holdStartAudioList = noteAudioSubmodule.holdStartAudioList;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as NoteBase).noteAudioSubmodule = new NoteAudioSubmodule(attachedElement as NoteBase,
|
||||
generalJudgeAudioList, perfectAudioList, goodAudioList, badAudioList, missAudioList, holdStartAudioList);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as NoteBase).noteAudioSubmodule = new NoteAudioSubmodule(attached as NoteBase,
|
||||
generalJudgeAudioList, perfectAudioList, goodAudioList, badAudioList, missAudioList, holdStartAudioList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class FullScreenNearTimeJudgeUnit : NoteJudgeUnit
|
||||
{
|
||||
protected override GameObject GetHintImagePrefab() => EditorManager.instance.basePrefabs.fullscreenNearTimeHint;
|
||||
|
||||
public FullScreenNearTimeJudgeUnit(NoteBase note) : base(note)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void UpdateJudge()
|
||||
{
|
||||
if (note is Hold hold)
|
||||
{
|
||||
if (hold.isFinalJudged) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (note.isFirstJudged) return;
|
||||
}
|
||||
Vector2 noteScreenPosition = note.noteScreenPosition;
|
||||
RectTransform canvasRect = EditorManager.instance.judgeHintCanvas.GetComponent<RectTransform>();
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, noteScreenPosition, null, out Vector2 uiPosition))
|
||||
{
|
||||
judgeHintImage.anchoredPosition = uiPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Full Screen Near Time Judge Unit");
|
||||
var judgeModuleSettings = container.GenerateSubcontainer(3);
|
||||
var isShowingJudgeField =
|
||||
inspector.GenerateToggle(this, judgeModuleSettings, "Is Showing Judge", nameof(isShowingJudge))
|
||||
.AddListenerFunction(() => SetShowingJudge(isShowingJudge));
|
||||
var removeButton = inspector.GenerateButton(this, judgeModuleSettings, "Remove", () =>
|
||||
{
|
||||
SetShowingJudge(false);
|
||||
note.noteJudgeSubmodule.judgeUnitList.Remove(this);
|
||||
inspectorMain.SetInspector(note);
|
||||
});
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit_BM ConvertToBM()
|
||||
{
|
||||
return new FullScreenNearTimeJudgeUnit_BM();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class FullScreenNearTimeJudgeUnit_BM : NoteJudgeUnit_BM
|
||||
{
|
||||
public FullScreenNearTimeJudgeUnit_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit ConvertToGameType(NoteBase attachedNote)
|
||||
{
|
||||
return new FullScreenNearTimeJudgeUnit(attachedNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class NoteJudgeSubmodule : SubmoduleBase
|
||||
{
|
||||
public List<NoteJudgeUnit> judgeUnitList;
|
||||
private NoteBase note => attachedGameElement as NoteBase;
|
||||
|
||||
public NoteJudgeSubmodule(NoteBase attachedGameElement) : base(attachedGameElement)
|
||||
{
|
||||
judgeUnitList = new List<NoteJudgeUnit>();
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.noteJudgeSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public NoteJudgeSubmodule(NoteBase attachedGameElement, List<NoteJudgeUnit_BM> judgeUnitList_BM) : base(attachedGameElement)
|
||||
{
|
||||
judgeUnitList = new List<NoteJudgeUnit>();
|
||||
|
||||
foreach (NoteJudgeUnit_BM judgeUnitBM in judgeUnitList_BM)
|
||||
{
|
||||
judgeUnitList.Add(judgeUnitBM.ConvertToGameType(attachedGameElement));
|
||||
}
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.note.noteJudgeSubmodule = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class NoteJudgeSubmodule
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new NoteJudgeSubmodule_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Judge Submodule");
|
||||
var submoduleSettings = container.GenerateSubcontainer(3);
|
||||
var effectNameInputField = inspector.GenerateInputField(submoduleSettings, "Judge Unit Name");
|
||||
var addJudgeUnitButton = inspector.GenerateButton(this, submoduleSettings, "Add Judge Unit",
|
||||
() =>
|
||||
{
|
||||
AddJudgeUnit(effectNameInputField.GetValue<string>());
|
||||
inspectorMain.SetInspector(note);
|
||||
});
|
||||
|
||||
foreach (var judgeUnit in judgeUnitList)
|
||||
{
|
||||
judgeUnit.SetUpInspector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class NoteJudgeSubmodule
|
||||
{
|
||||
private static Dictionary<string, Func<NoteJudgeUnit>> JudgeUnitCollection(NoteBase note) =>
|
||||
new Dictionary<string, Func<NoteJudgeUnit>>()
|
||||
{
|
||||
{ "TouchArea",()=> new TouchAreaJudgeUnit(note, 600) },
|
||||
{ "FullScreenNearTime",()=> new FullScreenNearTimeJudgeUnit(note) },
|
||||
{ "TriggerConnect",()=> new TriggerConnectJudgeUnit(note, null) }
|
||||
};
|
||||
|
||||
public NoteJudgeUnit AddJudgeUnit(string judgeUnitName)
|
||||
{
|
||||
if (JudgeUnitCollection(note).TryGetValue(judgeUnitName, out var newJudgeUnit))
|
||||
{
|
||||
judgeUnitList.Add(newJudgeUnit());
|
||||
return newJudgeUnit();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWindow.Log("Judge Unit Type not found.", Color.red);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class NoteJudgeSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public List<NoteJudgeUnit_BM> judgeUnitList;
|
||||
|
||||
public NoteJudgeSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteJudgeSubmodule_BM(GameElement attachedElement, NoteJudgeSubmodule noteJudgeSubmodule) : base(attachedElement)
|
||||
{
|
||||
judgeUnitList = new List<NoteJudgeUnit_BM>();
|
||||
|
||||
foreach (var judgeUnit in noteJudgeSubmodule.judgeUnitList)
|
||||
{
|
||||
judgeUnitList.Add(judgeUnit.ConvertToBM());
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
(attachedElement as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attachedElement as NoteBase, judgeUnitList);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
(attached as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attached as NoteBase, judgeUnitList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class TouchAreaJudgeUnit : NoteJudgeUnit
|
||||
{
|
||||
public float areaRadius;
|
||||
protected override GameObject GetHintImagePrefab() => EditorManager.instance.basePrefabs.areaHint;
|
||||
|
||||
private float CurrentScreenRatio() => Screen.height / 1080f;
|
||||
|
||||
public TouchAreaJudgeUnit(NoteBase note, float areaRadius) : base(note)
|
||||
{
|
||||
this.areaRadius = areaRadius;
|
||||
}
|
||||
|
||||
public override void UpdateJudge()
|
||||
{
|
||||
if (note is Hold hold)
|
||||
{
|
||||
if (hold.isFinalJudged) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (note.isFirstJudged) return;
|
||||
}
|
||||
|
||||
Vector2 noteScreenPosition = note.noteScreenPosition;
|
||||
RectTransform canvasRect = EditorManager.instance.judgeHintCanvas.GetComponent<RectTransform>();
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, noteScreenPosition, null, out Vector2 uiPosition))
|
||||
{
|
||||
judgeHintImage.anchoredPosition = uiPosition;
|
||||
judgeHintImage.sizeDelta = new Vector2(areaRadius * 2, areaRadius * 2) * CurrentScreenRatio();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Touch Area Judge Unit");
|
||||
var judgeModuleSettings = container.GenerateSubcontainer(3);
|
||||
var isShowingJudgeField =
|
||||
inspector.GenerateToggle(this, judgeModuleSettings, "Is Showing Judge", nameof(isShowingJudge))
|
||||
.AddListenerFunction(() => SetShowingJudge(isShowingJudge));
|
||||
var areaRadiusField = inspector.GenerateInputField(this, judgeModuleSettings, "Area Radius", nameof(areaRadius));
|
||||
var removeButton = inspector.GenerateButton(this, judgeModuleSettings, "Remove", () =>
|
||||
{
|
||||
SetShowingJudge(false);
|
||||
note.noteJudgeSubmodule.judgeUnitList.Remove(this);
|
||||
inspectorMain.SetInspector(note);
|
||||
});
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit_BM ConvertToBM()
|
||||
{
|
||||
return new TouchAreaJudgeUnit_BM(areaRadius);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TouchAreaJudgeUnit_BM : NoteJudgeUnit_BM
|
||||
{
|
||||
public float areaRadius;
|
||||
|
||||
public TouchAreaJudgeUnit_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TouchAreaJudgeUnit_BM(float areaRadius)
|
||||
{
|
||||
this.areaRadius = areaRadius;
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit ConvertToGameType(NoteBase attachedNote)
|
||||
{
|
||||
return new TouchAreaJudgeUnit(attachedNote, areaRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class TriggerConnectJudgeUnit : NoteJudgeUnit
|
||||
{
|
||||
public GameElement connectedJudgeTrigger;
|
||||
protected override GameObject GetHintImagePrefab() => EditorManager.instance.basePrefabs.triggerHint;
|
||||
|
||||
public TriggerConnectJudgeUnit(NoteBase note, GameElement judgeTrigger) : base(note)
|
||||
{
|
||||
this.connectedJudgeTrigger = judgeTrigger;
|
||||
}
|
||||
|
||||
protected override void SetShowingJudge(bool isShowing)
|
||||
{
|
||||
if(connectedJudgeTrigger == null) return;
|
||||
|
||||
base.SetShowingJudge(isShowing);
|
||||
|
||||
if (judgeHintImage != null)
|
||||
{
|
||||
judgeHintImage.GetComponent<TMP_Text>().text = connectedJudgeTrigger.elementName;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateJudge()
|
||||
{
|
||||
if(note.isFirstJudged || connectedJudgeTrigger == null) return;
|
||||
Vector2 noteScreenPosition = note.noteScreenPosition;
|
||||
RectTransform canvasRect = EditorManager.instance.judgeHintCanvas.GetComponent<RectTransform>();
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, noteScreenPosition, null, out Vector2 uiPosition))
|
||||
{
|
||||
judgeHintImage.anchoredPosition = uiPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Trigger Connect Judge Unit");
|
||||
var judgeModuleSettings = container.GenerateSubcontainer(3);
|
||||
var isShowingJudgeField =
|
||||
inspector.GenerateToggle(this, judgeModuleSettings, "Is Showing Judge", nameof(isShowingJudge))
|
||||
.AddListenerFunction(() => SetShowingJudge(isShowingJudge));
|
||||
|
||||
var triggerNameField = inspector.GenerateInputField(judgeModuleSettings, "Trigger Name");
|
||||
|
||||
var connectTriggerButton = inspector.GenerateButton(this, judgeModuleSettings, "Connect Trigger", () =>
|
||||
{
|
||||
GameElement trigger = EditorManager.instance.operationManager.FindingModule.FindGameElementByName(triggerNameField.GetValue<string>());
|
||||
|
||||
if (trigger is not IHaveNoteJudgeTriggerSubmodule)
|
||||
{
|
||||
LogWindow.Log("The element you are trying to connect is not a Note Judge Trigger.");
|
||||
return;
|
||||
}
|
||||
|
||||
connectedJudgeTrigger = trigger;
|
||||
(trigger as IHaveNoteJudgeTriggerSubmodule).noteJudgeTriggerSubmodule.connectedNotes.Add(note);
|
||||
});
|
||||
|
||||
var removeButton = inspector.GenerateButton(this, judgeModuleSettings, "Remove", () =>
|
||||
{
|
||||
SetShowingJudge(false);
|
||||
note.noteJudgeSubmodule.judgeUnitList.Remove(this);
|
||||
inspectorMain.SetInspector(note);
|
||||
});
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit_BM ConvertToBM()
|
||||
{
|
||||
return new TriggerConnectJudgeUnit_BM(connectedJudgeTrigger.elementGuid);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TriggerConnectJudgeUnit_BM : NoteJudgeUnit_BM
|
||||
{
|
||||
public Guid connectedTriggerID;
|
||||
|
||||
public TriggerConnectJudgeUnit_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TriggerConnectJudgeUnit_BM(Guid connectedTriggerID)
|
||||
{
|
||||
this.connectedTriggerID = connectedTriggerID;
|
||||
}
|
||||
|
||||
public override NoteJudgeUnit ConvertToGameType(NoteBase attachedNote)
|
||||
{
|
||||
Debug.Log(GameElement_BM.GetElement(connectedTriggerID));
|
||||
return new TriggerConnectJudgeUnit(attachedNote, GameElement_BM.GetElement(connectedTriggerID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteBadEffect : NoteEffectBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteBadEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NoteBadEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteBadEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteEffectBase : EffectBase
|
||||
{
|
||||
public NoteBase note;
|
||||
public NoteVisualBase noteVisual;
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteEffectBase_BM : EffectBase_BM
|
||||
{
|
||||
public NoteEffectBase_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteEffectBase_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteGeneralJudgeEffect : NoteEffectBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteGeneralJudgeEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NoteGeneralJudgeEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteGeneralJudgeEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteGoodEffect : NoteEffectBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteGoodEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NoteGoodEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteGoodEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteHoldingEffect : NoteEffectBase
|
||||
{
|
||||
public float GetHoldingTime()
|
||||
{
|
||||
return (note as Hold).holdEndTime - note.exactJudgeTime;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteHoldingEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NoteHoldingEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteHoldingEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteMissEffect : NoteEffectBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteMissEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NoteMissEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteMissEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame.ThemeBundles.Basic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NotePerfectEffect : NoteEffectBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NotePerfectEffect_BM : NoteEffectBase_BM
|
||||
{
|
||||
public NotePerfectEffect_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NotePerfectEffect_BM(float effectTime) : base(effectTime)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class Flick : NoteBase
|
||||
{
|
||||
public List<Vector2> availableFlickDirections;
|
||||
public float flickBufferAngle = 60f;
|
||||
|
||||
public static Flick GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement parentElement, float exactJudgeTime, List<Vector2> directions)
|
||||
{
|
||||
Flick flick = Instantiate(EditorManager.instance.basePrefabs.flickNote, parentElement.transform)
|
||||
.GetComponent<Flick>();
|
||||
|
||||
|
||||
flick.Initialize(elementName, id, tags, EditorManager.instance.useNotePrefab ? false : isFirstGenerated, parentElement);
|
||||
flick.exactJudgeTime = exactJudgeTime;
|
||||
flick.availableFlickDirections = directions;
|
||||
|
||||
if (parentElement.TryGetComponent(out Track track))
|
||||
{
|
||||
if (track.trackTimeSubmodule != null)
|
||||
{
|
||||
flick.track = track;
|
||||
flick.trackPositioner = flick.AddComponent<SplinePositioner>();
|
||||
flick.trackPositioner.spline = track.trackPathSubmodule.path;
|
||||
flick.isOnTrack = true;
|
||||
flick.UpdateNoteInTrack();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.Exception("如果Note要生成在Track上,Track必须有TrackTimeSubmodule组件。");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flick.track = null;
|
||||
flick.isOnTrack = false;
|
||||
}
|
||||
|
||||
if (EditorManager.instance.useNotePrefab && isFirstGenerated)
|
||||
{
|
||||
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(flick, GetNoteTypeName(flick) + "_Prefab");
|
||||
}
|
||||
if (isFirstGenerated) flick.AfterInitialize();
|
||||
|
||||
return flick;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Flick
|
||||
{
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
base.SetDefaultSubmodules();
|
||||
noteAudioSubmodule ??= new NoteAudioSubmodule(this, "DefaultFlick");
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Flick_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
exactJudgeTime, availableFlickDirections);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var flickSpecial = inspector.GenerateContainer("Flick Special");
|
||||
var flickSpecialSubcontainer = flickSpecial.GenerateSubcontainer(3);
|
||||
var availableDirectionsButton =
|
||||
inspector.GenerateButton(this, flickSpecialSubcontainer, "Available Directions", () =>
|
||||
{
|
||||
var widthCurveWindow = inspector.GenerateCompositeParameterWindow(this, "Available Directions", nameof(availableFlickDirections));
|
||||
widthCurveWindow.SetAsFlexibleFloat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class Flick_BM : NoteBase_BM
|
||||
{
|
||||
public List<Vector2> availableFlickDirections;
|
||||
|
||||
public Flick_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Flick_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
float exactJudgeTime,
|
||||
List<Vector2> directions) : base(elementName, elementGuid, tags, attachedElement, exactJudgeTime)
|
||||
{
|
||||
availableFlickDirections = directions;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = Flick.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), exactJudgeTime, availableFlickDirections);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return Flick.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
exactJudgeTime, availableFlickDirections);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,344 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UniRx;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class Hold : NoteBase
|
||||
{
|
||||
public static List<Hold> holdingHoldList = new();
|
||||
|
||||
public float holdEndTime;
|
||||
public float holdingTime;
|
||||
public bool isHolding;
|
||||
public bool isFinalJudged;
|
||||
|
||||
public static Hold GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement parentElement, float exactJudgeTime, float holdEndTime)
|
||||
{
|
||||
Hold hold = Instantiate(EditorManager.instance.basePrefabs.holdNote, parentElement.transform)
|
||||
.GetComponent<Hold>();
|
||||
|
||||
hold.Initialize(elementName, id, tags, EditorManager.instance.useNotePrefab ? false : isFirstGenerated, parentElement);
|
||||
hold.exactJudgeTime = exactJudgeTime;
|
||||
hold.holdEndTime = holdEndTime;
|
||||
hold.holdingTime = 0;
|
||||
|
||||
if (parentElement.TryGetComponent(out Track track))
|
||||
{
|
||||
if (track.trackTimeSubmodule != null)
|
||||
{
|
||||
hold.track = track;
|
||||
hold.trackPositioner = hold.AddComponent<SplinePositioner>();
|
||||
hold.trackPositioner.spline = track.trackPathSubmodule.path;
|
||||
hold.trackPositioner.updateMethod = SplineUser.UpdateMethod.LateUpdate;
|
||||
hold.isOnTrack = true;
|
||||
hold.UpdateNoteInTrack();
|
||||
Observable.NextFrame().Subscribe(_ =>
|
||||
{
|
||||
hold.UpdateNoteInTrack();
|
||||
track.Refresh();
|
||||
track.trackPathSubmodule?.path.RebuildImmediate();
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("如果Note要生成在Track上,Track必须有TrackTimeSubmodule组件。");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hold.track = null;
|
||||
hold.isOnTrack = false;
|
||||
}
|
||||
|
||||
if (EditorManager.instance.useNotePrefab && isFirstGenerated)
|
||||
{
|
||||
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(hold, GetNoteTypeName(hold) + "_Prefab");
|
||||
}
|
||||
if (isFirstGenerated) hold.AfterInitialize();
|
||||
return hold;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Hold
|
||||
{
|
||||
public override void UpdateNoteInMovableTrack()
|
||||
{
|
||||
if (!isHolding && !isFinalJudged)
|
||||
{
|
||||
base.UpdateNoteInMovableTrack();
|
||||
}
|
||||
|
||||
if (noteVisual is INoteVisualHold noteVisualHold)
|
||||
{
|
||||
noteVisualHold.UpdateHoldInMovableTrack();
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateNoteInStaticTrack()
|
||||
{
|
||||
base.UpdateNoteInStaticTrack();
|
||||
if (noteVisual is INoteVisualHold noteVisualHold)
|
||||
{
|
||||
noteVisualHold.UpdateHoldInStaticTrack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Hold
|
||||
{
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
base.SetDefaultSubmodules();
|
||||
noteAudioSubmodule ??= new NoteAudioSubmodule(this, new List<string>() { "DefaultEndHold" },
|
||||
new List<string>(), new List<string>(),
|
||||
new List<string>(), new List<string>(),
|
||||
new List<string>() { "DefaultStartHold" });
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Hold_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM, exactJudgeTime, holdEndTime);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var holdSpecial = inspector.GenerateContainer("Hold");
|
||||
var holdSpecialSubcontainer = holdSpecial.GenerateSubcontainer(3);
|
||||
var holdEndTimeInputField = inspector.GenerateInputField(this, holdSpecialSubcontainer, "holdEndTime", nameof(holdEndTime), true);
|
||||
var holdingTimeInputField = inspector.GenerateInputField(holdSpecialSubcontainer, "holdingTime", (holdEndTime - exactJudgeTime).ToString());
|
||||
holdEndTimeInputField.AddListenerFunction(() =>
|
||||
{
|
||||
holdingTimeInputField.inputField.text = (holdEndTime - exactJudgeTime).ToString();
|
||||
noteVisual?.effectSubmodule.effectCollection["Holding"].ForEach(effect =>
|
||||
{
|
||||
effect.effectTime = holdEndTime - exactJudgeTime;
|
||||
});
|
||||
});
|
||||
holdingTimeInputField.AddListenerFunction(() =>
|
||||
{
|
||||
holdEndTime = float.Parse(holdingTimeInputField.inputField.text) + exactJudgeTime;
|
||||
holdEndTimeInputField.inputField.text = holdEndTime.ToString();
|
||||
holdEndTimeInputField.inputField.onEndEdit.Invoke(holdEndTimeInputField.inputField.text);
|
||||
});
|
||||
inspector.MarkedElements["ExactJudgeTime"].AddListenerFunction(() =>
|
||||
{
|
||||
noteVisual?.effectSubmodule.effectCollection["Holding"].ForEach(effect =>
|
||||
{
|
||||
effect.effectTime = holdEndTime - exactJudgeTime;
|
||||
});
|
||||
// 新增:根据holdingTimeInputField的值更新holdEndTime
|
||||
|
||||
float holdingTimeValue;
|
||||
if (float.TryParse(holdingTimeInputField.inputField.text, out holdingTimeValue))
|
||||
{
|
||||
holdEndTime = exactJudgeTime + holdingTimeValue;
|
||||
holdEndTimeInputField.inputField.text = holdEndTime.ToString();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Hold
|
||||
{
|
||||
public override void Update()
|
||||
{
|
||||
if (Keyboard.current.hKey.wasPressedThisFrame)
|
||||
{
|
||||
foreach (KeyValuePair<string, List<EffectBase>> effect in noteVisual.effectSubmodule.effectCollection)
|
||||
{
|
||||
effect.Value.ForEach(x => x.Disrupt());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
|
||||
// 边界检查
|
||||
if (holdEndTime < exactJudgeTime)
|
||||
{
|
||||
LogWindow.Log("Hold end time is earlier than exact judge time.", Color.red);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 重置逻辑:当时间回退到判定时间之前
|
||||
if (isFirstJudged && songTime < exactJudgeTime)
|
||||
{
|
||||
isFirstJudged = false;
|
||||
isHolding = false;
|
||||
isFinalJudged = false;
|
||||
holdingTime = 0;
|
||||
// 移除音频播放 - 重置时不应该播放任何音频
|
||||
}
|
||||
|
||||
// 2. 状态恢复:当时间从结束状态回退到hold区间内
|
||||
if (isFinalJudged && songTime >= exactJudgeTime && songTime <= holdEndTime)
|
||||
{
|
||||
isFirstJudged = true;
|
||||
isHolding = true;
|
||||
isFinalJudged = false;
|
||||
holdingTime = songTime - exactJudgeTime; // 修复:更新holdingTime
|
||||
}
|
||||
|
||||
// 3. 处理hold过程中的逻辑
|
||||
if (isHolding)
|
||||
{
|
||||
holdingTime = songTime - exactJudgeTime;
|
||||
|
||||
// 检查hold是否结束
|
||||
if (songTime >= holdEndTime && !isFinalJudged)
|
||||
{
|
||||
isHolding = false;
|
||||
isFinalJudged = true;
|
||||
// 可以考虑在这里播放hold结束的音频
|
||||
// noteAudioSubmodule?.PlayHoldEndAudio();
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 第一次判定:进入判定区间
|
||||
if (!isFirstJudged && songTime >= exactJudgeTime)
|
||||
{
|
||||
isFirstJudged = true;
|
||||
|
||||
// 检查是否可以开始hold
|
||||
if (songTime <= holdEndTime)
|
||||
{
|
||||
// 播放开始判定的音频
|
||||
noteAudioSubmodule?.PlayNoteJudgeAudios(EditorManager.instance.currentJudgeType);
|
||||
// 如果需要,在这里播放hold开始音频
|
||||
// noteAudioSubmodule.PlayHoldStartAudio();
|
||||
|
||||
isHolding = true;
|
||||
holdingTime = songTime - exactJudgeTime;
|
||||
}
|
||||
}
|
||||
if (noteJudgeSubmodule != null && !EditorManager.instance.cameraManager.isSceneCameraActive)
|
||||
{
|
||||
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
|
||||
{
|
||||
unit.UpdateJudge();
|
||||
}
|
||||
}
|
||||
|
||||
if (noteVisual != null)
|
||||
{
|
||||
noteVisual.effectSubmodule.effectCollection["Generate"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
noteVisual.effectSubmodule.effectCollection["StartHold"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
noteVisual.effectSubmodule.effectCollection["Holding"].ForEach(e => e.UpdateEffect(exactJudgeTime));
|
||||
|
||||
|
||||
noteVisual.effectSubmodule.effectCollection["GeneralJudge"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
switch (EditorManager.instance.currentJudgeType)
|
||||
{
|
||||
case NoteJudgeType.Perfect:
|
||||
noteVisual.effectSubmodule.effectCollection["Perfect"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
break;
|
||||
case NoteJudgeType.Good:
|
||||
noteVisual.effectSubmodule.effectCollection["Good"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
break;
|
||||
case NoteJudgeType.Bad:
|
||||
noteVisual.effectSubmodule.effectCollection["Bad"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
break;
|
||||
case NoteJudgeType.Miss:
|
||||
noteVisual.effectSubmodule.effectCollection["Miss"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
break;
|
||||
}
|
||||
|
||||
noteVisual.effectSubmodule.effectCollection["AfterJudge"].ForEach(e => e.UpdateEffect(holdEndTime));
|
||||
|
||||
if (EditorManager.instance.cameraManager.haveGameCamera)
|
||||
{
|
||||
noteScreenPosition = EditorManager.instance.cameraManager.gameCamera.gameCamera.WorldToScreenPoint(noteVisual.noteVisualPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 优化持有列表的添加和移除
|
||||
if (isHolding)
|
||||
{
|
||||
if (!holdingHoldList.Contains(this))
|
||||
holdingHoldList.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (holdingHoldList.Contains(this))
|
||||
holdingHoldList.Remove(this);
|
||||
}
|
||||
}
|
||||
public void SetFinishEffects()//一定在播放完之后再搞这个
|
||||
{
|
||||
noteVisual.effectSubmodule.effectCollection["Holding"].ForEach(e => e.Adjust());
|
||||
|
||||
|
||||
// noteVisual.effectSubmodule.effectCollection["GeneralJudge"].ForEach(e => e.Adjust());
|
||||
// switch (EditorManager.instance.currentJudgeType)
|
||||
// {
|
||||
// case NoteJudgeType.Perfect:
|
||||
// noteVisual.effectSubmodule.effectCollection["Perfect"].ForEach(e => e.Adjust());
|
||||
// break;
|
||||
// case NoteJudgeType.Good:
|
||||
// noteVisual.effectSubmodule.effectCollection["Good"].ForEach(e => e.Adjust());
|
||||
// break;
|
||||
// case NoteJudgeType.Bad:
|
||||
// noteVisual.effectSubmodule.effectCollection["Bad"].ForEach(e => e.Adjust());
|
||||
// break;
|
||||
// case NoteJudgeType.Miss:
|
||||
// noteVisual.effectSubmodule.effectCollection["Miss"].ForEach(e => e.Adjust());
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (isOnTrack)
|
||||
{
|
||||
UpdateNoteInTrack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class Hold_BM : NoteBase_BM
|
||||
{
|
||||
public float holdEndTime;
|
||||
|
||||
public Hold_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Hold_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement, float exactJudgeTime, float holdEndTime)
|
||||
: base(elementName, elementGuid, tags, attachedElement, exactJudgeTime)
|
||||
{
|
||||
this.holdEndTime = holdEndTime;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = Hold.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), exactJudgeTime, holdEndTime);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return Hold.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent, exactJudgeTime, holdEndTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract partial class NoteBase : GameElement, IHaveTimeDurationSubmodule, IComparable<NoteBase>
|
||||
{
|
||||
[Title("Basic Info")]
|
||||
public float exactJudgeTime;
|
||||
|
||||
[Title("Track Info")]
|
||||
public bool isOnTrack;
|
||||
public Track track;
|
||||
public SplinePositioner trackPositioner;
|
||||
|
||||
[Title("NoteVisual")]
|
||||
public NoteVisualBase noteVisual;
|
||||
|
||||
[Title("Submodules")]
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
public NoteJudgeSubmodule noteJudgeSubmodule { get; set; }
|
||||
public NoteAudioSubmodule noteAudioSubmodule { get; set; }
|
||||
|
||||
[Title("In-Game Info")]
|
||||
public Vector2 noteScreenPosition;
|
||||
[FormerlySerializedAs("isJudged")] public bool isFirstJudged;
|
||||
public override int HierarchyPriority => -10;
|
||||
public override void Initialize(string name, Guid elementGuid, List<string> tags, bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
base.Initialize(name, elementGuid, tags, isFirstGenerated, parentElement);
|
||||
Update();
|
||||
}
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
base.AfterInitialize();
|
||||
AddinNoteManager();
|
||||
}
|
||||
public void AddinNoteManager(bool isNewOne = true)
|
||||
{
|
||||
float beyondTime = 0f;
|
||||
|
||||
foreach (EffectBase effectBase in noteVisual.effectSubmodule.effectCollection["Generate"])
|
||||
{
|
||||
if (effectBase is NoteGenerateEffect ge)
|
||||
{
|
||||
ge.Recover();
|
||||
beyondTime = Mathf.Max(beyondTime, ge.generateTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
effectBase.Recover();
|
||||
}
|
||||
}
|
||||
float finishTime = 0f;
|
||||
List<EffectBase> finishEffects = new List<EffectBase>();
|
||||
finishEffects.AddRange(noteVisual.effectSubmodule.effectCollection["GeneralJudge"]);
|
||||
finishEffects.AddRange(noteVisual.effectSubmodule.effectCollection["Perfect"]);
|
||||
finishEffects.AddRange(noteVisual.effectSubmodule.effectCollection["Good"]);
|
||||
finishEffects.AddRange(noteVisual.effectSubmodule.effectCollection["Bad"]);
|
||||
finishEffects.AddRange(noteVisual.effectSubmodule.effectCollection["Miss"]);
|
||||
|
||||
foreach (EffectBase effectBase in finishEffects)
|
||||
{
|
||||
finishTime = Mathf.Max(finishTime, effectBase.effectTime);
|
||||
}
|
||||
|
||||
if (exactJudgeTime - beyondTime - 0.5f > -EditorManager.instance.songInformation.delay)
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
// if (this is Hold hold)
|
||||
// {
|
||||
// EditorManager.instance.noteManager.RegisterNote(hold, hold.exactJudgeTime - beyondTime - 0.1f, + finishTime + 0.5f);
|
||||
|
||||
// }
|
||||
if (isNewOne) EditorManager.instance.noteManager.RegisterNote(this, exactJudgeTime - beyondTime - 0.1f, (this is Hold hold ? hold.holdEndTime : exactJudgeTime) + finishTime + 0.1f);
|
||||
else NoteManager.instance.ChangeNoteInfo(this, exactJudgeTime - beyondTime - 0.1f, (this is Hold hold ? hold.holdEndTime : exactJudgeTime) + finishTime + 0.1f);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 在MovableTrack上更新Note的位置,注意HoldNote需要重写这个方法
|
||||
/// </summary>
|
||||
public virtual void UpdateNoteInMovableTrack()
|
||||
{
|
||||
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
|
||||
trackPositioner.SetPercent(trackTimeSubmoduleMovable.GetTrackPercent(exactJudgeTime));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在StaticTrack上更新Note的位置,注意HoldNote需要重写这个方法
|
||||
/// </summary>
|
||||
public virtual void UpdateNoteInStaticTrack()
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
TrackTimeSubmoduleStatic trackTimeSubmoduleStatic = track.trackTimeSubmodule as TrackTimeSubmoduleStatic;
|
||||
|
||||
float startMove = exactJudgeTime - trackTimeSubmoduleStatic.trackTotalTime;
|
||||
float percent = AnimationCurveEvaluator.Evaluate(trackTimeSubmoduleStatic.animationCurveType, (songTime - startMove) / trackTimeSubmoduleStatic.trackTotalTime);
|
||||
|
||||
percent = Mathf.Max(percent, 0);
|
||||
percent = Mathf.Min(percent, 1);
|
||||
|
||||
trackPositioner.SetPercent(1 - percent);
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule ??= new TimeDurationSubmodule(this);
|
||||
noteJudgeSubmodule ??= new NoteJudgeSubmodule(this);
|
||||
}
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
if (noteVisual != null)
|
||||
{
|
||||
noteVisual.Refresh();
|
||||
}
|
||||
AddinNoteManager(false);
|
||||
foreach (SampleWindow i in SampleWindow.instances.Where(i => i.gameElement)) i.OnceSpawnNote();
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
var editor = EditorManager.instance;
|
||||
var cameraManager = editor.cameraManager;
|
||||
float songTime = editor.songInformation.songTime;
|
||||
|
||||
// 轨道位置更新
|
||||
if (isOnTrack && track.trackTimeSubmodule is TrackTimeSubmoduleStatic)
|
||||
{
|
||||
UpdateNoteInStaticTrack();
|
||||
}
|
||||
|
||||
// 判定状态更新
|
||||
if (isFirstJudged && songTime < exactJudgeTime)
|
||||
{
|
||||
isFirstJudged = false;
|
||||
if (noteVisual != null) noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
}
|
||||
else if (!isFirstJudged && songTime >= exactJudgeTime)
|
||||
{
|
||||
noteAudioSubmodule?.PlayNoteJudgeAudios(editor.currentJudgeType);
|
||||
isFirstJudged = true;
|
||||
if (noteVisual != null) noteVisual.GetComponent<Collider>().enabled = !isFirstJudged;
|
||||
}
|
||||
|
||||
// 判定单元更新
|
||||
if (noteJudgeSubmodule != null && !cameraManager.isSceneCameraActive)
|
||||
{
|
||||
foreach (var unit in noteJudgeSubmodule.judgeUnitList)
|
||||
{
|
||||
if (unit.isShowingJudge) unit.UpdateJudge();
|
||||
}
|
||||
}
|
||||
|
||||
// 视觉效果更新
|
||||
if (noteVisual != null)
|
||||
{
|
||||
var effects = noteVisual.effectSubmodule.effectCollection;
|
||||
UpdateEffectList(effects["Generate"]);
|
||||
UpdateEffectList(effects["GeneralJudge"]);
|
||||
|
||||
if (editor.currentJudgeType == NoteJudgeType.Perfect)
|
||||
{
|
||||
UpdateEffectList(effects["Perfect"]);
|
||||
}
|
||||
else if (editor.currentJudgeType == NoteJudgeType.Good)
|
||||
{
|
||||
UpdateEffectList(this is Tap or Hold ? effects["Good"] : effects["Perfect"]);
|
||||
}
|
||||
else if (editor.currentJudgeType == NoteJudgeType.Bad)
|
||||
{
|
||||
UpdateEffectList(this is Tap or Hold ? effects["Bad"] : effects["Perfect"]);
|
||||
}
|
||||
else if (editor.currentJudgeType == NoteJudgeType.Miss)
|
||||
{
|
||||
UpdateEffectList(effects["Miss"]);
|
||||
}
|
||||
|
||||
UpdateEffectList(effects["AfterJudge"]);
|
||||
|
||||
// 屏幕位置更新(降低频率)
|
||||
if (cameraManager.haveGameCamera)//&& Time.frameCount % 3 == 0)
|
||||
{
|
||||
noteScreenPosition = cameraManager.gameCamera.gameCamera.WorldToScreenPoint(noteVisual.noteVisualPosition);
|
||||
}
|
||||
|
||||
// 碰撞体状态
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:更新效果列表
|
||||
private void UpdateEffectList(List<EffectBase> effects)
|
||||
{
|
||||
for (int i = 0; i < effects.Count; i++)
|
||||
{
|
||||
effects[i].UpdateEffect(exactJudgeTime);
|
||||
}
|
||||
}
|
||||
public void ExecuteStartJudge()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void UpdateNoteInTrack()
|
||||
{
|
||||
if (isOnTrack && track.trackTimeSubmodule != null)
|
||||
{
|
||||
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable)
|
||||
{
|
||||
UpdateNoteInMovableTrack();
|
||||
}
|
||||
else if (track.trackTimeSubmodule is TrackTimeSubmoduleStatic)
|
||||
{
|
||||
UpdateNoteInStaticTrack();
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
//
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Element Info");
|
||||
|
||||
//基础信息
|
||||
var info = container.GenerateSubcontainer(3);
|
||||
var nameInputField = inspector.GenerateInputField(this, info, GetType().Name + "'s Name", nameof(elementName));
|
||||
var guidText = inspector.GenerateParameterText(this, info, "Element GUID", nameof(elementGuid));
|
||||
var tagsListButton = inspector.GenerateButton(this, info, "Tags List", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Tags List", nameof(tags)).SetAsStringList();
|
||||
});
|
||||
if (noteVisual != null)
|
||||
{
|
||||
noteVisual.transformSubmodule.SetUpInspector();
|
||||
}
|
||||
//次级模块
|
||||
foreach (var submodule in submoduleList)
|
||||
{
|
||||
submodule.SetUpInspector();
|
||||
}
|
||||
//为了设置便捷Transform编辑手动更改原方法而不是用Base
|
||||
|
||||
var infoContainer = inspector.GenerateContainer("Note Info");
|
||||
var noteBaseSettings = infoContainer.GenerateSubcontainer(3);
|
||||
var exactJudgeTimeInputField =
|
||||
inspector.GenerateInputField(this, noteBaseSettings, "exactJudgeTime", nameof(exactJudgeTime))
|
||||
.AddListenerFunction(UpdateNoteInTrack).Mark("ExactJudgeTime");
|
||||
var saveNotePrefabButton =
|
||||
inspector.GenerateButton(this, noteBaseSettings, "Save Note Prefab", () =>
|
||||
{
|
||||
EditorManager.instance.projectManager.notePrefabManager.SaveNotePrefab(this, GetNoteTypeName(this) + "_Prefab");
|
||||
});
|
||||
var noteScreenPositionText = inspector.GenerateHintText(this, noteBaseSettings,
|
||||
() => "Note Screen Position: " + noteScreenPosition);
|
||||
|
||||
var noteVisualContainer = inspector.GenerateContainer("Note Visual");
|
||||
var noteVisualGeneration = noteVisualContainer.GenerateSubcontainer(3);
|
||||
var generateNoteVisualButton = inspector.GenerateButton(this, noteVisualGeneration, "Generate Note Visual", () =>
|
||||
{
|
||||
TemporaryObject.GenerateElement("New Note Visual", Guid.NewGuid(), new List<string>(), true, this);
|
||||
});
|
||||
|
||||
if (noteVisual != null)
|
||||
{
|
||||
generateNoteVisualButton.button.interactable = false;
|
||||
}
|
||||
}
|
||||
public override void OnDelete()
|
||||
{
|
||||
base.OnDelete();
|
||||
if (parentElement != null)
|
||||
{
|
||||
if (EditorManager.instance.uiManager.inspector.connectedGameElement == parentElement)
|
||||
{
|
||||
EditorManager.instance.uiManager.timeline.SetTimeLine(parentElement);
|
||||
}
|
||||
foreach (SampleWindow i in SampleWindow.instances.Where(i => i.gameElement)) i.OnceSpawnNote();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(NoteBase other)
|
||||
{
|
||||
return exactJudgeTime.CompareTo(other.exactJudgeTime);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class NoteBase
|
||||
{
|
||||
public enum NoteJudgeType
|
||||
{
|
||||
Perfect,
|
||||
Good,
|
||||
Bad,
|
||||
Miss
|
||||
}
|
||||
|
||||
public static string GetNoteTypeName(NoteBase note)
|
||||
{
|
||||
return note switch
|
||||
{
|
||||
Tap => "Tap",
|
||||
Stay => "Stay",
|
||||
Hold => "Hold",
|
||||
Flick => "Flick",
|
||||
_ => throw new NotImplementedException("Note type not recognized")
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteBase_BM : GameElement_BM
|
||||
{
|
||||
public float exactJudgeTime;
|
||||
|
||||
public NoteBase_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteBase_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement, float exactJudgeTime)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.exactJudgeTime = exactJudgeTime;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public abstract class NoteVisualBase : SubstantialObject, IHaveEffectSubmodule, IHaveSelectSubmodule
|
||||
{
|
||||
public NoteBase note;
|
||||
|
||||
public bool isHighlighted;
|
||||
|
||||
public GameObject noteMain;
|
||||
public GameObject judgeEffect;
|
||||
|
||||
public List<GameObject> notePartList;
|
||||
public List<GameObject> extraPartList;
|
||||
public List<GameObject> effectPrefabList;
|
||||
|
||||
public virtual Vector3 noteVisualPosition => noteMain.transform.position;
|
||||
|
||||
public EffectSubmodule effectSubmodule { get; set; }
|
||||
public SelectSubmodule selectSubmodule { get; set; }
|
||||
|
||||
public static NoteVisualBase GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement, bool isHighlighted)
|
||||
{
|
||||
NoteVisualBase noteVisual = SubstantialObject.GenerateElement(elementName, id, tags,
|
||||
isFirstGenerated, themeBundleName, objectName, parentElement).GetComponent<NoteVisualBase>();
|
||||
|
||||
noteVisual.isHighlighted = isHighlighted;
|
||||
noteVisual.SetHighlight();
|
||||
noteVisual.SetEditorSubmodules();
|
||||
return noteVisual;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
base.SetDefaultSubmodules();
|
||||
effectSubmodule = new EffectSubmodule(this, EffectSubmodule.EffectSubmodulePreset.Note);
|
||||
}
|
||||
|
||||
|
||||
public override void SetEditorSubmodules()
|
||||
{
|
||||
selectSubmodule ??= new SelectSubmodule(this, note);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Generate");
|
||||
StandardInspectionElement.GenerateForTransform(this, container);
|
||||
|
||||
var settings = inspector.GenerateContainer("Settings");
|
||||
var settingsSubcontainer = settings.GenerateSubcontainer(3);
|
||||
var highlightToggle =
|
||||
inspector.GenerateToggle(this, settingsSubcontainer, "Highlight", nameof(isHighlighted))
|
||||
.AddListenerFunction(SetHighlight);
|
||||
}
|
||||
|
||||
public virtual void Recover()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void SetHighlight()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public abstract class NoteVisualBase_BM : SubstantialObject_BM
|
||||
{
|
||||
public bool isHighlighted;
|
||||
public NoteVisualBase_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NoteVisualBase_BM(string elementName, Guid id, List<string> tags,
|
||||
GameElement_BM parent, string themeBundleName, string objectName, bool isHighlighted) :
|
||||
base(elementName, id, tags, parent, themeBundleName, objectName)
|
||||
{
|
||||
this.isHighlighted = isHighlighted;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -1,173 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class PathNode : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule, IHaveColorSubmodule, IHaveSelectSubmodule
|
||||
{
|
||||
public Track track;
|
||||
public SplinePoint node;
|
||||
public int index => track.trackPathSubmodule.pathNodeList.IndexOf(this);
|
||||
public TransformSubmodule transformSubmodule { get; set; }
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
public ColorSubmodule colorSubmodule { get; set; }
|
||||
public bool haveEmissionColor => false;
|
||||
public override int HierarchyPriority => -100;
|
||||
|
||||
|
||||
public SelectSubmodule selectSubmodule { get; set; }
|
||||
|
||||
[Title("Editor独有参数")]
|
||||
[SerializeField]
|
||||
[HideInPlayMode]
|
||||
private GameObject pathNodeSphere;
|
||||
public bool isShowingSphere;
|
||||
|
||||
public static PathNode GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
Track track, bool isShowingSphere, int index = -1)
|
||||
{
|
||||
PathNode pathNode = Instantiate(EditorManager.instance.basePrefabs.pathNode, track.transform)
|
||||
.GetComponent<PathNode>();
|
||||
|
||||
pathNode.Initialize(elementName, id, tags, isFirstGenerated, track);
|
||||
|
||||
pathNode.track = track;
|
||||
pathNode.isShowingSphere = isShowingSphere;
|
||||
pathNode.SetPathNodeSphere(isShowingSphere);
|
||||
if (index < 0)
|
||||
{
|
||||
track.trackPathSubmodule.pathNodeList.Add(pathNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
track.trackPathSubmodule.pathNodeList.Insert(index, pathNode);
|
||||
}
|
||||
pathNode.SetEditorSubmodules();
|
||||
|
||||
return pathNode;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
transformSubmodule = new TransformSubmodule(this);
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
colorSubmodule = new ColorSubmodule(this);
|
||||
}
|
||||
public override void SetEditorSubmodules()
|
||||
{
|
||||
selectSubmodule ??= new SelectSubmodule(this, this);
|
||||
}
|
||||
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
base.AfterInitialize();
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class PathNode
|
||||
{
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
Vector3 position = transformSubmodule.currentPosition;
|
||||
Vector3 normal = Quaternion.Euler(transformSubmodule.currentEulerAngles) * Vector3.up;
|
||||
float size = transformSubmodule.currentScale.x;
|
||||
Color color = colorSubmodule.currentBaseColor;
|
||||
MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
|
||||
materialPropertyBlock.SetColor("_Color", color);
|
||||
pathNodeSphere.GetComponent<Renderer>()?.SetPropertyBlock(materialPropertyBlock);
|
||||
transform.localPosition = position;
|
||||
transform.localRotation = Quaternion.LookRotation(normal);
|
||||
transform.localScale = Vector3.one * size;
|
||||
|
||||
node = new SplinePoint(position, Vector3.up, normal, size, color);
|
||||
track.trackPathSubmodule.SetPathNode(this);
|
||||
}
|
||||
public void OnDestroy()
|
||||
{
|
||||
track.trackPathSubmodule.pathNodeList.Remove(this);
|
||||
track.trackPathSubmodule.SetPathPoints();
|
||||
track.Refresh();
|
||||
//print("PathNode " + elementName + " destroyed.");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class PathNode
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Beatmap.PathNode_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM, isShowingSphere);
|
||||
}
|
||||
|
||||
public void SetPathNodeSphere(bool isShowing)
|
||||
{
|
||||
isShowingSphere = isShowing;
|
||||
pathNodeSphere.SetActive(isShowing);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
base.SetUpInspector();
|
||||
|
||||
var container = inspector.GenerateContainer("Path Node");
|
||||
|
||||
var pathNodeSettings = container.GenerateSubcontainer(3);
|
||||
var indexText = inspector.GenerateHintText(this, pathNodeSettings, "Index: " + index);
|
||||
var isShowingSphereToggle =
|
||||
inspector.GenerateToggle(this, pathNodeSettings, "Is Showing Sphere", nameof(isShowingSphere))
|
||||
.AddListenerFunction(() => SetPathNodeSphere(isShowingSphere));
|
||||
|
||||
var generateAnimation = container.GenerateSubcontainer(3);
|
||||
StandardInspectionElement.GenerateForTransform(this, container);
|
||||
var generateBaseColorChangeButton = inspector.GenerateButton(this, generateAnimation, "Base Color Change",
|
||||
() => BaseColorChange.GenerateElement("New Base Color Change", Guid.NewGuid(), new List<string>(), true,
|
||||
this,
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.r, colorSubmodule.originalBaseColor.r, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.g, colorSubmodule.originalBaseColor.g, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.b, colorSubmodule.originalBaseColor.b, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.a, colorSubmodule.originalBaseColor.a, animationCurveType: AnimationCurveType.Linear) })
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class PathNode_BM : GameElement_BM
|
||||
{
|
||||
public bool isShowingSphere;
|
||||
public PathNode_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public PathNode_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
bool isShowingSphere)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.isShowingSphere = isShowingSphere;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = PathNode.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, isShowingSphere);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return PathNode.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent as Track, isShowingSphere);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class CrossTrackPoint : GameElement, IHaveTimeDurationSubmodule
|
||||
{
|
||||
public ElementFolder trackListFolder;
|
||||
public Track nowAttachedTrack;
|
||||
private int nowAttachedTrackIndex;
|
||||
public SplinePositioner trackPositioner;
|
||||
|
||||
public FlexibleInt trackSwitch;
|
||||
public FlexibleFloat trackPercent;
|
||||
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
|
||||
public bool MotionAngles = false;
|
||||
|
||||
public static CrossTrackPoint GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, ElementFolder elementFolder, FlexibleInt trackSwitch, FlexibleFloat trackPercent)
|
||||
{
|
||||
CrossTrackPoint point = Instantiate(EditorManager.instance.basePrefabs.emptyObject, elementFolder.transform)
|
||||
.AddComponent<CrossTrackPoint>();
|
||||
point.Initialize(elementName, id, tags, isFirstGenerated, elementFolder);
|
||||
point.trackPositioner = point.gameObject.AddComponent<SplinePositioner>();
|
||||
point.nowAttachedTrackIndex = -1;
|
||||
point.trackListFolder = elementFolder;
|
||||
point.trackSwitch = trackSwitch;
|
||||
point.trackPercent = trackPercent;
|
||||
|
||||
point.trackPositioner.motion.rotationOffset = Vector3.zero;
|
||||
point.trackPositioner.motion.applyRotation = false;
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (trackPercent.animations.Count > 0)
|
||||
{
|
||||
trackSwitch.UpdateFlexibleInt(EditorManager.instance.songInformation.songTime);
|
||||
trackPercent.UpdateFlexibleFloat(EditorManager.instance.songInformation.songTime);
|
||||
SetPoint();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPoint()
|
||||
{
|
||||
if (nowAttachedTrackIndex != trackSwitch.value &&
|
||||
trackSwitch.value >= 0 &&
|
||||
trackSwitch.value < trackListFolder.trackList.Count)
|
||||
{
|
||||
nowAttachedTrack = trackListFolder.trackList[trackSwitch.value];
|
||||
nowAttachedTrackIndex = trackSwitch.value;
|
||||
trackPositioner.spline = trackListFolder.trackList[trackSwitch.value].trackPathSubmodule.path;
|
||||
}
|
||||
|
||||
trackPositioner.SetPercent(trackPercent.value);
|
||||
}
|
||||
|
||||
private void PasteTrackList()
|
||||
{
|
||||
List<Track> trackList = (parentElement as ElementFolder).trackList;
|
||||
trackSwitch = new FlexibleInt();
|
||||
trackPercent = new FlexibleFloat();
|
||||
foreach (Track track in trackList)
|
||||
{
|
||||
TrackTimeSubmoduleMovable trackTimeSubmodule = track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
|
||||
trackSwitch.animations.Add(new AnimatedInt(trackTimeSubmodule.trackStartTime,
|
||||
trackList.IndexOf(track)));
|
||||
trackPercent.animations.Add(new AnimatedFloat(trackTimeSubmodule.trackStartTime,
|
||||
trackTimeSubmodule.trackEndTime, 0, 1, trackTimeSubmodule.animationCurveType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CrossTrackPoint
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new CrossTrackPoint_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM, trackSwitch, trackPercent)
|
||||
{
|
||||
MotionAngles = this.MotionAngles
|
||||
};
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
base.SetUpInspector();
|
||||
var container = inspector.GenerateContainer("Cross Track Point");
|
||||
var pointSettings = container.GenerateSubcontainer(3);
|
||||
var trackSwitchButton = inspector.GenerateButton(this, pointSettings, "Track Switch", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Track Switch", nameof(trackSwitch)).SetAsFlexibleInt();
|
||||
});
|
||||
var trackPercentButton = inspector.GenerateButton(this, pointSettings, "Track Percent", () =>
|
||||
{
|
||||
inspector.GenerateCompositeParameterWindow(this, "Track Percent", nameof(trackPercent)).SetAsFlexibleFloat();
|
||||
});
|
||||
var pasteTrackListButton = inspector.GenerateButton(this, pointSettings, "Paste Track List", PasteTrackList);
|
||||
|
||||
// 新增MotionAngles开关
|
||||
var motionAnglesToggle = inspector.GenerateToggle(this, pointSettings, "Motion With Angles", nameof(MotionAngles));
|
||||
|
||||
var generation = container.GenerateSubcontainer(3);
|
||||
var generateCameraButton = inspector.GenerateButton(this, generation, "Game Camera",
|
||||
() => GameCamera.GenerateElement("New Game Camera", Guid.NewGuid(), new List<string>(),
|
||||
true, this, GameCamera.CameraViewType.Perspective, 60, 10));
|
||||
var generateTrailButton = inspector.GenerateButton(this, generation, "Trail",
|
||||
() => Trail.GenerateElement("New Trail", Guid.NewGuid(), new List<string>(),
|
||||
true, this, 1, true, 1,
|
||||
AnimationCurve.Constant(0, 1, 1), ColorExtensions.DefaultGradient(), "", ""));
|
||||
var environmentObjectButton = inspector.GenerateButton(this, generation, "Environment Object",
|
||||
() => TemporaryObject.GenerateElement("New Environment Object", Guid.NewGuid(), new List<string>(),
|
||||
true, this));
|
||||
var generateParticleEmitterButton = inspector.GenerateButton(this, generation, "Generate Particle Emitter", () =>
|
||||
{
|
||||
ParticleEmitter.GenerateElement("New Particle Emitter", Guid.NewGuid(), new List<string>(), true,
|
||||
this, "", "",false,0, 1, ParticleSystemSimulationSpace.World,
|
||||
10, 5, 1, 1 ,true, Vector3.zero);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
if (trackPositioner != null && trackPositioner.motion != null)
|
||||
trackPositioner.motion.applyRotation = MotionAngles;
|
||||
|
||||
this.transform.eulerAngles = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class CrossTrackPoint_BM : GameElement_BM
|
||||
{
|
||||
public FlexibleInt trackSwitch;
|
||||
public FlexibleFloat trackPercent;
|
||||
public bool MotionAngles = false;
|
||||
|
||||
public CrossTrackPoint_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public CrossTrackPoint_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleInt trackSwitch, FlexibleFloat trackPercent)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.trackSwitch = trackSwitch;
|
||||
this.trackPercent = trackPercent;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
var element = CrossTrackPoint.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as ElementFolder, trackSwitch, trackPercent);
|
||||
matchedElement = element;
|
||||
// 还原MotionAngles
|
||||
if (element is CrossTrackPoint ctp && this != null)
|
||||
{
|
||||
ctp.MotionAngles = this.MotionAngles;
|
||||
}
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
var newElement = CrossTrackPoint.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as ElementFolder, trackSwitch, trackPercent);
|
||||
// 复制MotionAngles
|
||||
if (newElement is CrossTrackPoint ctp)
|
||||
{
|
||||
ctp.MotionAngles = this.MotionAngles;
|
||||
}
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TrackHeadPoint : GameElement, IHaveTimeDurationSubmodule
|
||||
{
|
||||
public Track track;
|
||||
public TrackTimeSubmoduleMovable trackTimeSubmoduleMovable;
|
||||
public SplinePositioner trackPositioner;
|
||||
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
public bool motionApplyRotation;
|
||||
public Vector3 motionEulerAngles;
|
||||
private float SongTime => EditorManager.instance.songInformation.songTime;
|
||||
|
||||
public static TrackHeadPoint GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, Track track, bool motionApplyRotation, Vector3 motionEulerAngles)
|
||||
{
|
||||
TrackHeadPoint head = Instantiate(EditorManager.instance.basePrefabs.emptyObject, track.transform).AddComponent<TrackHeadPoint>();
|
||||
|
||||
head.Initialize(elementName, id, tags, isFirstGenerated, track);
|
||||
head.track = track;
|
||||
head.trackPositioner = head.gameObject.AddComponent<SplinePositioner>();
|
||||
head.trackPositioner.spline = track.trackPathSubmodule.path;
|
||||
head.trackTimeSubmoduleMovable = track.trackTimeSubmodule as TrackTimeSubmoduleMovable;
|
||||
|
||||
head.motionApplyRotation = motionApplyRotation;
|
||||
head.trackPositioner.motion.applyRotation = motionApplyRotation;
|
||||
head.motionEulerAngles = motionEulerAngles;
|
||||
head.trackPositioner.motion.rotationOffset = motionEulerAngles;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (track.timeDurationSubmodule.CheckTimeInDuration(SongTime))
|
||||
{
|
||||
trackPositioner.SetPercent(trackTimeSubmoduleMovable.headPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TrackHeadPoint
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
// 保存MotionAngles到BM
|
||||
matchedBM = new TrackHeadPoint_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
motionApplyRotation, motionEulerAngles);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Track Percent Point");
|
||||
var motionAngles0 = container.GenerateSubcontainer(3);
|
||||
var motionAnglesApplyToggle = inspector.GenerateToggle(this, motionAngles0, "Motion With Angles", nameof(motionApplyRotation))
|
||||
.AddListenerFunction(() => trackPositioner.motion.applyRotation = motionApplyRotation);
|
||||
var motionAngles1 = container.GenerateSubcontainer(1);
|
||||
var motionAnglesValueInputField = inspector.GenerateVector3InputField(this, motionAngles1, "Motion Angles", nameof(motionEulerAngles))
|
||||
.AddListenerFunction(()=> trackPositioner.motion.rotationOffset = motionEulerAngles);
|
||||
|
||||
var generation = container.GenerateSubcontainer(3);
|
||||
var generateTrailButton = inspector.GenerateButton(this, generation, "Generate Trail", () =>
|
||||
{
|
||||
Trail.GenerateElement("New Trail", Guid.NewGuid(), new List<string>(), true,
|
||||
this, 1, true, 1,
|
||||
AnimationCurve.Constant(0, 1, 1), ColorExtensions.DefaultGradient(), "", "");
|
||||
});
|
||||
var environmentObjectButton = inspector.GenerateButton(this, generation, "Environment Object",
|
||||
() => TemporaryObject.GenerateElement("New Environment Object", Guid.NewGuid(), new List<string>(),
|
||||
true, this));
|
||||
var generateParticleEmitterButton = inspector.GenerateButton(this, generation, "Generate Particle Emitter", () =>
|
||||
{
|
||||
ParticleEmitter.GenerateElement("New Particle Emitter", Guid.NewGuid(), new List<string>(), true,
|
||||
this, "", "",false,0, 1, ParticleSystemSimulationSpace.World,
|
||||
10, 5, 1, 1 ,true, Vector3.zero);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackHeadPoint_BM : GameElement_BM
|
||||
{
|
||||
// 新增属性
|
||||
public bool motionApplyRotation = false;
|
||||
public Vector3 motionEulerAngles = Vector3.zero;
|
||||
|
||||
public TrackHeadPoint_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackHeadPoint_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, bool motionApplyRotation, Vector3 motionEulerAngles)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.motionApplyRotation = motionApplyRotation;
|
||||
this.motionEulerAngles = motionEulerAngles;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = TrackHeadPoint.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, motionApplyRotation, motionEulerAngles);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return TrackHeadPoint.GenerateElement(elementName, Guid.NewGuid(), tags,
|
||||
false, parent as Track, motionApplyRotation, motionEulerAngles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Lean.Pool;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
/// <summary>
|
||||
/// 在轨道上根据百分比进行运动的点
|
||||
/// </summary>
|
||||
public partial class TrackPercentPoint : GameElement, IHaveTimeDurationSubmodule
|
||||
{
|
||||
public Track track;
|
||||
public SplinePositioner trackPositioner;
|
||||
public FlexibleFloat trackPercent;
|
||||
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
|
||||
public bool MotionAngles = false;
|
||||
|
||||
public static TrackPercentPoint GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated,
|
||||
Track track, FlexibleFloat trackPercent)
|
||||
{
|
||||
TrackPercentPoint point = Instantiate(EditorManager.instance.basePrefabs.emptyObject, track.transform)
|
||||
.AddComponent<TrackPercentPoint>();
|
||||
|
||||
point.Initialize(elementName, id, tags, isFirstGenerated, track);
|
||||
point.track = track;
|
||||
point.trackPositioner = point.gameObject.AddComponent<SplinePositioner>();
|
||||
point.trackPositioner.spline = track.trackPathSubmodule.path;
|
||||
point.trackPercent = trackPercent;
|
||||
|
||||
point.trackPositioner.motion.rotationOffset = Vector3.zero;
|
||||
point.trackPositioner.motion.applyRotation = false;
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (trackPercent.animations.Count > 0)
|
||||
{
|
||||
trackPercent.UpdateFlexibleFloat(EditorManager.instance.songInformation.songTime);
|
||||
if (trackPercent.returnType == FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
float finalValue = trackPercent.value;
|
||||
if (finalValue > 1 && finalValue > Mathf.Floor(finalValue)) finalValue -= Mathf.Floor(finalValue);
|
||||
|
||||
|
||||
trackPositioner.SetPercent(finalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TrackPercentPoint
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackPercentPoint_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM,
|
||||
trackPercent.ConvertToBM());
|
||||
|
||||
((TrackPercentPoint_BM)matchedBM).MotionAngles = this.MotionAngles;
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Track Percent Point");
|
||||
var pointSettings = container.GenerateSubcontainer(3);
|
||||
var trackPercentButton = inspector.GenerateButton(this, pointSettings, "Track Percent",
|
||||
() => { inspector.GenerateCompositeParameterWindow(this, "Track Percent", nameof(trackPercent)).SetAsFlexibleFloat(); });
|
||||
|
||||
// 新增MotionAngles开关
|
||||
var motionAnglesToggle = inspector.GenerateToggle(this, pointSettings, "Motion With Angles", nameof(MotionAngles));
|
||||
|
||||
var generation = container.GenerateSubcontainer(3);
|
||||
var generateTrailButton = inspector.GenerateButton(this, generation, "Generate Trail", () =>
|
||||
{
|
||||
Trail.GenerateElement("New Trail", Guid.NewGuid(), new List<string>(), true,
|
||||
this, 1, true, 1,
|
||||
AnimationCurve.Constant(0, 1, 1), ColorExtensions.DefaultGradient(), "", "");
|
||||
});
|
||||
var environmentObjectButton = inspector.GenerateButton(this, generation, "Environment Object",
|
||||
() => TemporaryObject.GenerateElement("New Environment Object", Guid.NewGuid(), new List<string>(),
|
||||
true, this));
|
||||
var generateParticleEmitterButton = inspector.GenerateButton(this, generation, "Generate Particle Emitter", () =>
|
||||
{
|
||||
ParticleEmitter.GenerateElement("New Particle Emitter", Guid.NewGuid(), new List<string>(), true,
|
||||
this, "", "", false, 0, 1, ParticleSystemSimulationSpace.World,
|
||||
10, 5, 1, 1, true, Vector3.zero);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
this.transform.eulerAngles = Vector3.zero;
|
||||
if (trackPositioner != null && trackPositioner.motion != null)
|
||||
trackPositioner.motion.applyRotation = MotionAngles;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackPercentPoint_BM : GameElement_BM
|
||||
{
|
||||
public FlexibleFloat_BM trackPercent;
|
||||
public bool MotionAngles = false;
|
||||
|
||||
public TrackPercentPoint_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackPercentPoint_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM trackPercent)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.trackPercent = trackPercent;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
var element = TrackPercentPoint.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, trackPercent.ConvertToGameType());
|
||||
matchedElement = element;
|
||||
// 还原MotionAngles
|
||||
if (element is TrackPercentPoint tpp && this != null)
|
||||
{
|
||||
tpp.MotionAngles = this.MotionAngles;
|
||||
}
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
var newElement = TrackPercentPoint.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as Track, trackPercent.ConvertToGameType());
|
||||
// 复制MotionAngles
|
||||
if (newElement is TrackPercentPoint tpp)
|
||||
{
|
||||
tpp.MotionAngles = this.MotionAngles;
|
||||
}
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TrackPathSubmodule : TrackSubmodule
|
||||
{
|
||||
public SplineComputer path;
|
||||
public SplineRenderer trackDisplay;
|
||||
public List<PathNode> pathNodeList;
|
||||
|
||||
public Track.TrackSpaceType trackSpaceType;
|
||||
public Track.TrackSamplingType trackSamplingType;
|
||||
public bool isClosed;
|
||||
|
||||
public bool isShowingDisplay;
|
||||
|
||||
public TrackPathSubmodule(Track track, Track.TrackSpaceType trackSpaceType,
|
||||
Track.TrackSamplingType trackSamplingType, bool isClosed, bool isShowingDisplay) : base(track)
|
||||
{
|
||||
this.path = track.AddComponent<SplineComputer>();
|
||||
|
||||
this.pathNodeList = new List<PathNode>();
|
||||
this.trackSpaceType = trackSpaceType;
|
||||
this.trackSamplingType = trackSamplingType;
|
||||
this.isClosed = isClosed;
|
||||
|
||||
this.path.sampleRate = 16;
|
||||
this.path.updateMode = SplineComputer.UpdateMode.LateUpdate;
|
||||
SetUpSplineComputer(this.trackSpaceType, this.trackSamplingType);
|
||||
//闭合路径在PathNode生成时执行,在初始化的情况下,PathNode数量为0,不会执行闭合操作
|
||||
|
||||
this.isShowingDisplay = isShowingDisplay;
|
||||
this.trackDisplay = UnityEngine.Object.Instantiate(EditorManager.instance.basePrefabs.trackDisplay, track.transform).GetComponent<SplineRenderer>();
|
||||
this.trackDisplay.spline = path;
|
||||
this.trackDisplay.size = 0.1f;
|
||||
|
||||
this.SetDisplay(isShowingDisplay);
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.track.trackPathSubmodule = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TrackPathSubmodule
|
||||
{
|
||||
|
||||
private void SetUpSplineComputer(Track.TrackSpaceType trackSpaceType, Track.TrackSamplingType trackSamplingType)
|
||||
{
|
||||
path.type = (Spline.Type)trackSpaceType;
|
||||
path.sampleMode = (SplineComputer.SampleMode)(int)trackSamplingType;
|
||||
path.space = SplineComputer.Space.Local;
|
||||
}
|
||||
|
||||
public void ClosePath()
|
||||
{
|
||||
if (isClosed && pathNodeList.Count > 2)
|
||||
{
|
||||
path.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Break();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTrackSpaceType(int spaceType)
|
||||
{
|
||||
int SpaceType = spaceType;
|
||||
if (spaceType == 2) SpaceType++;
|
||||
trackSpaceType = (Track.TrackSpaceType)SpaceType;
|
||||
path.type = (Spline.Type)SpaceType;
|
||||
}
|
||||
|
||||
public void SetPathNode(PathNode point)
|
||||
{
|
||||
path.SetPoint(point.index, point.node, SplineComputer.Space.Local);
|
||||
}
|
||||
|
||||
public void SetDisplay(bool isShowing)
|
||||
{
|
||||
this.isShowingDisplay = isShowing;
|
||||
trackDisplay.gameObject.SetActive(isShowing);
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
EditorRefresh();
|
||||
path.Rebuild(true);
|
||||
}
|
||||
public void EditorRefresh()
|
||||
{
|
||||
SetTrackSpaceType((int)trackSpaceType);
|
||||
SetUpSplineComputer(trackSpaceType, trackSamplingType);
|
||||
|
||||
|
||||
|
||||
ClosePath();
|
||||
}
|
||||
public void SortPathnodeInChildren()//emm待用吧
|
||||
{
|
||||
Debug.Log("TrackSort");
|
||||
track.childElementList.Sort((x, y) =>
|
||||
{
|
||||
// 处理两个都是索引类的情况
|
||||
if (x is PathNode idxX && y is PathNode idxY)
|
||||
return idxX.index.CompareTo(idxY.index);
|
||||
|
||||
// 处理两个都是非索引类的情况 - 保持原顺序
|
||||
if (x is not PathNode && y is not PathNode)
|
||||
return 0;
|
||||
|
||||
// 混合类型处理:索引类排在前面
|
||||
return x is PathNode ? 1 : -1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class TrackPathSubmodule
|
||||
{
|
||||
public void SetPathPoints()
|
||||
{
|
||||
path.SetPoints(new SplinePoint[0]);
|
||||
foreach (var pathNode in pathNodeList)
|
||||
{
|
||||
SetPathNode(pathNode);
|
||||
}
|
||||
}
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackPathSubmodule_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Track Path");
|
||||
var trackPathSubmoduleSettings = container.GenerateSubcontainer(3);
|
||||
var trackSpaceDropdown =
|
||||
inspector.GenerateDropdown(this, trackPathSubmoduleSettings, "Space Type", typeof(Track.TrackSpaceType), nameof(trackSpaceType));
|
||||
var trackSamplingDropdown =
|
||||
inspector.GenerateDropdown(this, trackPathSubmoduleSettings, "Sampling Type", typeof(Track.TrackSamplingType), nameof(trackSamplingType));
|
||||
var isClosedToggle =
|
||||
inspector.GenerateToggle(this, trackPathSubmoduleSettings, "Is Closed", nameof(isClosed))
|
||||
.AddListenerFunction(ClosePath);
|
||||
var generatePathNodeButton = inspector.GenerateButton(this, trackPathSubmoduleSettings, "Generate Path Node", () =>
|
||||
{
|
||||
PathNode.GenerateElement("New Path Node", Guid.NewGuid(), new List<string>(), true, track, true);
|
||||
});
|
||||
var showDisplayToggle = inspector.GenerateToggle(this, trackPathSubmoduleSettings, "Show Display", nameof(isShowingDisplay))
|
||||
.AddListenerFunction(() => SetDisplay(isShowingDisplay));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackPathSubmodule_BM : Submodule_BM
|
||||
{
|
||||
public Track.TrackSpaceType trackSpaceType;
|
||||
public Track.TrackSamplingType trackSamplingType;
|
||||
public bool isClosed;
|
||||
public bool isShowingDisplay;
|
||||
|
||||
public TrackPathSubmodule_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public TrackPathSubmodule_BM(GameElement attachedElement, TrackPathSubmodule trackPathSubmodule) : base(
|
||||
attachedElement)
|
||||
{
|
||||
this.trackSpaceType = trackPathSubmodule.trackSpaceType;
|
||||
this.trackSamplingType = trackPathSubmodule.trackSamplingType;
|
||||
this.isClosed = trackPathSubmodule.isClosed;
|
||||
this.isShowingDisplay = trackPathSubmodule.isShowingDisplay;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed, isShowingDisplay);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed, isShowingDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,591 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using Inspector = Ichni.Editor.Inspector;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class TrackRendererSubmodule : TrackSubmodule
|
||||
{
|
||||
protected int submoduleNameIndex = 0;
|
||||
protected readonly string[] submoduleName = { "Auto Orient", "Path Generator", "Tube Generator", "Surface" };
|
||||
public MeshGenerator meshGenerator;
|
||||
public MeshRenderer meshRenderer;
|
||||
public Material renderMaterial;
|
||||
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
public bool enableEmission;
|
||||
public float emissionIntensity;
|
||||
public bool zWrite;
|
||||
public Vector2 uvScale;
|
||||
public Vector2 uvOffset;
|
||||
|
||||
public TrackRendererSubmodule(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
|
||||
Vector2 uvScale, Vector2 uvOffset) : base(track)
|
||||
{
|
||||
this.enableEmission = enableEmission;
|
||||
this.emissionIntensity = emissionIntensity;
|
||||
this.materialThemeBundleName = String.Empty;
|
||||
this.materialName = String.Empty;
|
||||
this.zWrite = zWrite;
|
||||
this.uvScale = uvScale;
|
||||
this.uvOffset = uvOffset;
|
||||
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.track.trackRendererSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyMaterial(string materialThemeBundleName, string materialName)
|
||||
{
|
||||
this.materialThemeBundleName = materialThemeBundleName;
|
||||
this.materialName = materialName;
|
||||
Material mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
|
||||
if (mat == null)
|
||||
{
|
||||
mat = EditorManager.instance.basePrefabs.defaultTrackMaterial;
|
||||
|
||||
}
|
||||
renderMaterial = mat;
|
||||
meshRenderer.material = renderMaterial;
|
||||
}
|
||||
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
// 使用 MaterialPropertyBlock 替代直接操作 material
|
||||
var block = new MaterialPropertyBlock();
|
||||
meshRenderer.GetPropertyBlock(block);
|
||||
|
||||
// ZWrite
|
||||
block.SetFloat("_ZWrite", zWrite ? 1f : 0f);
|
||||
|
||||
// Emission
|
||||
if (enableEmission)
|
||||
{
|
||||
meshRenderer.material.EnableKeyword("_EMISSION_ON");
|
||||
block.SetColor("_EmissionColor", Color.white * Mathf.Pow(2, emissionIntensity));
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.material.DisableKeyword("_EMISSION_ON");
|
||||
block.SetColor("_EmissionColor", Color.black);
|
||||
}
|
||||
|
||||
// UV(仍然直接设置到 meshGenerator)
|
||||
SetUV();
|
||||
|
||||
meshRenderer.SetPropertyBlock(block);
|
||||
|
||||
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable trackTimeSubmoduleMovable)
|
||||
{
|
||||
meshGenerator.clipFrom = trackTimeSubmoduleMovable.tailPercent;
|
||||
meshGenerator.clipTo = trackTimeSubmoduleMovable.headPercent;
|
||||
}
|
||||
else
|
||||
{
|
||||
meshGenerator.clipFrom = 0;
|
||||
meshGenerator.clipTo = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
base.OnDelete();
|
||||
Object.Destroy(meshGenerator);
|
||||
Object.Destroy(meshRenderer);
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
public partial class TrackRendererSubmodule
|
||||
{
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Track Renderer " + submoduleName[submoduleNameIndex] + (meshGenerator.baked ? " (Baked)" : ""));
|
||||
var zWriteSettings = container.GenerateSubcontainer(3);
|
||||
|
||||
var zWriteToggle =
|
||||
inspector.GenerateToggle(this, zWriteSettings, "Enable ZWrite", nameof(zWrite))
|
||||
.AddListenerFunction(SetEnableZWrite);
|
||||
var emissionSettings = container.GenerateSubcontainer(3);
|
||||
var enableEmissionToggle =
|
||||
inspector.GenerateToggle(this, emissionSettings, "Enable Emission", nameof(enableEmission))
|
||||
.AddListenerFunction(SetEnableEmission);
|
||||
var emissionIntensityInputField =
|
||||
inspector.GenerateInputField(this, emissionSettings, "Emission Intensity", nameof(emissionIntensity))
|
||||
.AddListenerFunction(SetEmissionIntensity);
|
||||
|
||||
var uvSettings = container.GenerateSubcontainer(1);
|
||||
var uvScaleInputField =
|
||||
inspector.GenerateVector2InputField(this, uvSettings, "UV Scale", nameof(uvScale))
|
||||
.AddListenerFunction(SetUV);
|
||||
var uvOffsetInputField =
|
||||
inspector.GenerateVector2InputField(this, uvSettings, "UV Offset", nameof(uvOffset))
|
||||
.AddListenerFunction(SetUV);
|
||||
|
||||
var materialSettings = container.GenerateSubcontainer(3);
|
||||
var themeBundleDropdown = inspector
|
||||
.GenerateDropdown(this, materialSettings, "Theme Bundle", ThemeBundleManager.instance.selectedThemeBundleList, nameof(materialThemeBundleName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(track));
|
||||
if (materialThemeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(materialThemeBundleName, out ThemeBundle themeBundle))
|
||||
{
|
||||
List<string> materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
|
||||
var objectNameDropdown = inspector.GenerateDropdown(this, materialSettings, "Material Name", materialNameList, nameof(materialName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(track));
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectNameDropdown = inspector.GenerateDropdown(this, materialSettings, "Material Name", new List<string>(), nameof(materialName));
|
||||
objectNameDropdown.dropdown.interactable = false;
|
||||
}
|
||||
|
||||
var applyMaterialButton = inspector.GenerateButton(this, materialSettings, "Apply Material", () => { ApplyMaterial(materialThemeBundleName, materialName); });
|
||||
|
||||
var delete = container.GenerateSubcontainer(3);
|
||||
var deleteButton = inspector.GenerateButton(this, delete, "Delete", () =>
|
||||
{
|
||||
Delete();
|
||||
track.trackRendererSubmodule = null;
|
||||
inspectorMain.SetInspector(track);
|
||||
track.Refresh();
|
||||
});
|
||||
}
|
||||
|
||||
protected void SetEnableEmission()
|
||||
{
|
||||
// 仅保留关键字控制,具体颜色由 Refresh 的 property block 控制
|
||||
if (enableEmission)
|
||||
{
|
||||
meshRenderer.material.EnableKeyword("_EMISSION_ON");
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.material.DisableKeyword("_EMISSION_ON");
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetEnableZWrite()
|
||||
{
|
||||
var block = new MaterialPropertyBlock();
|
||||
meshRenderer.GetPropertyBlock(block);
|
||||
|
||||
// ZWrite
|
||||
block.SetFloat("_ZWrite", zWrite ? 1f : 0f);
|
||||
meshRenderer.SetPropertyBlock(block);
|
||||
}
|
||||
|
||||
protected void SetEmissionIntensity()
|
||||
{
|
||||
var block = new MaterialPropertyBlock();
|
||||
meshRenderer.GetPropertyBlock(block);
|
||||
|
||||
|
||||
// Emission
|
||||
if (enableEmission)
|
||||
{
|
||||
meshRenderer.material.EnableKeyword("_EMISSION_ON");
|
||||
block.SetColor("_EmissionColor", Color.white * Mathf.Pow(2, emissionIntensity));
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.material.DisableKeyword("_EMISSION_ON");
|
||||
block.SetColor("_EmissionColor", Color.black);
|
||||
}
|
||||
meshRenderer.SetPropertyBlock(block);
|
||||
}
|
||||
|
||||
protected void SetUV()
|
||||
{
|
||||
meshGenerator.uvScale = uvScale;
|
||||
meshGenerator.uvOffset = uvOffset;
|
||||
}
|
||||
}
|
||||
|
||||
#region AutoOrient
|
||||
|
||||
public class TrackRendererSubmoduleAutoOrient : TrackRendererSubmodule
|
||||
{
|
||||
public SplineRenderer splineRenderer;
|
||||
|
||||
public TrackRendererSubmoduleAutoOrient(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
|
||||
Vector2 uvScale, Vector2 uvOffset, Material material = null) :
|
||||
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
|
||||
{
|
||||
this.splineRenderer = track.AddComponent<SplineRenderer>();
|
||||
this.meshRenderer = splineRenderer.GetComponent<MeshRenderer>();
|
||||
this.meshGenerator = splineRenderer;
|
||||
this.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrackMaterial : material;
|
||||
this.splineRenderer.spline = track.trackPathSubmodule.path;
|
||||
this.splineRenderer.doubleSided = true;
|
||||
this.splineRenderer.clipFrom = 0;
|
||||
this.splineRenderer.clipTo = 1;
|
||||
this.splineRenderer.updateMethod = SplineUser.UpdateMethod.Update;
|
||||
this.meshRenderer.material = renderMaterial;
|
||||
this.splineRenderer.color = Color.white;
|
||||
this.splineRenderer.uvRotation = 90;
|
||||
this.splineRenderer.uvMode = MeshGenerator.UVMode.UniformClip;
|
||||
this.submoduleNameIndex = 0; // Auto Orient is the first submodule
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackRendererSubmoduleAutoOrient_BM(attachedGameElement, this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackRendererSubmoduleAutoOrient_BM : Submodule_BM
|
||||
{
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
public bool enableEmission;
|
||||
public float emissionIntensity;
|
||||
public bool zWrite; // 新增
|
||||
public Vector2 uvScale = Vector2.one;
|
||||
public Vector2 uvOffset = Vector2.zero;
|
||||
|
||||
public TrackRendererSubmoduleAutoOrient_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackRendererSubmoduleAutoOrient_BM(GameElement attachedElement,
|
||||
TrackRendererSubmoduleAutoOrient trackRendererSubmodule) : base(attachedElement)
|
||||
{
|
||||
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
|
||||
materialName = trackRendererSubmodule.materialName;
|
||||
enableEmission = trackRendererSubmodule.enableEmission;
|
||||
emissionIntensity = trackRendererSubmodule.emissionIntensity;
|
||||
zWrite = trackRendererSubmodule.zWrite; // 新增
|
||||
uvScale = trackRendererSubmodule.uvScale;
|
||||
uvOffset = trackRendererSubmodule.uvOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PathGenerator
|
||||
|
||||
public class TrackRendererSubmodulePathGenerator : TrackRendererSubmodule
|
||||
{
|
||||
public PathGenerator pathGenerator;
|
||||
|
||||
public TrackRendererSubmodulePathGenerator(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
|
||||
Vector2 uvScale, Vector2 uvOffset, Material material = null) :
|
||||
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
|
||||
{
|
||||
this.pathGenerator = track.AddComponent<PathGenerator>();
|
||||
this.meshRenderer = pathGenerator.GetComponent<MeshRenderer>();
|
||||
this.meshGenerator = pathGenerator;
|
||||
this.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrackMaterial : material;
|
||||
this.pathGenerator.spline = track.trackPathSubmodule.path;
|
||||
this.pathGenerator.doubleSided = true;
|
||||
this.pathGenerator.clipFrom = 0;
|
||||
this.pathGenerator.clipTo = 1;
|
||||
this.pathGenerator.updateMethod = SplineUser.UpdateMethod.Update;
|
||||
this.meshRenderer.material = renderMaterial;
|
||||
this.pathGenerator.color = Color.white;
|
||||
this.pathGenerator.uvRotation = 90;
|
||||
this.pathGenerator.uvMode = MeshGenerator.UVMode.UniformClip;
|
||||
this.submoduleNameIndex = 1; // Path Generator is the second submodule
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackRendererSubmodulePathGenerator_BM(attachedGameElement, this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackRendererSubmodulePathGenerator_BM : Submodule_BM
|
||||
{
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
public bool enableEmission;
|
||||
public float emissionIntensity;
|
||||
public bool zWrite; // 新增
|
||||
public Vector2 uvScale = Vector2.one;
|
||||
public Vector2 uvOffset = Vector2.zero;
|
||||
|
||||
public TrackRendererSubmodulePathGenerator_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackRendererSubmodulePathGenerator_BM(GameElement attachedElement,
|
||||
TrackRendererSubmodulePathGenerator trackRendererSubmodule) : base(attachedElement)
|
||||
{
|
||||
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
|
||||
materialName = trackRendererSubmodule.materialName;
|
||||
enableEmission = trackRendererSubmodule.enableEmission;
|
||||
emissionIntensity = trackRendererSubmodule.emissionIntensity;
|
||||
zWrite = trackRendererSubmodule.zWrite; // 新增
|
||||
uvScale = trackRendererSubmodule.uvScale;
|
||||
uvOffset = trackRendererSubmodule.uvOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TubeGenerator
|
||||
|
||||
public class TrackRendererSubmoduleTubeGenerator : TrackRendererSubmodule
|
||||
{
|
||||
public TubeGenerator tubeGenerator;
|
||||
public int sideCount;
|
||||
|
||||
public TrackRendererSubmoduleTubeGenerator(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
|
||||
int sideCount, Vector2 uvScale, Vector2 uvOffset, Material material = null) :
|
||||
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
|
||||
{
|
||||
this.sideCount = sideCount;
|
||||
|
||||
this.tubeGenerator = track.AddComponent<TubeGenerator>();
|
||||
this.meshRenderer = tubeGenerator.GetComponent<MeshRenderer>();
|
||||
this.meshGenerator = tubeGenerator;
|
||||
this.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrackMaterial : material;
|
||||
this.tubeGenerator.spline = track.trackPathSubmodule.path;
|
||||
this.tubeGenerator.doubleSided = true;
|
||||
this.tubeGenerator.clipFrom = 0;
|
||||
this.tubeGenerator.clipTo = 1;
|
||||
this.tubeGenerator.updateMethod = SplineUser.UpdateMethod.Update;
|
||||
this.meshRenderer.material = renderMaterial;
|
||||
this.tubeGenerator.color = Color.white;
|
||||
this.tubeGenerator.uvRotation = 90;
|
||||
this.tubeGenerator.sides = sideCount;
|
||||
this.tubeGenerator.uvMode = MeshGenerator.UVMode.UniformClip;
|
||||
this.submoduleNameIndex = 2; // Tube Generator is the third submodule
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackRendererSubmoduleTubeGenerator_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Tube Settings");
|
||||
var tubeSettings = container.GenerateSubcontainer(3);
|
||||
var sideCountInputField =
|
||||
inspector.GenerateInputField(this, tubeSettings, "Side Count", nameof(sideCount))
|
||||
.AddListenerFunction(() => { tubeGenerator.sides = sideCount; });
|
||||
|
||||
base.SetUpInspector();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackRendererSubmoduleTubeGenerator_BM : Submodule_BM
|
||||
{
|
||||
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
public bool enableEmission;
|
||||
public float emissionIntensity;
|
||||
public bool zWrite; // 新增
|
||||
public int sideCount;
|
||||
public Vector2 uvScale = Vector2.one;
|
||||
public Vector2 uvOffset = Vector2.zero;
|
||||
|
||||
public TrackRendererSubmoduleTubeGenerator_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackRendererSubmoduleTubeGenerator_BM(GameElement attachedElement,
|
||||
TrackRendererSubmoduleTubeGenerator trackRendererSubmodule) : base(attachedElement)
|
||||
{
|
||||
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
|
||||
materialName = trackRendererSubmodule.materialName;
|
||||
enableEmission = trackRendererSubmodule.enableEmission;
|
||||
emissionIntensity = trackRendererSubmodule.emissionIntensity;
|
||||
zWrite = trackRendererSubmodule.zWrite; // 新增
|
||||
sideCount = trackRendererSubmodule.sideCount;
|
||||
uvScale = trackRendererSubmodule.uvScale;
|
||||
uvOffset = trackRendererSubmodule.uvOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleTubeGenerator(track, enableEmission, emissionIntensity, zWrite, sideCount, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleTubeGenerator(track, enableEmission, emissionIntensity, zWrite, sideCount, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Surface
|
||||
|
||||
public class TrackRendererSubmoduleSurface : TrackRendererSubmodule
|
||||
{
|
||||
public SurfaceGenerator surface;
|
||||
|
||||
public TrackRendererSubmoduleSurface(Track track, bool enableEmission, float emissionIntensity, bool zWrite,
|
||||
Vector2 uvScale, Vector2 uvOffset, Material material = null) :
|
||||
base(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset)
|
||||
{
|
||||
this.surface = track.AddComponent<SurfaceGenerator>();
|
||||
this.meshRenderer = surface.GetComponent<MeshRenderer>();
|
||||
this.meshGenerator = surface;
|
||||
this.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrackMaterial : material;
|
||||
this.surface.spline = track.trackPathSubmodule.path;
|
||||
this.surface.doubleSided = true;
|
||||
this.surface.clipFrom = 0;
|
||||
this.surface.clipTo = 1;
|
||||
this.surface.updateMethod = SplineUser.UpdateMethod.Update;
|
||||
this.meshRenderer.material = renderMaterial;
|
||||
this.surface.color = Color.white;
|
||||
this.surface.uvRotation = 90;
|
||||
this.surface.uvMode = MeshGenerator.UVMode.UniformClip;
|
||||
this.submoduleNameIndex = 3; // Surface is the fourth submodule
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new TrackRendererSubmoduleSurface_BM(attachedGameElement, this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackRendererSubmoduleSurface_BM : Submodule_BM
|
||||
{
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
public bool enableEmission;
|
||||
public float emissionIntensity;
|
||||
public bool zWrite; // 新增
|
||||
public Vector2 uvScale = Vector2.one;
|
||||
public Vector2 uvOffset = Vector2.zero;
|
||||
|
||||
public TrackRendererSubmoduleSurface_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackRendererSubmoduleSurface_BM(GameElement attachedElement,
|
||||
TrackRendererSubmoduleSurface trackRendererSubmodule) : base(attachedElement)
|
||||
{
|
||||
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
|
||||
materialName = trackRendererSubmodule.materialName;
|
||||
enableEmission = trackRendererSubmodule.enableEmission;
|
||||
emissionIntensity = trackRendererSubmodule.emissionIntensity;
|
||||
zWrite = trackRendererSubmodule.zWrite; // 新增
|
||||
uvScale = trackRendererSubmodule.uvScale;
|
||||
uvOffset = trackRendererSubmodule.uvOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackRendererSubmodule =
|
||||
new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity, zWrite, uvScale, uvOffset);
|
||||
if (materialName.Trim() != String.Empty)
|
||||
{
|
||||
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01fba1b4480fc4988be3f80598f285c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,299 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class TrackTimeSubmodule : TrackSubmodule
|
||||
{
|
||||
public float headPercent, tailPercent;
|
||||
|
||||
public TrackTimeSubmodule(Track track) : base(track)
|
||||
{
|
||||
if (!HaveSameSubmodule)
|
||||
{
|
||||
this.track.trackTimeSubmodule = this;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
#region Movable
|
||||
|
||||
public class TrackTimeSubmoduleMovable : TrackTimeSubmodule
|
||||
{
|
||||
public float trackStartTime;
|
||||
public float trackEndTime;
|
||||
public float trackTotalTime;
|
||||
public float visibleTrackTimeLength;
|
||||
public AnimationCurveType animationCurveType;
|
||||
//public bool isGoWithZ = false;
|
||||
public TrackTimeSubmoduleMovable(Track track, float trackStartTime, float trackEndTime,
|
||||
float visibleTrackTimeLength, AnimationCurveType animationCurveType) : base(track)
|
||||
{
|
||||
this.trackStartTime = trackStartTime;
|
||||
this.trackEndTime = trackEndTime;
|
||||
this.trackTotalTime = trackEndTime - trackStartTime;
|
||||
this.visibleTrackTimeLength = visibleTrackTimeLength;
|
||||
this.animationCurveType = animationCurveType;
|
||||
//timeDurationSubmodule 根据下辖Note的时间来设置
|
||||
}
|
||||
|
||||
public void UpdateTrackPart()
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
|
||||
headPercent = GetTrackPercent(songTime);
|
||||
tailPercent = GetTrackPercent(songTime - visibleTrackTimeLength);
|
||||
|
||||
if (track.trackRendererSubmodule != null)
|
||||
{
|
||||
track.trackRendererSubmodule.meshGenerator.clipFrom = tailPercent;
|
||||
track.trackRendererSubmodule.meshGenerator.clipTo = headPercent;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetTrackPercent(float songTimeInTime)
|
||||
{
|
||||
float per = AnimationCurveEvaluator.Evaluate(animationCurveType, (songTimeInTime - trackStartTime) / trackTotalTime);
|
||||
// return isGoWithZ ? GetSplineZPercent(Mathf.Clamp01(per)) : Mathf.Clamp01(per);
|
||||
return Mathf.Clamp01(per);
|
||||
}
|
||||
public float GetTrackPercentRaw(float songTimeInTime)
|
||||
{
|
||||
float per = AnimationCurveEvaluator.Evaluate(animationCurveType, (songTimeInTime - trackStartTime) / trackTotalTime);
|
||||
// return isGoWithZ ? GetSplineZPercent(Mathf.Clamp01(per)) : Mathf.Clamp01(per);
|
||||
return per;
|
||||
}
|
||||
// private float GetSplineZPercent(float percent)
|
||||
// {
|
||||
// var nodeList = track.trackPathSubmodule.pathNodeList;
|
||||
// int count = nodeList.Count;
|
||||
// if (count <= 2) return percent;
|
||||
|
||||
// float startZ = nodeList[0].transformSubmodule.currentPosition.z;
|
||||
// float endZ = nodeList[count - 1].transformSubmodule.currentPosition.z;
|
||||
// float needZ = Mathf.Lerp(startZ, endZ, percent);
|
||||
|
||||
// float outpercent = 0f;
|
||||
// float percentBetween = 1f / (count - 1);
|
||||
|
||||
// for (int i = 0; i < count - 1; i++)
|
||||
// {
|
||||
// float z0 = nodeList[i].transformSubmodule.currentPosition.z;
|
||||
// float z1 = nodeList[i + 1].transformSubmodule.currentPosition.z;
|
||||
|
||||
// // 如果 needZ 在当前区间内,做插值
|
||||
// if ((z0 <= needZ && needZ <= z1) || (z1 <= needZ && needZ <= z0))
|
||||
// {
|
||||
// float zDelta = z1 - z0;
|
||||
// if (Mathf.Approximately(zDelta, 0f)) return outpercent;
|
||||
// float t = (needZ - z0) / zDelta;
|
||||
// outpercent += percentBetween * Mathf.Clamp01(t);
|
||||
// return outpercent;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// outpercent += percentBetween;
|
||||
// }
|
||||
// }
|
||||
// // 如果没找到区间,返回 1f(已遍历所有节点)
|
||||
// return 1f;
|
||||
// }
|
||||
|
||||
public override void Refresh()
|
||||
|
||||
{
|
||||
trackTotalTime = trackEndTime - trackStartTime;
|
||||
UpdateTrackPart();
|
||||
|
||||
track.childElementList.ForEach(child =>
|
||||
{
|
||||
if (child is NoteBase note)
|
||||
{
|
||||
note.UpdateNoteInTrack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Beatmap.TrackTimeSubmoduleMovable_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Track Time Movable");
|
||||
var trackTimeSubmoduleSettings = container.GenerateSubcontainer(3);
|
||||
var startTimeInputField =
|
||||
inspector.GenerateInputField(this, trackTimeSubmoduleSettings, "Start Time", nameof(trackStartTime))
|
||||
.AddListenerFunction(RefreshChildren);
|
||||
var endTimeInputField = inspector.GenerateInputField(this, trackTimeSubmoduleSettings, "End Time", nameof(trackEndTime))
|
||||
.AddListenerFunction(RefreshChildren);
|
||||
var visibleTimeInputField =
|
||||
inspector.GenerateInputField(this, trackTimeSubmoduleSettings, "Visible Time Length", nameof(visibleTrackTimeLength));
|
||||
var animationCurveDropdown =
|
||||
inspector.GenerateDropdown(this, trackTimeSubmoduleSettings, "Animation Curve", typeof(AnimationCurveType), nameof(animationCurveType))
|
||||
.AddListenerFunction(RefreshChildren);
|
||||
// var isGoWithZToggle =
|
||||
// inspector.GenerateToggle(this, trackTimeSubmoduleSettings, "Go With Z", nameof(isGoWithZ));
|
||||
var deleteButton = inspector.GenerateButton(this, trackTimeSubmoduleSettings, "Delete", () =>
|
||||
{
|
||||
Delete();
|
||||
track.trackTimeSubmodule = null;
|
||||
inspectorMain.SetInspector(track);
|
||||
track.Refresh();
|
||||
});
|
||||
}
|
||||
|
||||
private void RefreshChildren()
|
||||
{
|
||||
track.childElementList.ForEach(child =>
|
||||
{
|
||||
if (child is NoteBase note)
|
||||
{
|
||||
note.UpdateNoteInTrack();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackTimeSubmoduleMovable_BM : Submodule_BM
|
||||
{
|
||||
public float trackStartTime;
|
||||
public float trackEndTime;
|
||||
public float visibleTrackTimeLength;
|
||||
public AnimationCurveType animationCurveType;
|
||||
|
||||
public TrackTimeSubmoduleMovable_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackTimeSubmoduleMovable_BM(GameElement attachedElement, TrackTimeSubmoduleMovable trackTimeSubmoduleMovable) : base(attachedElement)
|
||||
{
|
||||
trackStartTime = trackTimeSubmoduleMovable.trackStartTime;
|
||||
trackEndTime = trackTimeSubmoduleMovable.trackEndTime;
|
||||
visibleTrackTimeLength = trackTimeSubmoduleMovable.visibleTrackTimeLength;
|
||||
animationCurveType = trackTimeSubmoduleMovable.animationCurveType;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackTimeSubmodule = new TrackTimeSubmoduleMovable(track, trackStartTime, trackEndTime, visibleTrackTimeLength, animationCurveType);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackTimeSubmodule = new TrackTimeSubmoduleMovable(track, trackStartTime, trackEndTime, visibleTrackTimeLength, animationCurveType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
public class TrackTimeSubmoduleStatic : TrackTimeSubmodule
|
||||
{
|
||||
public float trackTotalTime;
|
||||
public AnimationCurveType animationCurveType;
|
||||
|
||||
public TrackTimeSubmoduleStatic(Track track, float trackTotalTime, AnimationCurveType animationCurveType) :
|
||||
base(track)
|
||||
{
|
||||
this.trackTotalTime = trackTotalTime;
|
||||
this.animationCurveType = animationCurveType;
|
||||
this.headPercent = 0;
|
||||
this.tailPercent = 1;
|
||||
//timeDurationSubmodule 根据下辖Note的时间来设置
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
if (track.trackRendererSubmodule != null)
|
||||
{
|
||||
track.trackRendererSubmodule.meshGenerator.clipFrom = tailPercent;
|
||||
track.trackRendererSubmodule.meshGenerator.clipTo = headPercent;
|
||||
}
|
||||
track.childElementList.ForEach(child =>
|
||||
{
|
||||
if (child is NoteBase note)
|
||||
{
|
||||
note.UpdateNoteInTrack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Beatmap.TrackTimeSubmoduleStatic_BM(attachedGameElement, this);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Track Time Static");
|
||||
var trackTimeSubmoduleSettings = container.GenerateSubcontainer(3);
|
||||
var totalTimeInputField =
|
||||
inspector.GenerateInputField(this, trackTimeSubmoduleSettings, "Total Time", nameof(trackTotalTime));
|
||||
var animationCurveDropdown =
|
||||
inspector.GenerateDropdown(this, trackTimeSubmoduleSettings, "Animation Curve", typeof(AnimationCurveType), nameof(animationCurveType));
|
||||
var deleteButton = inspector.GenerateButton(this, trackTimeSubmoduleSettings, "Delete", () =>
|
||||
{
|
||||
Delete();
|
||||
track.trackTimeSubmodule = null;
|
||||
inspectorMain.SetInspector(track);
|
||||
track.Refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class TrackTimeSubmoduleStatic_BM : Submodule_BM
|
||||
{
|
||||
public float trackTotalTime;
|
||||
public AnimationCurveType animationCurveType;
|
||||
|
||||
public TrackTimeSubmoduleStatic_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackTimeSubmoduleStatic_BM(GameElement attachedElement, TrackTimeSubmoduleStatic trackTimeSubmoduleStatic) : base(attachedElement)
|
||||
{
|
||||
trackTotalTime = trackTimeSubmoduleStatic.trackTotalTime;
|
||||
animationCurveType = trackTimeSubmoduleStatic.animationCurveType;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
||||
Track track = attachedElement as Track;
|
||||
track.trackTimeSubmodule = new TrackTimeSubmoduleStatic(track, trackTotalTime, animationCurveType);
|
||||
}
|
||||
|
||||
public override void DuplicateBM(GameElement attached)
|
||||
{
|
||||
Track track = attached as Track;
|
||||
track.trackTimeSubmodule = new TrackTimeSubmoduleStatic(track, trackTotalTime, animationCurveType);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91eb99ad678b44efe90bd2699a9502f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,285 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class ObjectTracker : GameElement
|
||||
{
|
||||
public Track track;
|
||||
public ObjectController objectController;
|
||||
public GameObject objectPrefab;
|
||||
private List<string> themeBundleList;
|
||||
private List<string> objectNameList;
|
||||
public string themeBundleName;
|
||||
public string objectName;
|
||||
|
||||
public float playTime;
|
||||
public float stopTime;
|
||||
|
||||
public int spawnCount;
|
||||
public Vector2 positionOffsetMin = Vector2.zero;
|
||||
public Vector2 positionOffsetMax = Vector2.zero;
|
||||
public string customPositionRuleName;
|
||||
|
||||
public bool applyRotationOffset = false;
|
||||
public Vector3 rotationOffsetMin = Vector3.zero;
|
||||
public Vector3 rotationOffsetMax = Vector3.zero;
|
||||
public string customRotationRuleName;
|
||||
|
||||
public bool applyScaleOffset = false;
|
||||
public Vector3 scaleOffsetMin = Vector3.one;
|
||||
public Vector3 scaleOffsetMax = Vector3.one;
|
||||
public string customScaleRuleName;
|
||||
|
||||
public static ObjectTracker GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, Track track, string themeBundleName, string objectName, int spawnCount,
|
||||
Vector2 positionOffsetMin, Vector2 positionOffsetMax, string customPositionRuleName,
|
||||
bool applyRotationOffset, Vector3 rotationOffsetMin, Vector3 rotationOffsetMax, string customRotationRuleName,
|
||||
bool applyScaleOffset, Vector3 scaleOffsetMin, Vector3 scaleOffsetMax, string customScaleRuleName)
|
||||
{
|
||||
ObjectTracker objectTracker = Instantiate(EditorManager.instance.basePrefabs.objectTracker, track.transform).GetComponent<ObjectTracker>();
|
||||
objectTracker.objectPrefab = ThemeBundleManager.instance.GetObject<GameObject>(themeBundleName, objectName);
|
||||
|
||||
objectTracker.objectController.objects = new[] { objectTracker.objectPrefab };
|
||||
objectTracker.Initialize(elementName, id, tags, isFirstGenerated, track);
|
||||
objectTracker.track = track;
|
||||
objectTracker.objectController.spline = track.trackPathSubmodule.path;
|
||||
objectTracker.themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
||||
objectTracker.objectNameList = new List<string>();
|
||||
objectTracker.themeBundleName = themeBundleName;
|
||||
objectTracker.objectName = objectName;
|
||||
objectTracker.SetSpawnSettings(spawnCount,
|
||||
positionOffsetMin, positionOffsetMax, customPositionRuleName,
|
||||
applyRotationOffset, rotationOffsetMin, rotationOffsetMax, customRotationRuleName,
|
||||
applyScaleOffset, scaleOffsetMin, scaleOffsetMax, customScaleRuleName);
|
||||
return objectTracker;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
if (playTime > songTime || stopTime < songTime)
|
||||
{
|
||||
if (objectController.enabled)
|
||||
{
|
||||
objectController.enabled = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!objectController.enabled)
|
||||
{
|
||||
objectController.enabled = true;
|
||||
objectController.Spawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Object Tracker");
|
||||
var generate = container.GenerateSubcontainer(3);
|
||||
var themeBundleDropdown =
|
||||
inspector.GenerateDropdown(this, generate, "Theme Bundle", themeBundleList, nameof(themeBundleName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
if (themeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(themeBundleName, out ThemeBundle themeBundle))
|
||||
{
|
||||
objectNameList = themeBundle.assetList_GameObject.ConvertAll(x => x.name);
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, generate, "Object Name", objectNameList, nameof(objectName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, generate, "Object Name", new List<string>(), nameof(objectName));
|
||||
objectNameDropdown.dropdown.interactable = false;
|
||||
} // 如果没有选择主题包,则物体名称下拉框不可用
|
||||
|
||||
var setButton = inspector.GenerateButton(this, generate, "Generate", () =>
|
||||
{
|
||||
objectController.Clear();
|
||||
this.objectPrefab = ThemeBundleManager.instance.GetObject<GameObject>(themeBundleName, objectName);
|
||||
this.objectController.objects = new[] { this.objectPrefab };
|
||||
this.objectController.Spawn();
|
||||
});
|
||||
|
||||
if (themeBundleName == String.Empty || objectName == String.Empty)
|
||||
{
|
||||
setButton.button.interactable = false;
|
||||
}
|
||||
|
||||
var spawnSettings = container.GenerateSubcontainer(3);
|
||||
inspector.GenerateInputField(this, spawnSettings, "Spawn Count", nameof(spawnCount))
|
||||
.AddListenerFunction(() => objectController.spawnCount = spawnCount);
|
||||
inspector.GenerateInputField(this, spawnSettings, "Play Time", nameof(playTime));
|
||||
inspector.GenerateInputField(this, spawnSettings, "Stop Time", nameof(stopTime));
|
||||
var posSettings = container.GenerateSubcontainer(1);
|
||||
inspector.GenerateVector2InputField(this, posSettings, "Position Offset Min", nameof(positionOffsetMin))
|
||||
.AddListenerFunction(() => objectController.minOffset = positionOffsetMin);
|
||||
inspector.GenerateVector2InputField(this, posSettings, "Position Offset Max", nameof(positionOffsetMax))
|
||||
.AddListenerFunction(() => objectController.maxOffset = positionOffsetMax);
|
||||
//inspector.GenerateInputField(this, posSettings, "Custom Position Rule Name", nameof(customPositionRuleName));
|
||||
var rotSettings = container.GenerateSubcontainer(1);
|
||||
inspector.GenerateToggle(this, rotSettings, "Apply Rotation Offset", nameof(applyRotationOffset))
|
||||
.AddListenerFunction(() => objectController.applyRotation = applyRotationOffset);
|
||||
inspector.GenerateVector3InputField(this, rotSettings, "Rotation Offset Min", nameof(rotationOffsetMin))
|
||||
.AddListenerFunction(() => objectController.minRotation = rotationOffsetMin);
|
||||
inspector.GenerateVector3InputField(this, rotSettings, "Rotation Offset Max", nameof(rotationOffsetMax))
|
||||
.AddListenerFunction(() => objectController.maxRotation = rotationOffsetMax);
|
||||
//inspector.GenerateInputField(this, rotSettings, "Custom Rotation Rule Name", nameof(customRotationRuleName));
|
||||
var scaleSettings = container.GenerateSubcontainer(1);
|
||||
inspector.GenerateToggle(this, scaleSettings, "Apply Scale Offset", nameof(applyScaleOffset))
|
||||
.AddListenerFunction(() => objectController.applyScale = applyScaleOffset);
|
||||
inspector.GenerateVector3InputField(this, scaleSettings, "Scale Offset Min", nameof(scaleOffsetMin))
|
||||
.AddListenerFunction(() => objectController.minScaleMultiplier = scaleOffsetMin);
|
||||
inspector.GenerateVector3InputField(this, scaleSettings, "Scale Offset Max", nameof(scaleOffsetMax))
|
||||
.AddListenerFunction(() => objectController.maxScaleMultiplier = scaleOffsetMax);
|
||||
//inspector.GenerateInputField(this, scaleSettings, "Custom Scale Rule Name", nameof(customScaleRuleName));
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Beatmap.ObjectTracker_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM,
|
||||
themeBundleName, objectName,
|
||||
playTime, stopTime,
|
||||
spawnCount,
|
||||
positionOffsetMin, positionOffsetMax, customPositionRuleName,
|
||||
applyRotationOffset, rotationOffsetMin, rotationOffsetMax, customRotationRuleName,
|
||||
applyScaleOffset, scaleOffsetMin, scaleOffsetMax, customScaleRuleName);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ObjectTracker
|
||||
{
|
||||
public void SetSpawnSettings(int spawnCount,
|
||||
Vector2 positionOffsetMin, Vector2 positionOffsetMax, string customPositionRuleName,
|
||||
bool applyRotationOffset, Vector3 rotationOffsetMin, Vector3 rotationOffsetMax, string customRotationRuleName,
|
||||
bool applyScaleOffset, Vector3 scaleOffsetMin, Vector3 scaleOffsetMax, string customScaleRuleName)
|
||||
{
|
||||
this.spawnCount = spawnCount;
|
||||
this.positionOffsetMin = positionOffsetMin;
|
||||
this.positionOffsetMax = positionOffsetMax;
|
||||
this.customPositionRuleName = customPositionRuleName;
|
||||
this.applyRotationOffset = applyRotationOffset;
|
||||
this.rotationOffsetMin = rotationOffsetMin;
|
||||
this.rotationOffsetMax = rotationOffsetMax;
|
||||
this.customRotationRuleName = customRotationRuleName;
|
||||
this.applyScaleOffset = applyScaleOffset;
|
||||
this.scaleOffsetMin = scaleOffsetMin;
|
||||
this.scaleOffsetMax = scaleOffsetMax;
|
||||
this.customScaleRuleName = customScaleRuleName;
|
||||
|
||||
objectController.spawnCount = spawnCount;
|
||||
objectController.minOffset = positionOffsetMin;
|
||||
objectController.maxOffset = positionOffsetMax;
|
||||
|
||||
objectController.applyRotation = applyRotationOffset;
|
||||
objectController.minRotation = rotationOffsetMin;
|
||||
objectController.maxRotation = rotationOffsetMax;
|
||||
|
||||
objectController.applyScale = applyScaleOffset;
|
||||
objectController.minScaleMultiplier = scaleOffsetMin;
|
||||
objectController.maxScaleMultiplier = scaleOffsetMax;
|
||||
|
||||
objectController.Spawn();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class ObjectTracker_BM : GameElement_BM
|
||||
{
|
||||
public string themeBundleName;
|
||||
public string objectName;
|
||||
|
||||
public float playTime;
|
||||
public float stopTime;
|
||||
|
||||
public int spawnCount;
|
||||
public Vector2 positionOffsetMin;
|
||||
public Vector2 positionOffsetMax;
|
||||
public string customPositionRuleName;
|
||||
|
||||
public bool applyRotationOffset;
|
||||
public Vector3 rotationOffsetMin;
|
||||
public Vector3 rotationOffsetMax;
|
||||
public string customRotationRuleName;
|
||||
|
||||
public bool applyScaleOffset;
|
||||
public Vector3 scaleOffsetMin;
|
||||
public Vector3 scaleOffsetMax;
|
||||
public string customScaleRuleName;
|
||||
|
||||
public ObjectTracker_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ObjectTracker_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
string themeBundleName, string objectName,
|
||||
float playTime, float stopTime,
|
||||
int spawnCount,
|
||||
Vector2 positionOffsetMin, Vector2 positionOffsetMax, string customPositionRuleName,
|
||||
bool applyRotationOffset, Vector3 rotationOffsetMin, Vector3 rotationOffsetMax, string customRotationRuleName,
|
||||
bool applyScaleOffset, Vector3 scaleOffsetMin, Vector3 scaleOffsetMax, string customScaleRuleName)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.themeBundleName = themeBundleName;
|
||||
this.objectName = objectName;
|
||||
|
||||
this.playTime = playTime;
|
||||
this.stopTime = stopTime;
|
||||
|
||||
this.spawnCount = spawnCount;
|
||||
this.positionOffsetMin = positionOffsetMin;
|
||||
this.positionOffsetMax = positionOffsetMax;
|
||||
this.customPositionRuleName = customPositionRuleName;
|
||||
|
||||
this.applyRotationOffset = applyRotationOffset;
|
||||
this.rotationOffsetMin = rotationOffsetMin;
|
||||
this.rotationOffsetMax = rotationOffsetMax;
|
||||
this.customRotationRuleName = customRotationRuleName;
|
||||
|
||||
this.applyScaleOffset = applyScaleOffset;
|
||||
this.scaleOffsetMin = scaleOffsetMin;
|
||||
this.scaleOffsetMax = scaleOffsetMax;
|
||||
this.customScaleRuleName = customScaleRuleName;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = ObjectTracker.GenerateElement(
|
||||
elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track,
|
||||
themeBundleName, objectName,
|
||||
spawnCount,
|
||||
positionOffsetMin, positionOffsetMax, customPositionRuleName,
|
||||
applyRotationOffset, rotationOffsetMin, rotationOffsetMax, customRotationRuleName,
|
||||
applyScaleOffset, scaleOffsetMin, scaleOffsetMax, customScaleRuleName);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return ObjectTracker.GenerateElement(
|
||||
elementName, Guid.NewGuid(), new List<string>(tags), false,
|
||||
attached as Track,
|
||||
themeBundleName, objectName,
|
||||
spawnCount,
|
||||
positionOffsetMin, positionOffsetMax, customPositionRuleName,
|
||||
applyRotationOffset, rotationOffsetMin, rotationOffsetMax, customRotationRuleName,
|
||||
applyScaleOffset, scaleOffsetMin, scaleOffsetMax, customScaleRuleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dreamteck.Splines;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class ParticleTracker : GameElement, IHaveParticles, IHaveColorSubmodule
|
||||
{
|
||||
public Track track;
|
||||
public ParticleController particleController;
|
||||
private IHaveParticles particlesContainer => this;
|
||||
public ParticleSystem particle { get; set; }
|
||||
public ColorSubmodule colorSubmodule { get; set; }
|
||||
public bool haveBaseColor => true;
|
||||
public bool haveEmissionColor => true;
|
||||
|
||||
private List<string> themeBundleList;
|
||||
private List<string> materialNameList;
|
||||
public string themeBundleName;
|
||||
public string materialName;
|
||||
|
||||
public bool prewarm;
|
||||
public float playTime;
|
||||
public float stopTime;
|
||||
|
||||
public bool is3D;
|
||||
public float width;
|
||||
public Vector3 extendDirection;
|
||||
|
||||
public float density;
|
||||
public float lifeTime;
|
||||
|
||||
public bool isAutoOrient;
|
||||
public Vector3 particleRotation;
|
||||
|
||||
|
||||
public static ParticleTracker GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, Track track, string themeBundleName, string materialName,
|
||||
bool prewarm, float playTime, float stopTime,
|
||||
bool is3D, float width, Vector3 extendDirection,
|
||||
float density, float lifeTime,
|
||||
bool isAutoOrient, Vector3 particleRotation)
|
||||
{
|
||||
ParticleTracker particleTracker = Instantiate(EditorManager.instance.basePrefabs.particleTracker, track.transform)
|
||||
.GetComponent<ParticleTracker>();
|
||||
particleTracker.particle = particleTracker.GetComponentInChildren<ParticleSystem>();
|
||||
particleTracker.Initialize(elementName, id, tags, isFirstGenerated, track);
|
||||
particleTracker.track = track;
|
||||
particleTracker.particleController.spline = track.trackPathSubmodule.path;
|
||||
particleTracker.playTime = playTime;
|
||||
particleTracker.stopTime = stopTime;
|
||||
particleTracker.themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
||||
particleTracker.materialNameList = new List<string>();
|
||||
particleTracker.themeBundleName = themeBundleName;
|
||||
particleTracker.materialName = materialName;
|
||||
particleTracker.particlesContainer.SetParticleMaterial(themeBundleName, materialName);
|
||||
particleTracker.SetParticleSettings(prewarm, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
|
||||
return particleTracker;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
colorSubmodule = new ColorSubmodule(this, Color.white, true, Color.white, 0);
|
||||
}
|
||||
|
||||
|
||||
public void SetParticleSettings(bool prewarm, bool is3D, float width, Vector3 extendDirection,
|
||||
float density, float lifeTime, bool isAutoOrient, Vector3 particleRotation)
|
||||
{
|
||||
this.prewarm = prewarm;
|
||||
this.is3D = is3D;
|
||||
this.width = width;
|
||||
this.extendDirection = extendDirection;
|
||||
this.density = density;
|
||||
this.lifeTime = lifeTime;
|
||||
this.prewarm = prewarm;
|
||||
this.isAutoOrient = isAutoOrient;
|
||||
this.particleRotation = particleRotation;
|
||||
particlesContainer.SetParticleSettings(prewarm, ParticleSystemSimulationSpace.Local, density,
|
||||
lifeTime, 0, 1, isAutoOrient, particleRotation);
|
||||
SetShape();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ParticleTracker
|
||||
{
|
||||
private void Update()
|
||||
{
|
||||
float songTime = EditorManager.instance.songInformation.songTime;
|
||||
if (playTime > songTime || stopTime < songTime)
|
||||
{
|
||||
if (particle.isPlaying || particle.isPaused)
|
||||
{
|
||||
particle.Stop();
|
||||
|
||||
if (songTime < playTime) { particle.Clear(); }
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!EditorManager.instance.musicPlayer.isPlaying)
|
||||
{
|
||||
particle.Pause();
|
||||
}
|
||||
else if (!particle.isPlaying)
|
||||
{
|
||||
particle.Play();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new ParticleTracker_BM(elementName, elementGuid, tags,
|
||||
parentElement.matchedBM as GameElement_BM,
|
||||
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation,
|
||||
themeBundleName, materialName);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Particle Tracker");
|
||||
|
||||
// 确保 themeBundleList 初始化
|
||||
if (themeBundleList == null)
|
||||
themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
||||
|
||||
DynamicUISubcontainer particleSettings0 = container.GenerateSubcontainer(3);
|
||||
inspector.GenerateToggle(this, particleSettings0, "Prewarm", nameof(prewarm))
|
||||
.AddListenerFunction(() => particlesContainer.SetPrewarm(prewarm));
|
||||
inspector.GenerateInputField(this, particleSettings0, "Play Time", nameof(playTime));
|
||||
inspector.GenerateInputField(this, particleSettings0, "Stop Time", nameof(stopTime));
|
||||
|
||||
DynamicUISubcontainer particleSettings1_0 = container.GenerateSubcontainer(3);
|
||||
inspector.GenerateToggle(this, particleSettings1_0, "Is 3D", nameof(is3D))
|
||||
.AddListenerFunction(SetShape);
|
||||
inspector.GenerateInputField(this, particleSettings1_0, "Width", nameof(width))
|
||||
.AddListenerFunction(SetShape);
|
||||
DynamicUISubcontainer particleSettings1_1 = container.GenerateSubcontainer(1);
|
||||
inspector.GenerateVector3InputField(this, particleSettings1_1, "Extend Direction", nameof(extendDirection))
|
||||
.AddListenerFunction(SetShape);
|
||||
|
||||
DynamicUISubcontainer particleSettings2 = container.GenerateSubcontainer(3);
|
||||
inspector.GenerateInputField(this, particleSettings2, "Density", nameof(density))
|
||||
.AddListenerFunction(()=>particlesContainer.SetDensity(density));
|
||||
inspector.GenerateInputField(this, particleSettings2, "Life Time", nameof(lifeTime))
|
||||
.AddListenerFunction(()=>particlesContainer.SetLifeTime(lifeTime));
|
||||
|
||||
DynamicUISubcontainer particleSettings3_0 = container.GenerateSubcontainer(3);
|
||||
inspector.GenerateToggle(this, particleSettings3_0, "Is Auto Orient", nameof(isAutoOrient))
|
||||
.AddListenerFunction(()=>particlesContainer.SetAlignment(isAutoOrient, particleRotation));
|
||||
DynamicUISubcontainer particleSettings3_1 = container.GenerateSubcontainer(1);
|
||||
inspector.GenerateVector3InputField(this, particleSettings3_1, "Particle Rotation", nameof(particleRotation))
|
||||
.AddListenerFunction(()=>particlesContainer.SetParticleRotation(particleRotation));
|
||||
|
||||
DynamicUISubcontainer materialSettings = container.GenerateSubcontainer(3);
|
||||
var themeBundleDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Theme Bundle", themeBundleList, nameof(themeBundleName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
if (themeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(themeBundleName, out ThemeBundle themeBundle))
|
||||
{
|
||||
materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Material Name", materialNameList, nameof(materialName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
materialNameList = new List<string>(); // 防止为null
|
||||
var objectNameDropdown =
|
||||
inspector.GenerateDropdown(this, materialSettings, "Material Name", materialNameList, nameof(materialName));
|
||||
objectNameDropdown.dropdown.interactable = false;
|
||||
} // 如果没有选择主题包,则材质名称下拉框不可用
|
||||
|
||||
var setMaterialButton = inspector.GenerateButton(this, materialSettings, "Set Material", () =>
|
||||
{
|
||||
particlesContainer.SetParticleMaterial(themeBundleName, materialName);
|
||||
});
|
||||
|
||||
if (themeBundleName == String.Empty || materialName == String.Empty)
|
||||
{
|
||||
setMaterialButton.button.interactable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ParticleTracker
|
||||
{
|
||||
private void SetShape()
|
||||
{
|
||||
particleController.is3D = is3D;
|
||||
particleController.width = width;
|
||||
particleController.extendDirection = extendDirection;
|
||||
particleController.Rebuild();
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
ParticleSystemRenderer particleSystemRenderer = particle.GetComponent<ParticleSystemRenderer>();
|
||||
particleSystemRenderer.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor);
|
||||
if (colorSubmodule.emissionEnabled)
|
||||
{
|
||||
particleSystemRenderer.material.EnableKeyword("_EMISSION_ON");
|
||||
particleSystemRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
particleSystemRenderer.material.DisableKeyword("_EMISSION_ON");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class ParticleTracker_BM : GameElement_BM
|
||||
{
|
||||
public bool prewarm = false;
|
||||
public float playTime = 0f;
|
||||
public float stopTime = 1f;
|
||||
|
||||
public bool is3D = false;
|
||||
public float width = 10f;
|
||||
public Vector3 extendDirection = Vector3.right;
|
||||
|
||||
public float density = 10;
|
||||
public float lifeTime = 5;
|
||||
|
||||
public bool isAutoOrient = true;
|
||||
public Vector3 particleRotation = Vector3.zero;
|
||||
|
||||
public string materialThemeBundleName = string.Empty;
|
||||
public string materialName = string.Empty;
|
||||
|
||||
public ParticleTracker_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ParticleTracker_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
bool prewarm, float playTime, float stopTime,
|
||||
bool is3D, float width, Vector3 extendDirection,
|
||||
float density, float lifeTime,
|
||||
bool isAutoOrient, Vector3 particleRotation,
|
||||
string materialThemeBundleName, string materialName) : base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.prewarm = prewarm;
|
||||
this.playTime = playTime;
|
||||
this.stopTime = stopTime;
|
||||
this.width = width;
|
||||
this.density = density;
|
||||
this.is3D = is3D;
|
||||
this.extendDirection = extendDirection;
|
||||
this.lifeTime = lifeTime;
|
||||
this.isAutoOrient = isAutoOrient;
|
||||
this.particleRotation = particleRotation;
|
||||
|
||||
this.materialThemeBundleName = materialThemeBundleName;
|
||||
this.materialName = materialName;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = ParticleTracker.GenerateElement(
|
||||
elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, materialThemeBundleName, materialName,
|
||||
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return ParticleTracker.GenerateElement(
|
||||
elementName, Guid.NewGuid(), tags, false,
|
||||
attached as Track, materialThemeBundleName, materialName,
|
||||
prewarm, playTime, stopTime, is3D, width, extendDirection, density, lifeTime, isAutoOrient, particleRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class Trail : GameElement, IHaveTransformSubmodule, IHaveTrail
|
||||
{
|
||||
public TrailRenderer trailRenderer { get; set; }
|
||||
public Material renderMaterial;
|
||||
|
||||
// Add these fields for material selection in inspector
|
||||
public string materialThemeBundleName;
|
||||
public string materialName;
|
||||
|
||||
public float visibleTimeLength;
|
||||
public bool isAutoOrient;
|
||||
public float widthMultiplier;
|
||||
public AnimationCurve widthCurve;
|
||||
public Gradient gradient;
|
||||
|
||||
public TransformSubmodule transformSubmodule { get; set; }
|
||||
float IHaveTrail.visibleTimeLength
|
||||
{
|
||||
get => visibleTimeLength;
|
||||
set => visibleTimeLength = value;
|
||||
}
|
||||
public bool emissionEnabled = false;
|
||||
// public float emissionIntensity = 1f; // 发光强度
|
||||
|
||||
|
||||
|
||||
public static Trail GenerateElement(string name, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement parentElement, float visibleTimeLength, bool isAutoOrient, float widthMultiplier,
|
||||
AnimationCurve widthCurve, Gradient gradient, string materialThemeBundleName, string materialName, Material material = null)
|
||||
{
|
||||
gradient ??= ColorExtensions.DefaultGradient();
|
||||
|
||||
Trail trail = Instantiate(EditorManager.instance.basePrefabs.trail, parentElement.transform).GetComponent<Trail>();
|
||||
trail.trailRenderer = trail.GetComponent<TrailRenderer>();
|
||||
|
||||
trail.Initialize(name, id, tags, isFirstGenerated, parentElement);
|
||||
|
||||
trail.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrailMaterial : material;
|
||||
trail.visibleTimeLength = visibleTimeLength;
|
||||
trail.isAutoOrient = isAutoOrient;
|
||||
trail.widthMultiplier = widthMultiplier;
|
||||
trail.widthCurve = widthCurve;
|
||||
trail.gradient = gradient;
|
||||
trail.materialThemeBundleName = materialThemeBundleName;
|
||||
trail.materialName = materialName;
|
||||
|
||||
trail.trailRenderer.material = trail.renderMaterial;
|
||||
trail.trailRenderer.time = visibleTimeLength;
|
||||
trail.trailRenderer.alignment = isAutoOrient ? LineAlignment.View : LineAlignment.TransformZ;
|
||||
trail.trailRenderer.widthMultiplier = widthMultiplier;
|
||||
trail.trailRenderer.widthCurve = widthCurve;
|
||||
trail.trailRenderer.colorGradient = gradient;
|
||||
|
||||
return trail;
|
||||
}
|
||||
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
transformSubmodule = new TransformSubmodule(this);
|
||||
}
|
||||
|
||||
// 新增:通过主题包名和材质名获取材质的方法
|
||||
public Material GetMaterialFromThemeBundle()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(materialThemeBundleName) && !string.IsNullOrEmpty(materialName))
|
||||
{
|
||||
var mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
|
||||
if (mat != null)
|
||||
return mat;
|
||||
}
|
||||
return EditorManager.instance.basePrefabs.defaultTrailMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Trail
|
||||
{
|
||||
public override void SaveBM()
|
||||
{
|
||||
matchedBM = new Trail_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
visibleTimeLength, isAutoOrient, widthMultiplier, widthCurve, materialThemeBundleName, materialName, gradient);
|
||||
}
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
StandardInspectionElement.GenerateForTransform(this); //关于有Transform的元素
|
||||
|
||||
var container = inspector.GenerateContainer("Trail");
|
||||
|
||||
var trailSettings = container.GenerateSubcontainer(3);
|
||||
var visibleTimeLengthInputField =
|
||||
inspector.GenerateInputField(this, trailSettings, "Visible Time Length", nameof(visibleTimeLength))
|
||||
.AddListenerFunction(() => trailRenderer.time = visibleTimeLength);
|
||||
var isAutoOrientToggle =
|
||||
inspector.GenerateToggle(this, trailSettings, "Is Auto Orient", nameof(isAutoOrient))
|
||||
.AddListenerFunction(() => trailRenderer.alignment = isAutoOrient ? LineAlignment.View : LineAlignment.TransformZ);
|
||||
var widthMultiplierInputField =
|
||||
inspector.GenerateInputField(this, trailSettings, "Width Multiplier", nameof(widthMultiplier))
|
||||
.AddListenerFunction(() => trailRenderer.widthMultiplier = widthMultiplier);
|
||||
var widthCurveButton = inspector.GenerateButton(this, trailSettings, "Width Curve", () =>
|
||||
{
|
||||
var widthCurveWindow = inspector.GenerateCompositeParameterWindow(this, "Width Curve", nameof(widthCurve));
|
||||
widthCurveWindow.SetAsCustomCurve();
|
||||
widthCurveWindow.closeButton.onClick.AddListener(() => trailRenderer.widthCurve = widthCurve);
|
||||
});
|
||||
|
||||
// ----------- 新增:材质设置 -----------
|
||||
var materialSettings = container.GenerateSubcontainer(3);
|
||||
|
||||
|
||||
// 主题包下拉框
|
||||
if (ThemeBundleManager.instance != null)
|
||||
{
|
||||
var themeBundleDropdown = inspector
|
||||
.GenerateDropdown(this, materialSettings, "Theme Bundle", ThemeBundleManager.instance.selectedThemeBundleList, nameof(materialThemeBundleName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
// 材质名下拉框
|
||||
if (!string.IsNullOrEmpty(materialThemeBundleName) && ThemeBundleManager.instance.TryGetThemeBundle(materialThemeBundleName, out ThemeBundle themeBundle))
|
||||
{
|
||||
List<string> materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
|
||||
var objectNameDropdown = inspector.GenerateDropdown(this, materialSettings, "Material Name", materialNameList, nameof(materialName))
|
||||
.AddListenerFunction(() => inspectorMain.SetInspector(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectNameDropdown = inspector.GenerateDropdown(this, materialSettings, "Material Name", new List<string>(), nameof(materialName));
|
||||
objectNameDropdown.dropdown.interactable = false;
|
||||
}
|
||||
// 应用材质按钮
|
||||
var applyMaterialButton = inspector.GenerateButton(this, materialSettings, "Apply Material", () =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(materialThemeBundleName) && !string.IsNullOrEmpty(materialName))
|
||||
{
|
||||
Material mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
|
||||
if (mat != null)
|
||||
{
|
||||
renderMaterial = mat;
|
||||
if (trailRenderer != null)
|
||||
trailRenderer.material = renderMaterial;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// ----------- 材质设置结束 -----------
|
||||
|
||||
var colorSettings = container.GenerateSubcontainer(3);
|
||||
var gradientColorKeysButton = inspector.GenerateButton(this, colorSettings, "Gradient Color Keys", () =>
|
||||
{
|
||||
var gradientWindow = inspector.GenerateCompositeParameterWindow(this, "Gradient Color Keys", nameof(gradient));
|
||||
gradientWindow.SetAsGradientColorKeys();
|
||||
gradientWindow.closeButton.onClick.AddListener(() => trailRenderer.colorGradient = gradient);
|
||||
});
|
||||
var gradientAlphaKeysButton = inspector.GenerateButton(this, colorSettings, "Gradient Alpha Keys", () =>
|
||||
{
|
||||
var gradientWindow = inspector.GenerateCompositeParameterWindow(this, "Gradient Alpha Keys", nameof(gradient));
|
||||
gradientWindow.SetAsGradientAlphaKeys();
|
||||
gradientWindow.closeButton.onClick.AddListener(() => trailRenderer.colorGradient = gradient);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Trail
|
||||
{
|
||||
public static void SetAllTrails(bool emitting, bool willClear)
|
||||
{
|
||||
foreach (GameElement x in EditorManager.instance.beatmapContainer.gameElementList)
|
||||
{
|
||||
if (x is IHaveTrail t && t.trailRenderer != null)
|
||||
{
|
||||
t.trailRenderer.emitting = emitting;
|
||||
t.trailRenderer.enabled = emitting;
|
||||
if (willClear) t.trailRenderer.Clear();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void FreezeAllTrails(bool freeze)
|
||||
{
|
||||
foreach (GameElement x in EditorManager.instance.beatmapContainer.gameElementList)
|
||||
{
|
||||
if (x is IHaveTrail t && t != null)
|
||||
{
|
||||
FreezeTrail(freeze, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void FreezeTrail(bool freeze, IHaveTrail trail)
|
||||
{
|
||||
|
||||
|
||||
if (!freeze)
|
||||
{
|
||||
UnfreezeTrail(trail);
|
||||
return;
|
||||
}
|
||||
trail.trailRenderer.time = Mathf.Infinity; // 使现有轨迹永不消失
|
||||
trail.trailRenderer.emitting = false; // 停止生成新轨迹点
|
||||
}
|
||||
|
||||
// 解冻尾迹(恢复动态更新)
|
||||
public static void UnfreezeTrail(IHaveTrail trail)
|
||||
{
|
||||
trail.trailRenderer.Clear(); // 清除当前冻结的轨迹
|
||||
trail.trailRenderer.time = trail.visibleTimeLength; // 恢复原始持续时间
|
||||
trail.trailRenderer.emitting = true; // 重新开始发射轨迹点
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHaveTrail
|
||||
{
|
||||
TrailRenderer trailRenderer { get; set; }
|
||||
float visibleTimeLength { get; set; }
|
||||
}
|
||||
|
||||
namespace Beatmap
|
||||
{
|
||||
public class Trail_BM : GameElement_BM
|
||||
{
|
||||
public float visibleTimeLength;
|
||||
public string renderMaterialName;
|
||||
public string materialThemeBundleName; // 新增
|
||||
public string materialName; // 新增
|
||||
public bool isAutoOrient;
|
||||
public float widthMultiplier;
|
||||
public AnimationCurve widthCurve;
|
||||
public Gradient gradient;
|
||||
|
||||
public Trail_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Trail_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
||||
float visibleTimeLength, bool isAutoOrient, float widthMultiplier,
|
||||
AnimationCurve widthCurve, string materialThemeBundleName, string materialName, Gradient gradient) : base(elementName, elementGuid, tags,
|
||||
attachedElement)
|
||||
{
|
||||
this.visibleTimeLength = visibleTimeLength;
|
||||
// 新增:保存主题包名和材质名
|
||||
this.materialThemeBundleName = materialThemeBundleName;
|
||||
this.materialName = materialName;
|
||||
|
||||
this.isAutoOrient = isAutoOrient;
|
||||
this.widthMultiplier = widthMultiplier;
|
||||
this.widthCurve = widthCurve;
|
||||
this.gradient = gradient;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
// 新增:根据bm里的主题包名和材质名获取材质
|
||||
Material mat = null;
|
||||
if (!string.IsNullOrEmpty(materialThemeBundleName) && !string.IsNullOrEmpty(materialName))
|
||||
{
|
||||
mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
|
||||
}
|
||||
matchedElement = Trail.GenerateElement(elementName, elementGuid, tags,
|
||||
false, GetElement(attachedElementGuid),
|
||||
visibleTimeLength, isAutoOrient, widthMultiplier, widthCurve, gradient, materialThemeBundleName, materialName, mat);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
// 新增:根据bm里的主题包名和材质名获取材质
|
||||
Material mat = null;
|
||||
if (!string.IsNullOrEmpty(materialThemeBundleName) && !string.IsNullOrEmpty(materialName))
|
||||
{
|
||||
mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
|
||||
}
|
||||
return Trail.GenerateElement(elementName, Guid.NewGuid(), tags,
|
||||
false, parent, visibleTimeLength,
|
||||
isAutoOrient, widthMultiplier, widthCurve, gradient, materialThemeBundleName, materialName, mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bf117e642611451c8562357254c1e83
|
||||
guid: e5c81960366f31346aada41fa3847d97
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f5c439efd47f46888026603e35d5a4e
|
||||
guid: 0465fbef9411d134cb49c9da5db347a9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f85e090ad2708745a8fd3b9c254ad3a
|
||||
guid: 92c40b847213a5e41a3ebe8a47bc7daf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public abstract class AnimationBase_BM : GameElement_BM
|
||||
{
|
||||
public AnimationBase_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AnimationBase_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement) : base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62f7f20bc287dba439ab78c3adc20013
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6944ee6ee5d024c15a16862148361df3
|
||||
guid: afaa9a1f53951cc4293cdf042a085792
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public partial class CameraFieldOfView_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM fieldOfView;
|
||||
|
||||
public CameraFieldOfView_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public CameraFieldOfView_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM fieldOfView)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.fieldOfView = fieldOfView;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = CameraFieldOfView.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as GameCamera, fieldOfView.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return CameraFieldOfView.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as GameCamera, fieldOfView.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4237b95b10903c04da3914fb0d9ebd0e
|
||||
8
Assets/Scripts/Game/DataCore/Animations_BM/Color.meta
Normal file
8
Assets/Scripts/Game/DataCore/Animations_BM/Color.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b8cd7510e8f92a48ba5c8e59842d7d6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class BaseColorChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM colorR, colorG, colorB, colorA;
|
||||
|
||||
public BaseColorChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BaseColorChange_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM colorR, FlexibleFloat_BM colorG,
|
||||
FlexibleFloat_BM colorB, FlexibleFloat_BM colorA) :
|
||||
base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.colorR = colorR;
|
||||
this.colorG = colorG;
|
||||
this.colorB = colorB;
|
||||
this.colorA = colorA;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = BaseColorChange.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), colorR.ConvertToGameType(),
|
||||
colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return BaseColorChange.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent, colorR.ConvertToGameType(), colorG.ConvertToGameType(),
|
||||
colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54072515035e86e4490c1d5d6412e834
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class EmissionColorChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM colorR, colorG, colorB, colorI;
|
||||
|
||||
public EmissionColorChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EmissionColorChange_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM parentElement,
|
||||
FlexibleFloat_BM colorR, FlexibleFloat_BM colorG, FlexibleFloat_BM colorB, FlexibleFloat_BM colorI) :
|
||||
base(elementName, elementGuid, tags, parentElement)
|
||||
{
|
||||
this.colorR = colorR;
|
||||
this.colorG = colorG;
|
||||
this.colorB = colorB;
|
||||
this.colorI = colorI;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = EmissionColorChange.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return EmissionColorChange.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41c413de18a45884cb5a212200f3193b
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01dfe5498ab26864495721e303263c30
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class DisplacementTracker_BM : AnimationBase_BM, ICanNotInExport
|
||||
{
|
||||
public Guid targetDisplacementGuid;
|
||||
public float timeOffset;
|
||||
|
||||
public DisplacementTracker_BM() { }
|
||||
|
||||
public DisplacementTracker_BM(string elementName, System.Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, Guid targetDisplacementGuid, float timeOffset)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.targetDisplacementGuid = targetDisplacementGuid;
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = DisplacementTracker.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), GetElement(targetDisplacementGuid) as Displacement, timeOffset);
|
||||
matchedElement.matchedBM = this;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return DisplacementTracker.GenerateElement(elementName, System.Guid.NewGuid(), tags, false, parent,
|
||||
GetElement(targetDisplacementGuid) as Displacement, timeOffset);
|
||||
}
|
||||
|
||||
public override void AfterExecute()
|
||||
{
|
||||
(matchedElement as DisplacementTracker).targetDisplacement = GetElement(targetDisplacementGuid) as ICanBeTrackedDisplacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a854f837f01d15f45bd486d81ff35259
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class ScaleTracker_BM : AnimationBase_BM, ICanNotInExport
|
||||
{
|
||||
public Guid targetScaleGuid;
|
||||
public float timeOffset;
|
||||
|
||||
public ScaleTracker_BM() { }
|
||||
|
||||
public ScaleTracker_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, Guid targetScaleGuid, float timeOffset)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.targetScaleGuid = targetScaleGuid;
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = ScaleTracker.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), GetElement(targetScaleGuid) as ICanBeTrackedScale, timeOffset);
|
||||
matchedElement.matchedBM = this;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return ScaleTracker.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
GetElement(targetScaleGuid) as ICanBeTrackedScale, timeOffset);
|
||||
}
|
||||
|
||||
public override void AfterExecute()
|
||||
{
|
||||
(matchedElement as ScaleTracker).targetScale = GetElement(targetScaleGuid) as ICanBeTrackedScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fd8d93fbaacc9e4693a14658c303fa9
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class SwirlTracker_BM : AnimationBase_BM, ICanNotInExport
|
||||
{
|
||||
public Guid targetSwirlGuid;
|
||||
public float timeOffset;
|
||||
|
||||
public SwirlTracker_BM() { }
|
||||
|
||||
public SwirlTracker_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, Guid targetSwirlGuid, float timeOffset)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.targetSwirlGuid = targetSwirlGuid;
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = SwirlTracker.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), GetElement(targetSwirlGuid) as Swirl, timeOffset);
|
||||
matchedElement.matchedBM = this;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return SwirlTracker.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
GetElement(targetSwirlGuid) as Swirl, timeOffset);
|
||||
}
|
||||
|
||||
public override void AfterExecute()
|
||||
{
|
||||
(matchedElement as SwirlTracker).targetSwirl = GetElement(targetSwirlGuid) as ICanBeTrackedSwirl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49c51b81352f0444a9348e594a8364d6
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class Vector3Interferometer_BM : AnimationBase_BM, ICanNotInExport
|
||||
{
|
||||
public Vector3 InterferomValueVector3;
|
||||
public InterferomType InterferomType;
|
||||
|
||||
public Vector3Interferometer_BM() { }
|
||||
|
||||
public Vector3Interferometer_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, InterferomType interferomType, Vector3 interferomValue)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.InterferomType = interferomType;
|
||||
this.InterferomValueVector3 = interferomValue;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = Vector3Interferometer.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as AnimationBase, InterferomType, InterferomValueVector3);
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return Vector3Interferometer.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as AnimationBase, InterferomType, InterferomValueVector3);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanNotInExport { }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 523d5a711ebc2d84797488b5fee2b08c
|
||||
8
Assets/Scripts/Game/DataCore/Animations_BM/Track.meta
Normal file
8
Assets/Scripts/Game/DataCore/Animations_BM/Track.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a83fcedde1f35345b7b234c7fc02f3a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class TrackGlobalColorChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM colorR, colorG, colorB, colorA;
|
||||
|
||||
public TrackGlobalColorChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackGlobalColorChange_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM colorR, FlexibleFloat_BM colorG, FlexibleFloat_BM colorB, FlexibleFloat_BM colorA)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.colorR = colorR;
|
||||
this.colorG = colorG;
|
||||
this.colorB = colorB;
|
||||
this.colorA = colorA;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement attached)
|
||||
{
|
||||
return TrackGlobalColorChange.GenerateElement(elementName, Guid.NewGuid(), tags, true, attached,
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = TrackGlobalColorChange.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
|
||||
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorA.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a6e3c456031ba64dbb66efb488a2cff
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class TrackTotalTimeChange_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM totalTime;
|
||||
|
||||
public TrackTotalTimeChange_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TrackTotalTimeChange_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM totalTime) :
|
||||
base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = TrackTotalTimeChange.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid) as Track, totalTime.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return TrackTotalTimeChange.GenerateElement(elementName, Guid.NewGuid(), tags, false,
|
||||
parent as Track, totalTime.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 095a199d040efa14c8505df1752c832f
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcc2843ec7b9a134f91a9c233de0b32a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class Displacement_BM : AnimationBase_BM
|
||||
{
|
||||
public FlexibleFloat_BM positionX, positionY, positionZ;
|
||||
|
||||
public Displacement_BM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Displacement_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleFloat_BM positionX, FlexibleFloat_BM positionY, FlexibleFloat_BM positionZ)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.positionX = positionX;
|
||||
this.positionY = positionY;
|
||||
this.positionZ = positionZ;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = Displacement.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
|
||||
positionX.ConvertToGameType(), positionY.ConvertToGameType(), positionZ.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return Displacement.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
positionX.ConvertToGameType(), positionY.ConvertToGameType(), positionZ.ConvertToGameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee1155566a762724bbf8486c2f0ed48b
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ichni.RhythmGame.Beatmap
|
||||
{
|
||||
public class LookAt_BM : GameElement_BM
|
||||
{
|
||||
public FlexibleBool_BM enabling;
|
||||
public Guid lookAtObjectGuid;
|
||||
|
||||
public LookAt_BM()
|
||||
{
|
||||
}
|
||||
|
||||
public LookAt_BM(string elementName, Guid elementGuid, List<string> tags,
|
||||
GameElement_BM attachedElement, FlexibleBool_BM enabling, Guid lookAtObjectGuid)
|
||||
: base(elementName, elementGuid, tags, attachedElement)
|
||||
{
|
||||
this.enabling = enabling;
|
||||
this.lookAtObjectGuid = lookAtObjectGuid;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
matchedElement = LookAt.GenerateElement(elementName, elementGuid, tags, false,
|
||||
GetElement(attachedElementGuid), GetElement(lookAtObjectGuid), enabling.ConvertToGameType());
|
||||
matchedElement.matchedBM = this;
|
||||
}
|
||||
|
||||
public override GameElement DuplicateBM(GameElement parent)
|
||||
{
|
||||
return LookAt.GenerateElement(elementName, Guid.NewGuid(), tags, false, parent,
|
||||
GetElement(lookAtObjectGuid), enabling.ConvertToGameType());
|
||||
}
|
||||
|
||||
public override void AfterExecute()
|
||||
{
|
||||
(matchedElement as LookAt).lookAtObject = GetElement(lookAtObjectGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc1bafbf1d46274459a8339c37f65a70
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user