QuickCopy & fix NoteEffects

This commit is contained in:
SoulliesOfficial
2025-02-21 14:08:32 -05:00
parent 70eddeb881
commit 187b2efdad
28 changed files with 277 additions and 60 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -14,8 +14,15 @@ namespace Ichni.Editor
public override void Initialize(IBaseElement baseElement, string title, string parameterName) public override void Initialize(IBaseElement baseElement, string title, string parameterName)
{ {
base.Initialize(baseElement, title, parameterName); base.Initialize(baseElement, title, parameterName);
toggle.isOn = (bool)connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement); //获取对应变量的值 if (parameterName != string.Empty)
toggle.onValueChanged.AddListener(ApplyParameters); {
toggle.isOn = (bool)connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement); //获取对应变量的值
toggle.onValueChanged.AddListener(ApplyParameters);
}
else
{
toggle.isOn = false;
}
} }
private void ApplyParameters(bool value) private void ApplyParameters(bool value)

View File

@@ -91,7 +91,7 @@ namespace Ichni.Editor
{ {
EditorManager.instance.operationManager.SelectElement(connectedGameElement); EditorManager.instance.operationManager.SelectElement(connectedGameElement);
EditorManager.instance.uiManager.inspector.SetInspector(connectedGameElement); EditorManager.instance.uiManager.inspector.SetInspector(connectedGameElement);
EditorManager.instance.timeline.SetTimeLine(connectedGameElement); EditorManager.instance.timeline.SetTimeLine(connectedGameElement); // TODO: Error
} }
private void ExpandOrFold() private void ExpandOrFold()

View File

@@ -8,7 +8,7 @@ using UnityEngine.Serialization;
namespace Ichni.RhythmGame namespace Ichni.RhythmGame
{ {
public abstract class AnimationBase : GameElement, IHaveTimeDurationSubmodule public abstract partial class AnimationBase : GameElement, IHaveTimeDurationSubmodule
{ {
public GameElement animatedObject; public GameElement animatedObject;
public FlexibleReturnType animationReturnType; public FlexibleReturnType animationReturnType;
@@ -21,6 +21,10 @@ namespace Ichni.RhythmGame
submoduleList.Add(timeDurationSubmodule); submoduleList.Add(timeDurationSubmodule);
} }
/// <summary>
/// 更新动画
/// </summary>
/// <param name="songTime">歌曲时间</param>
protected abstract void UpdateAnimation(float songTime); protected abstract void UpdateAnimation(float songTime);
protected virtual void Update() protected virtual void Update()
@@ -30,6 +34,16 @@ namespace Ichni.RhythmGame
UpdateAnimation(EditorManager.instance.songInformation.songTime); UpdateAnimation(EditorManager.instance.songInformation.songTime);
} }
} }
/// <summary>
/// 施加时间偏移即移动所有Flexible参数的时间
/// </summary>
/// <param name="offset"></param>
public virtual void ApplyTimeOffset(float offset)
{
timeDurationSubmodule.startTime += offset;
timeDurationSubmodule.endTime += offset;
}
} }
namespace Beatmap namespace Beatmap

View File

@@ -63,6 +63,15 @@ namespace Ichni.RhythmGame
animationReturnType = FlexibleReturnType.MiddleInterval; 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 partial class BaseColorChange public partial class BaseColorChange

View File

@@ -66,6 +66,15 @@ namespace Ichni.RhythmGame
animationReturnType = FlexibleReturnType.MiddleInterval; 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 partial class EmissionColorChange

View File

@@ -45,6 +45,12 @@ namespace Ichni.RhythmGame
targetTrackTimeSubmoduleStatic.trackTotalTime = totalTime.value; 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 partial class TrackTotalTimeChange

View File

@@ -59,6 +59,14 @@ namespace Ichni.RhythmGame
animationReturnType = FlexibleReturnType.MiddleInterval; animationReturnType = FlexibleReturnType.MiddleInterval;
} }
} }
public override void ApplyTimeOffset(float offset)
{
base.ApplyTimeOffset(offset);
positionX.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
positionY.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
positionZ.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
}
} }
public partial class Displacement public partial class Displacement

View File

@@ -71,6 +71,12 @@ namespace Ichni.RhythmGame
matchedBM = new LookAt_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM, matchedBM = new LookAt_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
enabling.ConvertToBM(), lookAtObject.elementGuid); enabling.ConvertToBM(), lookAtObject.elementGuid);
} }
public override void ApplyTimeOffset(float offset)
{
base.ApplyTimeOffset(offset);
enabling.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
}
} }
namespace Beatmap namespace Beatmap

