Tilt,Offset,以及谱面合并操作

This commit is contained in:
SoulliesOfficial
2025-06-01 13:01:31 -04:00
parent 61e6ac3a32
commit 4497c3b3da
13 changed files with 37011 additions and 16607 deletions

View File

@@ -19,6 +19,7 @@ namespace Ichni.Editor
public Button songInfoButton;
public Button saveButton;
public Button exportButton;
public Button mergeButton;
public Button clipSaveButton;
public Button clipLoadButton;
public Button beatmapToolsButton;
@@ -33,6 +34,7 @@ namespace Ichni.Editor
reloadButton.onClick.AddListener(GenerateReloadConfirmWindow);
saveButton.onClick.AddListener(EditorManager.instance.projectManager.saveManager.Save);
exportButton.onClick.AddListener(EditorManager.instance.projectManager.exportManager.Export);
mergeButton.onClick.AddListener(GenerateMergeWindow);
clipSaveButton.onClick.AddListener(GenerateSaveClipWindow);
clipLoadButton.onClick.AddListener(GenerateLoadClipWindow);
beatmapToolsButton.onClick.AddListener(GenerateBeatmapToolsWindow);
@@ -144,6 +146,22 @@ namespace Ichni.Editor
EditorManager.instance.projectManager.beatmapClipManager.LoadClip(clipNameInputField.GetValue<string>());
});
}
private void GenerateMergeWindow()
{
GeneralSecondaryWindow mergeWindow = Instantiate(EditorManager.instance.basePrefabs.generalSecondaryWindow,
EditorManager.instance.uiManager.mainPage.mainCanvas.GetComponent<RectTransform>()).GetComponent<GeneralSecondaryWindow>();
mergeWindow.Initialize("Merge Beatmap");
var container = mergeWindow.GenerateContainer();
var clipSettings = container.GenerateSubcontainer(3);
var clipNameInputField = mergeWindow.GenerateInputField(clipSettings, "Beatmap Name");
var applyClipButton = mergeWindow.GenerateButton(clipSettings, "Apply", () =>
{
EditorManager.instance.projectManager.beatmapMergeManager.MergeBeatmap(clipNameInputField.GetValue<string>());
});
}
}
public partial class ToolBar

View File

@@ -129,9 +129,7 @@ namespace Ichni.RhythmGame
{ "Bloom", new BloomEffect(1, 2, CustomCurvePresets.Parabolic(1, 0, 1)) },
{ "CameraShake", new CameraShakeEffect(1, 50, 1, 1, 1) },
{"CameraOffset", new CameraOffsetEffect(0.2f, Vector3.forward, CustomCurvePresets.CustomPeakTimeParabolic(1,0,1,0.3f))},
{"CameraTilt", new CameraTiltEffect(false, 0.2f, 5f, CustomCurvePresets.CustomPeakTimeParabolic(1,0,1, 0.3f),
false, 0.2f, 5f, CustomCurvePresets.CustomPeakTimeParabolic(1,0,1, 0.3f),
false, 0.2f, 5f, CustomCurvePresets.CustomPeakTimeParabolic(1,0,1, 0.3f))},
{"CameraTilt", new CameraTiltEffect(0.2f, new Vector3(0,0,5), CustomCurvePresets.CustomPeakTimeParabolic(1,0,1, 0.3f))},
{ "ChromaticAberration", new ChromaticAberrationEffect(1, 1, CustomCurvePresets.Parabolic(1, 0, 1)) },
{ "Vignette", new VignetteEffect(1, 1, 0.4f, Color.black, CustomCurvePresets.Parabolic(1, 0, 1)) },
{ "SetInteger", new SetIntegerEffect("New Variable", 0, false, 0, 1) },

View File

