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)
{
base.Initialize(baseElement, title, parameterName);
toggle.isOn = (bool)connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement); //获取对应变量的值
toggle.onValueChanged.AddListener(ApplyParameters);
if (parameterName != string.Empty)
{
toggle.isOn = (bool)connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement); //获取对应变量的值
toggle.onValueChanged.AddListener(ApplyParameters);
}
else
{
toggle.isOn = false;
}
}
private void ApplyParameters(bool value)

View File

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

View File

@@ -8,7 +8,7 @@ using UnityEngine.Serialization;
namespace Ichni.RhythmGame
{
public abstract class AnimationBase : GameElement, IHaveTimeDurationSubmodule
public abstract partial class AnimationBase : GameElement, IHaveTimeDurationSubmodule
{
public GameElement animatedObject;
public FlexibleReturnType animationReturnType;
@@ -21,6 +21,10 @@ namespace Ichni.RhythmGame
submoduleList.Add(timeDurationSubmodule);
}
/// <summary>
/// 更新动画
/// </summary>
/// <param name="songTime">歌曲时间</param>
protected abstract void UpdateAnimation(float songTime);
protected virtual void Update()
@@ -30,6 +34,16 @@ namespace Ichni.RhythmGame
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

View File

@@ -63,6 +63,15 @@ namespace Ichni.RhythmGame
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

View File

@@ -66,6 +66,15 @@ namespace Ichni.RhythmGame
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

View File

@@ -45,6 +45,12 @@ namespace Ichni.RhythmGame
targetTrackTimeSubmoduleStatic.trackTotalTime = totalTime.value;
}
}
public override void ApplyTimeOffset(float offset)
{
base.ApplyTimeOffset(offset);
totalTime.animations.ForEach(anim => anim.ApplyTimeOffset(offset));
}
}
public partial class TrackTotalTimeChange

View File

@@ -59,6 +59,14 @@ namespace Ichni.RhythmGame
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

View File

@@ -71,6 +71,12 @@ namespace Ichni.RhythmGame
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));
}
}
namespace Beatmap

View File

@@ -59,6 +59,14 @@ namespace Ichni.RhythmGame
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

View File

@@ -61,6 +61,14 @@ namespace Ichni.RhythmGame
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

View File

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

View File

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

View File

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

View File

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

View File

@@ -45,7 +45,8 @@ namespace Ichni.RhythmGame
List<EffectBase> effectList = new List<EffectBase>();
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);
}
@@ -283,7 +284,7 @@ namespace Ichni.RhythmGame
/// 转换为游戏类
/// </summary>
/// <returns></returns>
public abstract EffectBase ConvertToGameType();
public abstract EffectBase ConvertToGameType(GameElement attachedGameElement);
}
}
}

View File

@@ -161,6 +161,26 @@ namespace Ichni.RhythmGame
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

View File

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

View File

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

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
{
Renderer noteMainRenderer;
public BasicNoteBadExpand(NoteBase note)
public BasicNoteBadExpand(NoteVisualBase noteVisual)
{
this.note = note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
this.note = noteVisual.note;
this.noteVisual = note.noteVisual;
this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>();
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 BasicNoteGenerateExpand(NoteBase note)
public BasicNoteGenerateExpand(NoteVisualBase noteVisual)
{
this.note = note;
this.note = noteVisual.note;
this.noteVisual = noteVisual;
this.generateTime = 1f;
this.effectTime = 0.1f;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
}
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;
public BasicNoteGoodBurst(NoteBase note)
public BasicNoteGoodBurst(NoteVisualBase noteVisual)
{
this.note = note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
this.note = noteVisual.note;
this.noteVisual = noteVisual;
this.effectRing = noteVisual.effectPartList[0];
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;
public BasicNoteMissPale(NoteBase note)
public BasicNoteMissPale(NoteVisualBase noteVisual)
{
this.note = note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
this.note = noteVisual.note;
this.noteVisual = noteVisual;
this.noteMainRenderer = noteVisual.noteMain.GetComponent<Renderer>();
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;
public BasicNotePerfectBurst(NoteBase note)
public BasicNotePerfectBurst(NoteVisualBase noteVisual)
{
this.note = note;
this.noteVisual = note.noteVisual.GetComponent<BasicNoteVisual>();
this.note = noteVisual.note;
this.noteVisual = noteVisual;
this.effectRing = noteVisual.effectPartList[0];
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)
{
noteVisual.effectSubmodule.effectCollection["Generate"].Add(new BasicNoteGenerateExpand(noteVisual.note));
noteVisual.effectSubmodule.effectCollection["Perfect"].Add(new BasicNotePerfectBurst(noteVisual.note));
noteVisual.effectSubmodule.effectCollection["Good"].Add(new BasicNoteGoodBurst(noteVisual.note));
noteVisual.effectSubmodule.effectCollection["Bad"].Add(new BasicNoteBadExpand(noteVisual.note));
noteVisual.effectSubmodule.effectCollection["Miss"].Add(new BasicNoteMissPale(noteVisual.note));
noteVisual.effectSubmodule.effectCollection["Generate"].Add(new BasicNoteGenerateExpand(noteVisual));
noteVisual.effectSubmodule.effectCollection["Perfect"].Add(new BasicNotePerfectBurst(noteVisual));
noteVisual.effectSubmodule.effectCollection["Good"].Add(new BasicNoteGoodBurst(noteVisual));
noteVisual.effectSubmodule.effectCollection["Bad"].Add(new BasicNoteBadExpand(noteVisual));
noteVisual.effectSubmodule.effectCollection["Miss"].Add(new BasicNoteMissPale(noteVisual));
}
return noteVisual;