View File

@@ -59,6 +59,14 @@ namespace Ichni.RhythmGame
animationReturnType = FlexibleReturnType.MiddleInterval; animationReturnType = FlexibleReturnType.MiddleInterval;
} }
} }
public override void ApplyTimeOffset(float offset)
{
base.ApplyTimeOffset(offset);
scaleX.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
scaleY.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
scaleZ.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
}
} }
public partial class Scale public partial class Scale

View File

@@ -61,6 +61,14 @@ namespace Ichni.RhythmGame
animationReturnType = FlexibleReturnType.MiddleInterval; animationReturnType = FlexibleReturnType.MiddleInterval;
} }
} }
public override void ApplyTimeOffset(float offset)
{
base.ApplyTimeOffset(offset);
eulerAngleX.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
eulerAngleY.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
eulerAngleZ.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
}
} }
public partial class Swirl public partial class Swirl

View File

@@ -15,6 +15,11 @@ namespace Ichni.RhythmGame
this.value = value; this.value = value;
this.time = time; this.time = time;
} }
public void ApplyTimeOffset(float offset)
{
time += offset;
}
} }
[System.Serializable] [System.Serializable]

View File

@@ -26,6 +26,12 @@ namespace Ichni.RhythmGame
this.endTime = endTime; this.endTime = endTime;
this.animationCurveType = animationCurveType; this.animationCurveType = animationCurveType;
} }
public void ApplyTimeOffset(float offset)
{
startTime += offset;
endTime += offset;
}
/// <summary> /// <summary>
/// 按照起始时间排序 /// 按照起始时间排序

View File

@@ -21,6 +21,11 @@ namespace Ichni.RhythmGame
this.value = value; this.value = value;
this.time = time; this.time = time;
} }
public void ApplyTimeOffset(float offset)
{
time += offset;
}
} }
[System.Serializable] [System.Serializable]

View File

@@ -2,7 +2,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace Ichni namespace Ichni.RhythmGame
{ {
public enum FlexibleReturnType public enum FlexibleReturnType
{ {

View File

@@ -45,7 +45,8 @@ namespace Ichni.RhythmGame
List<EffectBase> effectList = new List<EffectBase>(); List<EffectBase> effectList = new List<EffectBase>();
foreach (var effectBM in effect.Value) foreach (var effectBM in effect.Value)
{ {
effectList.Add(effectBM.ConvertToGameType()); Debug.Log(attachedGameElement.GetType().ToString());
effectList.Add(effectBM.ConvertToGameType(attachedGameElement));
} }
effectCollection.Add(effect.Key, effectList); effectCollection.Add(effect.Key, effectList);
} }
@@ -283,7 +284,7 @@ namespace Ichni.RhythmGame
/// 转换为游戏类 /// 转换为游戏类
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract EffectBase ConvertToGameType(); public abstract EffectBase ConvertToGameType(GameElement attachedGameElement);
} }
} }
} }

View File

@@ -161,6 +161,26 @@ namespace Ichni.RhythmGame
submodule.SetUpInspector(); submodule.SetUpInspector();
} }
} }
/// <summary>
/// 获取自身和所有子GameElement
/// </summary>
public List<GameElement> GetAllGameElementsFromThis()
{
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);
return gameElements;
}
} }
namespace Beatmap namespace Beatmap

View File

@@ -64,7 +64,7 @@ namespace Ichni.RhythmGame
this.bloomPeak = bloomPeak; this.bloomPeak = bloomPeak;
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BloomShake(bloomTime, bloomPeak); return new BloomShake(bloomTime, bloomPeak);
} }

View File