@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
@@ -11,18 +12,32 @@ namespace Ichni.RhythmGame
public class CameraOffsetEffect : EffectBase
{
public float duration;
public Vector3 offsetPeak;
public Vector3 offsetValue;
public AnimationCurve offsetCurve;
public CameraOffsetEffect(float duration, Vector3 offsetPeak, AnimationCurve offsetCurve)
Transform gameCameraTransform => EditorManager.instance.cameraManager.gameCamera.gameCamera.transform;
Tweener offsetTweener;
public CameraOffsetEffect(float duration, Vector3 offsetValue, AnimationCurve offsetCurve)
{
this.effectTime = 0;
this.effectTime = this.duration;
this.duration = duration;
this.offsetPeak = offsetPeak;
this.offsetValue = offsetValue;
this.offsetCurve = offsetCurve;
}
public override void Recover()
{
if (!EditorManager.instance.cameraManager.haveGameCamera)
{
LogWindow.Log("No game camera found, cannot apply camera tilt effect.", Color.yellow);
return;
}
offsetTweener?.Kill(true);
gameCameraTransform.localPosition = Vector3.zero;
}
public override void Adjust()
public override void PreExecute()
{
if (!EditorManager.instance.cameraManager.haveGameCamera)
{
@@ -30,18 +45,13 @@ namespace Ichni.RhythmGame
return;
}
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.cameraTiltEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_Position>().AnimatePositionTarget = EditorManager.instance.cameraManager.gameCamera.gameCamera.gameObject;
effect.GetFeedbackOfType<MMF_Position>().AnimatePositionDuration = duration;
effect.GetFeedbackOfType<MMF_Position>().DestinationPosition = offsetPeak;
effect.GetFeedbackOfType<MMF_Position>().AnimatePositionCurve = offsetCurve;
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, duration);
//GameCamera的摄像机本体能且只能被TiltEffect和OffsetEffect修改Transform并且必须归位
offsetTweener = gameCameraTransform.DOBlendableLocalMoveBy(offsetValue, duration).SetEase(offsetCurve);
}
public override EffectBase_BM ConvertToBM()
{
return new CameraOffsetEffect_BM(duration, offsetPeak, offsetCurve);
return new CameraOffsetEffect_BM(duration, offsetValue, offsetCurve);
}
public override void SetUpInspector()
@@ -53,10 +63,10 @@ namespace Ichni.RhythmGame
var curveButton = inspector.GenerateButton(this, subcontainer1, "Offset Curve", () =>
{
var intensityCurveWindow =
inspector.GenerateCompositeParameterWindow(this, "Tilt Curve", nameof(offsetCurve)).SetAsCustomCurve();
inspector.GenerateCompositeParameterWindow(this, "Offset Curve", nameof(offsetCurve)).SetAsCustomCurve();
});
var subcontainer2 = container.GenerateSubcontainer(3);
var xPeakField = inspector.GenerateVector3InputField(this, subcontainer2, "Offset Peak", nameof(offsetPeak));
var subcontainer2 = container.GenerateSubcontainer(1);
var offsetPeakField = inspector.GenerateVector3InputField(this, subcontainer2, "Offset Value", nameof(offsetValue));
}
}
@@ -65,19 +75,20 @@ namespace Ichni.RhythmGame
public class CameraOffsetEffect_BM : EffectBase_BM
{
public float duration;
public Vector3 offsetPeak;
public Vector3 offsetValue;
public AnimationCurve offsetCurve;
public CameraOffsetEffect_BM(float duration, Vector3 offsetPeak, AnimationCurve offsetCurve)
public CameraOffsetEffect_BM(float duration, Vector3 offsetValue, AnimationCurve offsetCurve)
{
this.effectTime = duration;
this.duration = duration;
this.offsetPeak = offsetPeak;
this.offsetValue = offsetValue;
this.offsetCurve = offsetCurve;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new CameraOffsetEffect(duration, offsetPeak, offsetCurve);
return new CameraOffsetEffect(duration, offsetValue, offsetCurve);
}
}
}

View File

@@ -12,48 +12,33 @@ namespace Ichni.RhythmGame
{
public class CameraTiltEffect : EffectBase
{
public bool haveXTilt;
public float xDuration;
public float xPeak;
public AnimationCurve tiltCurveX;
public float duration;
public Vector3 tiltValue;
public AnimationCurve tiltCurve;
public bool haveYTilt;
public float yDuration;
public float yPeak;
public AnimationCurve tiltCurveY;
Transform gameCameraTransform => EditorManager.instance.cameraManager.gameCamera.gameCamera.transform;
Tweener tiltTweener;
public bool haveZTilt;
public float zDuration;
public float zPeak;
public AnimationCurve tiltCurveZ;
public List<MMF_Player> avtiveEffectExecutors;
public CameraTiltEffect(bool haveXTilt, float xDuration, float xPeak, AnimationCurve tiltCurveX,
bool haveYTilt, float yDuration, float yPeak, AnimationCurve tiltCurveY,
bool haveZTilt, float zDuration, float zPeak, AnimationCurve tiltCurveZ)
public CameraTiltEffect(float duration, Vector3 tiltValue, AnimationCurve tiltCurve)
{
this.effectTime = 0;
this.haveXTilt = haveXTilt;
this.xDuration = xDuration;
this.xPeak = xPeak;
this.tiltCurveX = tiltCurveX;
this.haveYTilt = haveYTilt;
this.yDuration = yDuration;
this.yPeak = yPeak;
this.tiltCurveY = tiltCurveY;
this.haveZTilt = haveZTilt;
this.zDuration = zDuration;
this.zPeak = zPeak;
this.tiltCurveZ = tiltCurveZ;
avtiveEffectExecutors = new List<MMF_Player>();
this.effectTime = duration;
this.duration = duration;
this.tiltValue = tiltValue;
this.tiltCurve = tiltCurve;
}
public override void Adjust()
public override void Recover()
{
if (!EditorManager.instance.cameraManager.haveGameCamera)
{
LogWindow.Log("No game camera found, cannot apply camera tilt effect.", Color.yellow);
return;
}
tiltTweener?.Kill(true);
gameCameraTransform.localEulerAngles = Vector3.zero;
}
public override void PreExecute()
{
if (!EditorManager.instance.cameraManager.haveGameCamera)
{
@@ -61,111 +46,41 @@ namespace Ichni.RhythmGame
return;
}
if (haveXTilt)
{
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.cameraTiltEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationTarget = EditorManager.instance.cameraManager.gameCamera.gameCamera.transform;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationDuration = xDuration;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateX = true;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateY = false;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateZ = false;
effect.GetFeedbackOfType<MMF_Rotation>().RemapCurveOne = xPeak;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationX = tiltCurveX;
effect.GetComponent<PooledObject>().SetOnDespawn(() => avtiveEffectExecutors.Remove(effect));
avtiveEffectExecutors.Add(effect);
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, xDuration);
}
if (haveYTilt)
{
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.cameraTiltEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationTarget = EditorManager.instance.cameraManager.gameCamera.gameCamera.transform;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationDuration = yDuration;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateX = false;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateY = true;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateZ = false;
effect.GetFeedbackOfType<MMF_Rotation>().RemapCurveOne = yPeak;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationY = tiltCurveY;
effect.GetComponent<PooledObject>().SetOnDespawn(() => avtiveEffectExecutors.Remove(effect));
avtiveEffectExecutors.Add(effect);
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, yDuration);
}
//GameCamera的摄像机本体能且只能被TiltEffect和OffsetEffect修改Transform并且必须归位
tiltTweener = gameCameraTransform.DOBlendableLocalRotateBy(tiltValue, duration, RotateMode.FastBeyond360).SetEase(tiltCurve);
}
if (haveZTilt)
{
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.cameraTiltEffect).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationTarget = EditorManager.instance.cameraManager.gameCamera.gameCamera.transform;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationDuration = zDuration;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateX = false;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateZ = true;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateY = false;
effect.GetFeedbackOfType<MMF_Rotation>().RemapCurveOne = zPeak;
effect.GetFeedbackOfType<MMF_Rotation>().AnimateRotationZ = tiltCurveZ;
effect.GetComponent<PooledObject>().SetOnDespawn(() => avtiveEffectExecutors.Remove(effect));
avtiveEffectExecutors.Add(effect);
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, zDuration);
}
public override void Adjust()
{
}
public override EffectBase_BM ConvertToBM()
{
return new CameraTiltEffect_BM(
haveXTilt, xDuration, xPeak, tiltCurveX,
haveYTilt, yDuration, yPeak, tiltCurveY,
haveZTilt, zDuration, zPeak, tiltCurveZ);
return new CameraTiltEffect_BM(duration, tiltValue, tiltCurve);
}
public override void Disrupt()
{
foreach (MMF_Player executor in avtiveEffectExecutors)
{
executor.StopFeedbacks();
}
for (var i = 0; i < avtiveEffectExecutors.Count; i++)
{
LeanPool.Despawn(avtiveEffectExecutors[i].gameObject);
}
EditorManager.instance.cameraManager.gameCamera.gameCamera.transform.DOLocalRotate(Vector3.zero, 0.2f);
tiltTweener?.Kill();
EditorManager.instance.cameraManager.gameCamera.gameCamera.transform.DOLocalRotate(Vector3.zero, 0.4f);
}
public override void SetUpInspector()
{
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Camera Tilt");
var xSubcontainer= container.GenerateSubcontainer(3);
var haveXTileToggle = inspector.GenerateToggle(this, xSubcontainer, "Have X Tilt", nameof(haveXTilt));
var xDurationField = inspector.GenerateInputField(this, xSubcontainer, "Duration", nameof(xDuration));
var xPeakField = inspector.GenerateInputField(this, xSubcontainer, "X Peak Value", nameof(xPeak));
var xCurveButton = inspector.GenerateButton(this, xSubcontainer, "Intensity Curve", () =>
var subcontainer1 = container.GenerateSubcontainer(3);
var durationField = inspector.GenerateInputField(this, subcontainer1, "Duration", nameof(duration));
var tiltCurveButton = inspector.GenerateButton(this, subcontainer1, "Tilt Curve", () =>
{
var intensityCurveWindow =
inspector.GenerateCompositeParameterWindow(this, "Tilt Curve", nameof(tiltCurveX)).SetAsCustomCurve();
inspector.GenerateCompositeParameterWindow(this, "Tilt Curve", nameof(tiltCurve)).SetAsCustomCurve();
});
var ySubcontainer = container.GenerateSubcontainer(3);
var haveYTileToggle = inspector.GenerateToggle(this, ySubcontainer, "Have Y Tilt", nameof(haveYTilt));
var yDurationField = inspector.GenerateInputField(this, ySubcontainer, "Duration", nameof(yDuration));
var yPeakField = inspector.GenerateInputField(this, ySubcontainer, "Y Peak Value", nameof(yPeak));
var yCurveButton = inspector.GenerateButton(this, ySubcontainer, "Intensity Curve", () =>
{
var intensityCurveWindow =
inspector.GenerateCompositeParameterWindow(this, "Tilt Curve", nameof(tiltCurveY)).SetAsCustomCurve();
});
var zSubcontainer = container.GenerateSubcontainer(3);
var haveZTileToggle = inspector.GenerateToggle(this, zSubcontainer, "Have Z Tilt", nameof(haveZTilt));
var zDurationField = inspector.GenerateInputField(this, zSubcontainer, "Duration", nameof(zDuration));
var zPeakField = inspector.GenerateInputField(this, zSubcontainer, "Z Peak Value", nameof(zPeak));
var zCurveButton = inspector.GenerateButton(this, zSubcontainer, "Intensity Curve", () =>
{
var intensityCurveWindow =
inspector.GenerateCompositeParameterWindow(this, "Tilt Curve", nameof(tiltCurveZ)).SetAsCustomCurve();
});
var subcontainer2 = container.GenerateSubcontainer(1);
var tiltValueField = inspector.GenerateVector3InputField(this, subcontainer2, "Tilt Value", nameof(tiltValue));
}
}
@@ -173,45 +88,22 @@ namespace Ichni.RhythmGame
{
public class CameraTiltEffect_BM : EffectBase_BM
{
public bool haveXTilt;
public float xDuration;
public float xPeak;
public AnimationCurve tiltCurveX;
public bool haveYTilt;
public float yDuration;
public float yPeak;
public AnimationCurve tiltCurveY;
public bool haveZTilt;
public float zDuration;
public float zPeak;
public AnimationCurve tiltCurveZ;
public CameraTiltEffect_BM(bool haveXTilt, float xDuration, float xPeak, AnimationCurve tiltCurveX,
bool haveYTilt, float yDuration, float yPeak, AnimationCurve tiltCurveY,
bool haveZTilt, float zDuration, float zPeak, AnimationCurve tiltCurveZ)
public float duration;
public Vector3 tiltValue;
public AnimationCurve tiltCurve;
public CameraTiltEffect_BM(float duration, Vector3 tiltValue, AnimationCurve tiltCurve)
{
this.effectTime = 0;
this.effectTime = duration;
this.duration = duration;
this.tiltValue = tiltValue;
this.tiltCurve = tiltCurve;
this.haveXTilt = haveXTilt;
this.xDuration = xDuration;
this.xPeak = xPeak;
this.tiltCurveX = tiltCurveX;
this.haveYTilt = haveYTilt;
this.yDuration = yDuration;
this.yPeak = yPeak;
this.tiltCurveY = tiltCurveY;
this.haveZTilt = haveZTilt;
this.zDuration = zDuration;
this.zPeak = zPeak;
this.tiltCurveZ = tiltCurveZ;
}
public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{
return new CameraTiltEffect(haveXTilt, xDuration, xPeak, tiltCurveX,
haveYTilt, yDuration, yPeak, tiltCurveY,
haveZTilt, zDuration, zPeak, tiltCurveZ);
return new CameraTiltEffect(duration, tiltValue, tiltCurve);
}
}
}