@@ -152,18 +152,16 @@ namespace Ichni.RhythmGame
var xField = qcWindow.GenerateGetterInputField(qcContainer, "X offset", "0"); var xField = qcWindow.GenerateGetterInputField(qcContainer, "X offset", "0");
var yField = qcWindow.GenerateGetterInputField(qcContainer, "Y offset", "0"); var yField = qcWindow.GenerateGetterInputField(qcContainer, "Y offset", "0");
var zField = qcWindow.GenerateGetterInputField(qcContainer, "Z offset", "0"); var zField = qcWindow.GenerateGetterInputField(qcContainer, "Z offset", "0");
var timeField = qcWindow.GenerateGetterInputField(qcContainer, "Time offset", "0");
var iterationField = qcWindow.GenerateGetterInputField(qcContainer, "Iteration", "0");
var includeAnimationToggle = qcWindow.GenerateToggle(null, qcContainer, "Include Animation", string.Empty);
qcWindow.GenerateButton(this, qcContainer, "Copy", () => qcWindow.GenerateButton(this, qcContainer, "Copy", () =>
{ {
CopyPasteDeleteModule cpd = EditorManager.instance.operationManager.CopyPasteDeleteModule; Vector3 positionOffset = new Vector3(xField.GetResult<float>(), yField.GetResult<float>(), zField.GetResult<float>());
cpd.CopyElement(this); float timeOffset = timeField.GetResult<float>();
cpd.PasteElement(parentElement); int iteration = iterationField.GetResult<int>();
Track newTrack = cpd.pastedElementList[0] as Track; bool includeAnimation = includeAnimationToggle.toggle.isOn;
newTrack.trackPathSubmodule.pathNodeList.ForEach(pn => QuickCopy(positionOffset, timeOffset, includeAnimation, iteration);
{
Vector3 offset = new Vector3(xField.GetResult<float>(), yField.GetResult<float>(), zField.GetResult<float>());
pn.transformSubmodule.originalPosition += offset;
pn.transformSubmodule.Refresh();
});
}); });
}); });

View File

@@ -0,0 +1,76 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Ichni.Editor;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class Track
{
/// <summary>
/// 快速复制粘贴Track
/// </summary>
/// <param name="unitPositionOffset">单位位置整体偏移</param>
/// <param name="unitTimeOffset">单位时间偏移</param>
/// <param name="iteration">迭代次数即产生几个粘贴的Track</param>
private void QuickCopy(Vector3 unitPositionOffset, float unitTimeOffset, bool includeAnimations = true, int iteration = 1)
{
if(iteration <= 0) return;
CopyPasteDeleteModule cpd = EditorManager.instance.operationManager.CopyPasteDeleteModule;
cpd.CopyElement(this);
for (int i = 1; i <= iteration; i++)
{
cpd.PasteElement(parentElement);
Track newTrack = cpd.pastedElementList[0] as Track;
Vector3 positionOffset = unitPositionOffset * i;
float timeOffset = unitTimeOffset * i;
//对Track的所有有效的Submodule和子GameElement进行偏移
if (newTrack.trackTimeSubmodule is TrackTimeSubmoduleMovable movable)
{
movable.trackStartTime += timeOffset;
movable.trackEndTime += timeOffset;
}
newTrack.trackPathSubmodule.pathNodeList.ForEach(pn =>
{
pn.transformSubmodule.originalPosition += positionOffset;
pn.transformSubmodule.Refresh();
});
List<GameElement> allNewGameElements = newTrack.GetAllGameElementsFromThis();
List<TrackPercentPoint> percentPoints = allNewGameElements
.FindAll(x => x is TrackPercentPoint).Cast<TrackPercentPoint>().ToList();
percentPoints.ForEach(pp =>
{
pp.trackPercent.animations.ForEach(anim => anim.ApplyTimeOffset(timeOffset));
});
List<NoteBase> notes = allNewGameElements.FindAll(x => x is NoteBase).Cast<NoteBase>().ToList();
notes.ForEach(note =>
{
note.exactJudgeTime += timeOffset;
note.Refresh();
});
if (includeAnimations)
{
List<AnimationBase> animations = allNewGameElements
.FindAll(x => x.GetType().IsSubclassOf(typeof(AnimationBase))).Cast<AnimationBase>().ToList();
animations.ForEach(anim =>
{
anim.ApplyTimeOffset(timeOffset);
});
}
}
cpd.pastedElementList.Clear();
}
}
}

View File

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

View File

@@ -11,10 +11,10 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
public class BasicNoteBadExpand : NoteBadEffect public class BasicNoteBadExpand : NoteBadEffect
{ {
Renderer noteMainRenderer; Renderer noteMainRenderer;
public BasicNoteBadExpand(NoteBase note) public BasicNoteBadExpand(NoteVisualBase noteVisual)
{ {
this.note = note; this.note = noteVisual.note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>(); this.noteVisual = note.noteVisual;
this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>(); this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>();
this.effectTime = 0.1f; this.effectTime = 0.1f;
} }
@@ -59,9 +59,9 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BasicNoteBadExpand(GameElement_BM.GetElement(attachedNoteID) as NoteBase); return new BasicNoteBadExpand(attachedGameElement as NoteVisualBase);
} }
} }
} }

View File

@@ -12,12 +12,12 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
{ {
public class BasicNoteGenerateExpand : NoteGenerateEffect public class BasicNoteGenerateExpand : NoteGenerateEffect
{ {
public BasicNoteGenerateExpand(NoteBase note) public BasicNoteGenerateExpand(NoteVisualBase noteVisual)
{ {
this.note = note; this.note = noteVisual.note;
this.noteVisual = noteVisual;
this.generateTime = 1f; this.generateTime = 1f;
this.effectTime = 0.1f; this.effectTime = 0.1f;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
} }
public override void Recover() public override void Recover()
@@ -61,9 +61,9 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BasicNoteGenerateExpand(GameElement_BM.GetElement(attachedNoteID) as NoteBase); return new BasicNoteGenerateExpand(attachedGameElement as NoteVisualBase);
} }
} }
} }

View File

@@ -13,10 +13,10 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
{ {
private GameObject effectRing; private GameObject effectRing;
public BasicNoteGoodBurst(NoteBase note) public BasicNoteGoodBurst(NoteVisualBase noteVisual)
{ {
this.note = note; this.note = noteVisual.note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>(); this.noteVisual = noteVisual;
this.effectRing = noteVisual.effectPartList[0]; this.effectRing = noteVisual.effectPartList[0];
this.effectTime = 0.1f; this.effectTime = 0.1f;
} }
@@ -64,9 +64,9 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BasicNoteGoodBurst(GameElement_BM.GetElement(attachedNoteID) as NoteBase); return new BasicNoteGoodBurst(attachedGameElement as NoteVisualBase);
} }
} }
} }

View File

@@ -12,10 +12,10 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
{ {
Renderer noteMainRenderer; Renderer noteMainRenderer;
public BasicNoteMissPale(NoteBase note) public BasicNoteMissPale(NoteVisualBase noteVisual)
{ {
this.note = note; this.note = noteVisual.note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>(); this.noteVisual = noteVisual;
this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>(); this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>();
this.effectTime = 0.2f; this.effectTime = 0.2f;
} }
@@ -59,10 +59,10 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
{ {
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BasicNoteMissPale(GameElement_BM.GetElement(attachedNoteID) as NoteBase); return new BasicNoteMissPale(attachedGameElement as NoteVisualBase);
} }
} }
} }

View File

@@ -13,10 +13,10 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
{ {
private GameObject effectRing; private GameObject effectRing;
public BasicNotePerfectBurst(NoteBase note) public BasicNotePerfectBurst(NoteVisualBase noteVisual)
{ {
this.note = note; this.note = noteVisual.note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>(); this.noteVisual = noteVisual;
this.effectRing = noteVisual.effectPartList[0]; this.effectRing = noteVisual.effectPartList[0];
this.effectTime = 0.1f; this.effectTime = 0.1f;
} }
@@ -64,9 +64,9 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
} }
public override EffectBase ConvertToGameType() public override EffectBase ConvertToGameType(GameElement attachedGameElement)
{ {
return new BasicNotePerfectBurst(GameElement_BM.GetElement(attachedNoteID) as NoteBase); return new BasicNotePerfectBurst(attachedGameElement as NoteVisualBase);
} }
} }
} }

View File

@@ -22,11 +22,11 @@ namespace Ichni.RhythmGame.ThemeBundles.Basic
if (isFirstGenerated) if (isFirstGenerated)
{ {
noteVisual.effectSubmodule.effectCollection["Generate"].Add(new BasicNoteGenerateExpand(noteVisual.note)); noteVisual.effectSubmodule.effectCollection["Generate"].Add(new BasicNoteGenerateExpand(noteVisual));
noteVisual.effectSubmodule.effectCollection["Perfect"].Add(new BasicNotePerfectBurst(noteVisual.note)); noteVisual.effectSubmodule.effectCollection["Perfect"].Add(new BasicNotePerfectBurst(noteVisual));
noteVisual.effectSubmodule.effectCollection["Good"].Add(new BasicNoteGoodBurst(noteVisual.note)); noteVisual.effectSubmodule.effectCollection["Good"].Add(new BasicNoteGoodBurst(noteVisual));
noteVisual.effectSubmodule.effectCollection["Bad"].Add(new BasicNoteBadExpand(noteVisual.note)); noteVisual.effectSubmodule.effectCollection["Bad"].Add(new BasicNoteBadExpand(noteVisual));
noteVisual.effectSubmodule.effectCollection["Miss"].Add(new BasicNoteMissPale(noteVisual.note)); noteVisual.effectSubmodule.effectCollection["Miss"].Add(new BasicNoteMissPale(noteVisual));
} }
return noteVisual; return noteVisual;