View File

@@ -31,6 +31,7 @@ namespace Ichni
public LoadManager loadManager;
public ExportManager exportManager;
public BeatmapClipManager beatmapClipManager;
public BeatmapMergeManager beatmapMergeManager;
public NotePrefabManager notePrefabManager;
public AutoSaveManager autoSaveManager;
@@ -40,6 +41,7 @@ namespace Ichni
loadManager = new LoadManager();
exportManager = new ExportManager();
beatmapClipManager = new BeatmapClipManager();
beatmapMergeManager = new BeatmapMergeManager();
notePrefabManager = new NotePrefabManager();
autoSaveManager = new AutoSaveManager();
}
@@ -296,6 +298,57 @@ namespace Ichni
}
}
public class BeatmapMergeManager
{
public void MergeBeatmap(string mergeName)
{
string mergePath = Application.streamingAssetsPath + "/Merges/" + mergeName + ".json";
BeatmapContainer_BM merge = ES3.Load<BeatmapContainer_BM>("Beatmap", mergePath, ProjectManager.SaveSettings);
merge.elementList.ForEach(element =>
{
if (element == null)
{
Debug.LogError("Null element detected in elementList. Skipping execution.");
return;
}
if (BeatmapContainer_BM.LowPriorityGameElementTypes.Contains(element.GetType()))
{
return;
}
if (element is GameElement_BM gameElement)
{
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
}
if (element is GameCamera_BM || GameElement_BM.GetElementBM(element.attachedElementGuid) is GameCamera_BM)
{
return;
}
element.ExecuteBM();
});
merge.elementList.ForEach(element =>
{
if (element == null)
{
Debug.LogError("Null element detected in elementList during low-priority execution. Skipping execution.");
return;
}
if (BeatmapContainer_BM.LowPriorityGameElementTypes.Contains(element.GetType()))
{
element.ExecuteBM();
}
});
EditorManager.instance.beatmapContainer.ExecuteLowPriorityActions();
}
}
public class NotePrefabManager
{
private string notePrefabPath => Application.streamingAssetsPath + "/NotePrefabs";