效果模块,以及代码位置整理

This commit is contained in:
SoulliesOfficial
2025-02-16 11:15:42 -05:00
parent 934d1b5aba
commit d77e1a0f70
204 changed files with 1107 additions and 347 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 011e3f878bbe944f68b6d335600e3b80
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.RhythmGame
{
public abstract class AnimationBase : GameElement, IHaveTimeDurationSubmodule
{
public GameElement animatedObject;
public FlexibleReturnType animationReturnType;
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected abstract void UpdateAnimation(float songTime);
protected virtual void Update()
{
if (timeDurationSubmodule.CheckTimeInDuration(EditorManager.instance.songInformation.songTime))
{
UpdateAnimation(EditorManager.instance.songInformation.songTime);
}
}
}
namespace 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)
{
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e3418d0d84b6b476db0e552f2e754c7e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using System;
using System.Collections;
using System.Collections.Generic;
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;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
colorR.UpdateFlexibleFloat(songTime);
colorG.UpdateFlexibleFloat(songTime);
colorB.UpdateFlexibleFloat(songTime);
colorA.UpdateFlexibleFloat(songTime);
if (colorR.returnType is FlexibleReturnType.MiddleExecuting ||
colorG.returnType is FlexibleReturnType.MiddleExecuting ||
colorB.returnType is FlexibleReturnType.MiddleExecuting ||
colorA.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Color colorOffset = new Color(colorR.value, colorG.value, colorB.value, colorA.value);
targetColorSubmodule.baseColorOffset.Add(colorOffset);
targetColorSubmodule.baseColorDirtyMark = true;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
}
}
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, elementGuid, tags, false,
parent, colorR.ConvertToGameType(), colorG.ConvertToGameType(),
colorB.ConvertToGameType(), colorA.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections;
using System.Collections.Generic;
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;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
colorR.UpdateFlexibleFloat(songTime);
colorG.UpdateFlexibleFloat(songTime);
colorB.UpdateFlexibleFloat(songTime);
colorI.UpdateFlexibleFloat(songTime);
if (colorR.returnType is FlexibleReturnType.MiddleExecuting ||
colorG.returnType is FlexibleReturnType.MiddleExecuting ||
colorB.returnType is FlexibleReturnType.MiddleExecuting ||
colorI.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Color colorOffset = new Color(colorR.value, colorG.value, colorB.value);
float intensityOffset = colorI.value;
targetColorSubmodule.emissionColorOffset.Add(colorOffset);
targetColorSubmodule.emissionIntensityOffset.Add(intensityOffset);
targetColorSubmodule.emissionColorDirtyMark = true;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
}
}
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());
}
}
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, elementGuid, tags, false, parent,
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 17936224adc4a4e3497f05188aeb115f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections;
using System.Collections.Generic;
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;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
totalTime.UpdateFlexibleFloat(songTime);
if (totalTime.returnType == FlexibleReturnType.MiddleExecuting)
{
targetTrackTimeSubmoduleStatic.trackTotalTime = totalTime.value;
}
}
}
public partial class TrackTotalTimeChange
{
public override void SaveBM()
{
matchedBM = new TrackTotalTimeChange_BM(elementName, elementGuid, tags, animatedObject.matchedBM as Track_BM, totalTime.ConvertToBM());
}
}
namespace Beatmap
{
public class TrackTotalTimeChange_BM : GameElement_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, elementGuid, tags, false,
parent as Track, totalTime.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 469791310ebae4cbbb29b4d818077938
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,126 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class Displacement : AnimationBase
{
private TransformSubmodule targetTransformSubmodule;
public FlexibleFloat positionX, positionY, positionZ;
public static Displacement GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
FlexibleFloat positionX, FlexibleFloat positionY, FlexibleFloat positionZ)
{
Displacement displacement = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<Displacement>();
displacement.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
displacement.animatedObject = animatedObject;
displacement.positionX = positionX;
displacement.positionY = positionY;
displacement.positionZ = positionZ;
displacement.animationReturnType = FlexibleReturnType.Before;
displacement.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
//displacement.timeDurationSubmodule.SetDuration(positionX, positionY, positionZ);
return displacement;
}
protected override void UpdateAnimation(float songTime)
{
positionX.UpdateFlexibleFloat(songTime);
positionY.UpdateFlexibleFloat(songTime);
positionZ.UpdateFlexibleFloat(songTime);
if (positionX.returnType is FlexibleReturnType.MiddleExecuting or FlexibleReturnType.After or FlexibleReturnType.Before ||
positionY.returnType is FlexibleReturnType.MiddleExecuting or FlexibleReturnType.After or FlexibleReturnType.Before ||
positionZ.returnType is FlexibleReturnType.MiddleExecuting or FlexibleReturnType.After or FlexibleReturnType.Before)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
targetTransformSubmodule.positionOffset.Add(currentPosition);
targetTransformSubmodule.positionDirtyMark = true;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
}
}
public partial class Displacement
{
public override void SaveBM()
{
matchedBM = new Beatmap.Displacement_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
positionX.ConvertToBM(), positionY.ConvertToBM(), positionZ.ConvertToBM());
}
public override void SetUpInspector()
{
base.SetUpInspector();
var container = inspector.GenerateContainer("Displacement");
var positionXButton = inspector.GenerateButton(this, container, "Position X",
() =>
{
inspector.GenerateCompositeParameterWindow(this, "Position X", nameof(positionX)).SetAsFlexibleFloat();
});
var positionYButton = inspector.GenerateButton(this, container, "Position Y",
() =>
{
inspector.GenerateCompositeParameterWindow(this, "Position Y", nameof(positionY)).SetAsFlexibleFloat();
});
var positionZButton = inspector.GenerateButton(this, container, "Position Z",
() =>
{
inspector.GenerateCompositeParameterWindow(this, "Position Z", nameof(positionZ)).SetAsFlexibleFloat();
});
}
}
namespace 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, elementGuid, tags, false, parent,
positionX.ConvertToGameType(), positionY.ConvertToGameType(), positionZ.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections;
using System.Collections.Generic;
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 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.timeDurationSubmodule.SetDuration(-999f, 999f); //TODO: 换为(-delay, songLength)
return look;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
enabling.UpdateFlexibleBool(songTime);
if (enabling.value)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 lookingDirection =
(lookAtObject.transform.position - animatedObject.transform.position).normalized;
Vector3 eulerAnglesOffset = Quaternion.LookRotation(lookingDirection).eulerAngles;
targetTransformSubmodule.eulerAnglesOffsetLock = true;
targetTransformSubmodule.currentEulerAngles = eulerAnglesOffset;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
targetTransformSubmodule.eulerAnglesOffsetLock = false;
}
}
public override void SaveBM()
{
matchedBM = new LookAt_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
enabling.ConvertToBM(), lookAtObject.elementGuid);
}
}
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());
}
public override GameElement DuplicateBM(GameElement parent)
{
return LookAt.GenerateElement(elementName, elementGuid, tags, false, parent,
GetElement(lookAtObjectGuid), enabling.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class Scale : AnimationBase
{
public TransformSubmodule targetTransformSubmodule;
public FlexibleFloat scaleX, scaleY, scaleZ;
public static Scale GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
FlexibleFloat scaleX, FlexibleFloat scaleY, FlexibleFloat scaleZ)
{
Scale scale = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<Scale>();
scale.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
scale.animatedObject = animatedObject;
scale.scaleX = scaleX;
scale.scaleY = scaleY;
scale.scaleZ = scaleZ;
scale.animationReturnType = FlexibleReturnType.Before;
scale.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
//scale.timeDurationSubmodule.SetDuration(scaleX, scaleY, scaleZ);
return scale;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
scaleX.UpdateFlexibleFloat(songTime);
scaleY.UpdateFlexibleFloat(songTime);
scaleZ.UpdateFlexibleFloat(songTime);
if (scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
scaleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
targetTransformSubmodule.scaleOffset.Add(currentScale);
targetTransformSubmodule.scaleDirtyMark = true;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
}
}
public partial class Scale
{
public override void SaveBM()
{
matchedBM = new Scale_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
scaleX.ConvertToBM(), scaleY.ConvertToBM(), scaleZ.ConvertToBM());
}
}
namespace Beatmap
{
public class Scale_BM : GameElement_BM
{
public FlexibleFloat_BM scaleX, scaleY, scaleZ;
public Scale_BM()
{
}
public Scale_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
FlexibleFloat_BM scaleX, FlexibleFloat_BM scaleY, FlexibleFloat_BM scaleZ)
: base(elementName, elementGuid, tags, attachedElement)
{
this.scaleX = scaleX;
this.scaleY = scaleY;
this.scaleZ = scaleZ;
}
public override void ExecuteBM()
{
matchedElement = Scale.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
scaleX.ConvertToGameType(), scaleY.ConvertToGameType(), scaleZ.ConvertToGameType());
}
public override GameElement DuplicateBM(GameElement parent)
{
return Scale.GenerateElement(elementName, elementGuid, tags, false,
parent, scaleX.ConvertToGameType(), scaleY.ConvertToGameType(), scaleZ.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class Swirl : AnimationBase
{
private TransformSubmodule targetTransformSubmodule;
public FlexibleFloat eulerAngleX, eulerAngleY, eulerAngleZ;
public static Swirl GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement animatedObject,
FlexibleFloat eulerAngleX, FlexibleFloat eulerAngleY, FlexibleFloat eulerAngleZ)
{
Swirl swirl = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<Swirl>();
swirl.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
swirl.animatedObject = animatedObject;
swirl.eulerAngleX = eulerAngleX;
swirl.eulerAngleY = eulerAngleY;
swirl.eulerAngleZ = eulerAngleZ;
swirl.animationReturnType = FlexibleReturnType.Before;
swirl.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
//swirl.timeDurationSubmodule.SetDuration(eulerAngleX, eulerAngleY, eulerAngleZ);
return swirl;
}
protected override void SetDefaultSubmodules()
{
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(timeDurationSubmodule);
}
protected override void UpdateAnimation(float songTime)
{
eulerAngleX.UpdateFlexibleFloat(songTime);
eulerAngleY.UpdateFlexibleFloat(songTime);
eulerAngleZ.UpdateFlexibleFloat(songTime);
if (eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting)
{
animationReturnType = FlexibleReturnType.MiddleExecuting;
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
targetTransformSubmodule.eulerAnglesOffset.Add(currentEulerAngles);
targetTransformSubmodule.eulerAnglesDirtyMark = true;
}
else
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
}
}
public partial class Swirl
{
public override void SaveBM()
{
matchedBM = new Swirl_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
eulerAngleX.ConvertToBM(), eulerAngleY.ConvertToBM(), eulerAngleZ.ConvertToBM());
}
}
namespace Beatmap
{
public class Swirl_BM : AnimationBase_BM
{
public FlexibleFloat_BM eulerAngleX, eulerAngleY, eulerAngleZ;
public Swirl_BM()
{
}
public Swirl_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
FlexibleFloat_BM eulerAngleX, FlexibleFloat_BM eulerAngleY, FlexibleFloat_BM eulerAngleZ)
: base(elementName, elementGuid, tags, attachedElement)
{
this.eulerAngleX = eulerAngleX;
this.eulerAngleY = eulerAngleY;
this.eulerAngleZ = eulerAngleZ;
}
public override void ExecuteBM()
{
matchedElement = Swirl.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
eulerAngleX.ConvertToGameType(), eulerAngleY.ConvertToGameType(), eulerAngleZ.ConvertToGameType());
}
public override GameElement DuplicateBM(GameElement parent)
{
return Swirl.GenerateElement(elementName, elementGuid, tags, false, parent,
eulerAngleX.ConvertToGameType(), eulerAngleY.ConvertToGameType(), eulerAngleZ.ConvertToGameType());
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cf41da2409cb34cd7b2d92548a04b8a3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Scripts/EditorGame/Base/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Sirenix.OdinInspector;
using UniRx;
using UnityEngine;
namespace Ichni.RhythmGame
{
public interface IBaseElement
{
public BaseElement_BM matchedBM { get; set; }
/// <summary>
/// 用于生成存档
/// </summary>
public void SaveBM();
/// <summary>
/// 刷新物体的状态
/// </summary>
public void Refresh();
/// <summary>
/// 当物体被删除时执行的方法
/// </summary>
public void OnDelete()
{
throw new NotImplementedException();
}
/// <summary>
/// 删除物体,包括所有子物体
/// </summary>
public void Delete()
{
throw new NotImplementedException();
}
public Inspector inspector => EditorManager.instance.uiManager.inspector;
public void SetUpInspector();
}
// public virtual void SetTimeDuration()
// {
//
// }
//
// public void ApplyTimeDuration()
// {
// childElementList.ForEach(x => x.ApplyTimeDuration());
// timeDurationSubmodule?.SetDurationFromChildren(
// childElementList.Select(x => x.timeDurationSubmodule).ToList());
// }
//
namespace Beatmap
{
public abstract class BaseElement_BM
{
/// <summary>
/// 从存档类中生成游戏物体
/// </summary>
public abstract void ExecuteBM();
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fda5a36c77610481e976e5d7ceb764ab
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,397 @@
using UnityEngine;
using System;
using System.Collections.Generic;
namespace Ichni
{
public enum AnimationCurveType //预设动画曲线类型
{
Linear = 0,
InQuad = 1,
OutQuad = 2,
InOutQuad = 3,
InCubic = 4,
OutCubic = 5,
InOutCubic = 6,
InQuart = 7,
OutQuart = 8,
InOutQuart = 9,
InQuint = 10,
OutQuint = 11,
InOutQuint = 12,
InSine = 13,
OutSine = 14,
InOutSine = 15,
InExpo = 16,
OutExpo = 17,
InOutExpo = 18,
InCirc = 19,
OutCirc = 20,
InOutCirc = 21,
InBounce = 22,
OutBounce = 23,
InOutBounce = 24,
InElastic = 25,
OutElastic = 26,
InOutElastic = 27,
InBack = 28,
OutBack = 29,
InOutBack = 30
}
public static class AnimationCurveEvaluator
{
public static float Evaluate(AnimationCurveType animationCurveType, float t)
{
t = Mathf.Clamp(t, 0, 1);
switch (animationCurveType)
{
case AnimationCurveType.Linear:
return Linear(0, 1, t);
case AnimationCurveType.InQuad:
return InQuad(0, 1, t);
case AnimationCurveType.OutQuad:
return OutQuad(0, 1, t);
case AnimationCurveType.InOutQuad:
return InOutQuad(0, 1, t);
case AnimationCurveType.InCubic:
return InCubic(0, 1, t);
case AnimationCurveType.OutCubic:
return OutCubic(0, 1, t);
case AnimationCurveType.InOutCubic:
return InOutCubic(0, 1, t);
case AnimationCurveType.InQuart:
return InQuart(0, 1, t);
case AnimationCurveType.OutQuart:
return OutQuart(0, 1, t);
case AnimationCurveType.InOutQuart:
return InOutQuart(0, 1, t);
case AnimationCurveType.InQuint:
return InQuint(0, 1, t);
case AnimationCurveType.OutQuint:
return OutQuint(0, 1, t);
case AnimationCurveType.InOutQuint:
return InOutQuint(0, 1, t);
case AnimationCurveType.InSine:
return InSine(0, 1, t);
case AnimationCurveType.OutSine:
return OutSine(0, 1, t);
case AnimationCurveType.InOutSine:
return InOutSine(0, 1, t);
case AnimationCurveType.InExpo:
return InExpo(0, 1, t);
case AnimationCurveType.OutExpo:
return OutExpo(0, 1, t);
case AnimationCurveType.InOutExpo:
return InOutExpo(0, 1, t);
case AnimationCurveType.InCirc:
return InCirc(0, 1, t);
case AnimationCurveType.OutCirc:
return OutCirc(0, 1, t);
case AnimationCurveType.InOutCirc:
return InOutCirc(0, 1, t);
case AnimationCurveType.InBounce:
return InBounce(0, 1, t);
case AnimationCurveType.OutBounce:
return OutBounce(0, 1, t);
case AnimationCurveType.InOutBounce:
return InOutBounce(0, 1, t);
case AnimationCurveType.InElastic:
return InElastic(0, 1, t);
case AnimationCurveType.OutElastic:
return OutElastic(0, 1, t);
case AnimationCurveType.InOutElastic:
return InOutElastic(0, 1, t);
case AnimationCurveType.InBack:
return InBack(0, 1, t);
case AnimationCurveType.OutBack:
return OutBack(0, 1, t);
case AnimationCurveType.InOutBack:
return InOutBack(0, 1, t);
}
throw new NotImplementedException($"Animation curve type {animationCurveType} is not implemented.");
}
#region 线
private static float Linear(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return c * t / 1f + from;
}
private static float InQuad(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return c * t * t + from;
}
private static float OutQuad(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return -c * t * (t - 2f) + from;
}
private static float InOutQuad(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1) return c / 2f * t * t + from;
t--;
return -c / 2f * (t * (t - 2) - 1) + from;
}
private static float InCubic(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return c * t * t * t + from;
}
private static float OutCubic(float from, float to, float t)
{
float c = to - from;
t /= 1f;
t--;
return c * (t * t * t + 1) + from;
}
private static float InOutCubic(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1) return c / 2f * t * t * t + from;
t -= 2;
return c / 2f * (t * t * t + 2) + from;
}
private static float InQuart(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return c * t * t * t * t + from;
}
private static float OutQuart(float from, float to, float t)
{
float c = to - from;
t /= 1f;
t--;
return -c * (t * t * t * t - 1) + from;
}
private static float InOutQuart(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1) return c / 2f * t * t * t * t + from;
t -= 2;
return -c / 2f * (t * t * t * t - 2) + from;
}
private static float InQuint(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return c * t * t * t * t * t + from;
}
private static float OutQuint(float from, float to, float t)
{
float c = to - from;
t /= 1f;
t--;
return c * (t * t * t * t * t + 1) + from;
}
private static float InOutQuint(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1) return c / 2f * t * t * t * t * t + from;
t -= 2;
return c / 2f * (t * t * t * t * t + 2) + from;
}
private static float InSine(float from, float to, float t)
{
float c = to - from;
return -c * Mathf.Cos(t / 1f * (Mathf.PI / 2f)) + c + from;
}
private static float OutSine(float from, float to, float t)
{
float c = to - from;
return c * Mathf.Sin(t / 1f * (Mathf.PI / 2f)) + from;
}
private static float InOutSine(float from, float to, float t)
{
float c = to - from;
return -c / 2f * (Mathf.Cos(Mathf.PI * t / 1f) - 1) + from;
}
private static float InExpo(float from, float to, float t)
{
float c = to - from;
return c * Mathf.Pow(2, 10 * (t / 1f - 1)) + from;
}
private static float OutExpo(float from, float to, float t)
{
float c = to - from;
return c * (-Mathf.Pow(2, -10 * t / 1f) + 1) + from;
}
private static float InOutExpo(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1f) return c / 2f * Mathf.Pow(2, 10 * (t - 1)) + from;
t--;
return c / 2f * (-Mathf.Pow(2, -10 * t) + 2) + from;
}
private static float InCirc(float from, float to, float t)
{
float c = to - from;
t /= 1f;
return -c * (Mathf.Sqrt(1 - t * t) - 1) + from;
}
private static float OutCirc(float from, float to, float t)
{
float c = to - from;
t /= 1f;
t--;
return c * Mathf.Sqrt(1 - t * t) + from;
}
private static float InOutCirc(float from, float to, float t)
{
float c = to - from;
t /= 0.5f;
if (t < 1) return -c / 2f * (Mathf.Sqrt(1 - t * t) - 1) + from;
t -= 2;
return c / 2f * (Mathf.Sqrt(1 - t * t) + 1) + from;
}
private static float InBounce(float from, float to, float t)
{
float c = to - from;
return c - OutBounce(0f, c, 1f - t) + from; //does this work?
}
private static float OutBounce(float from, float to, float t)
{
float c = to - from;
if ((t /= 1f) < (1 / 2.75f))
{
return c * (7.5625f * t * t) + from;
}
else if (t < (2 / 2.75f))
{
return c * (7.5625f * (t -= (1.5f / 2.75f)) * t + .75f) + from;
}
else if (t < (2.5 / 2.75))
{
return c * (7.5625f * (t -= (2.25f / 2.75f)) * t + .9375f) + from;
}
else
{
return c * (7.5625f * (t -= (2.625f / 2.75f)) * t + .984375f) + from;
}
}
private static float InOutBounce(float from, float to, float t)
{
float c = to - from;
if (t < 0.5f) return InBounce(0, c, t * 2f) * 0.5f + from;
return OutBounce(0, c, t * 2 - 1) * 0.5f + c * 0.5f + from;
}
private static float InElastic(float from, float to, float t)
{
float c = to - from;
if (t == 0) return from;
if ((t /= 1f) == 1) return from + c;
float p = 0.3f;
float s = p / 4f;
return -(c * Mathf.Pow(2, 10 * (t -= 1)) * Mathf.Sin((t - s) * (2 * Mathf.PI) / p)) + from;
}
private static float OutElastic(float from, float to, float t)
{
float c = to - from;
if (t == 0) return from;
if ((t /= 1f) == 1) return from + c;
float p = 0.3f;
float s = p / 4f;
return (c * Mathf.Pow(2, -10 * t) * Mathf.Sin((t - s) * (2 * Mathf.PI) / p) + c + from);
}
private static float InOutElastic(float from, float to, float t)
{
float c = to - from;
if (t == 0) return from;
if ((t /= 0.5f) == 2) return from + c;
float p = 0.3f * 1.5f;
float s = p / 4f;
if (t < 1)
return -0.5f * (c * Mathf.Pow(2, 10 * (t -= 1f)) * Mathf.Sin((t - 2) * (2 * Mathf.PI) / p)) + from;
return c * Mathf.Pow(2, -10 * (t -= 1)) * Mathf.Sin((t - s) * (2f * Mathf.PI) / p) * 0.5f + c + from;
}
private static float InBack(float from, float to, float t)
{
float c = to - from;
float s = 1.70158f;
t /= 0.5f;
return c * t * t * ((s + 1) * t - s) + from;
}
private static float OutBack(float from, float to, float t)
{
float c = to - from;
float s = 1.70158f;
t = t / 1f - 1f;
return c * (t * t * ((s + 1) * t + s) + 1) + from;
}
private static float InOutBack(float from, float to, float t)
{
float c = to - from;
float s = 1.70158f;
t /= 0.5f;
if (t < 1) return c / 2f * (t * t * (((s *= (1.525f)) + 1) * t - s)) + from;
t -= 2;
return c / 2f * (t * t * (((s *= (1.525f)) + 1) * t + s) + 2) + from;
}
#endregion
}
// [System.Serializable]
// public class PresetAnimationCurve
// {
// public AnimationCurveType animationCurveType; //动画曲线类型
//
// public PresetAnimationCurve(AnimationCurveType animationCurveType)
// {
// this.animationCurveType = animationCurveType;
// }
//
// /// <summary>
// /// 根据Type选择曲线并计算t点(0,1)时曲线的值若t越界则直接返回0或1
// /// </summary>
// public float Evaluate(float t)
// {
// return AnimationCurveEvaluator.Evaluate(this.animationCurveType, t);
// }
// }
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b6924511d06874727a50bcbd03bc326a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,126 @@
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;
}
}
[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)
{
for (int i = 0; i < animations.Count; i++)
{
if (nowTime >= animations[i].time)
{
return animations[i];
}
}
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;
}
}
}
}

View File

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

View File

@@ -0,0 +1,213 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
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;
}
/// <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 FlexibleReturnType returnType;
public FlexibleFloat()
{
animations = new List<AnimatedFloat>();
}
public FlexibleFloat(List<AnimatedFloat> anim)
{
animations = anim;
}
public void Add(AnimatedFloat animatedFloat)
{
animations.Add(animatedFloat);
}
public void Sort()
{
animations.Sort();
}
/// <summary>
/// 在动画脚本的Update中更新value
/// </summary>
/// <param name="歌曲时间"></param>
public void UpdateFlexibleFloat(float nowTime)
{
AnimatedFloat nowAnimatedFloat = GetAnimatedFloat(nowTime); //获取当前时间点对应的AnimatedFloat
if (nowAnimatedFloat != null) //如果能获取到,表明当前时间点存在动画
{
//获取songTime时间点时基于动画曲线的AnimatedFloat比例点->01
float nowPercent = AnimationCurveEvaluator.Evaluate(nowAnimatedFloat.animationCurveType,
(nowTime - nowAnimatedFloat.startTime) / nowAnimatedFloat.totalTime);
value = nowAnimatedFloat.startValue + nowPercent * nowAnimatedFloat.differenceValue; //计算value
returnType = FlexibleReturnType.MiddleExecuting;
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;
return;
}
if (nowTime > finalEndTime) //如果当前时间大于最后一个动画的结束时间
{
nowAnimatedFloat = animations[animations.Count - 1];
//nowPercent = 1;
if (nowAnimatedFloat != null)
{
value = nowAnimatedFloat.endValue;
}
returnType = FlexibleReturnType.After;
return;
}
if (currentAnimationIndex >= 0) //如果当前时间点在动画之间
{
value = animations[currentAnimationIndex].endValue;
}
returnType = FlexibleReturnType.MiddleInterval;
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;
}
/// <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;
}
}
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;
}
}
}
}

View File

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

View File

@@ -0,0 +1,141 @@
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;
}
}
[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)
{
for (int i = 0; i < animations.Count; i++)
{
if (nowTime < animations[i].time)
{
if (i == 0)
{
return animations[i];
}
else
{
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;
}
}
}
}

View File

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

View File

@@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni
{
public enum FlexibleReturnType
{
None = -1, //没动画
Before = 0, //动画开始之前
MiddleExecuting = 1, //动画中间,正在运动
MiddleInterval = 2, //动画中间,在停顿空隙
After = 3 //动画结束后
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5f5c439efd47f46888026603e35d5a4e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
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 List<Color> baseColorOffset = new List<Color>();
public List<Color> emissionColorOffset = new List<Color>();
public List<float> emissionIntensityOffset = new List<float>();
public Color currentBaseColor;
public Color currentEmissionColor;
public float currentEmissionIntensity;
public bool baseColorDirtyMark;
public bool emissionColorDirtyMark;
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;
}
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;
}
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;
}
public override void SaveBM()
{
matchedBM = new ColorSubmodule_BM(attachedGameElement);
}
public override void SetUpInspector()
{
var container = inspector.GenerateContainer("Color");
var baseColor = inspector.GenerateBaseColorPicker(this, container, "Base Color", nameof(originalBaseColor));
if ((attachedGameElement as IHaveColorSubmodule).haveEmission)
{
var emissionColor = inspector.GenerateEmissionColorPicker(this, container, "Emission Color",
nameof(emissionEnabled), nameof(originalEmissionColor), nameof(originalEmissionIntensity));
}
}
}
public interface IHaveColorSubmodule
{
public ColorSubmodule colorSubmodule { get; set; }
public bool haveEmission { get; }
}
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);
attachedElement.submoduleList.Add((attachedElement as IHaveColorSubmodule).colorSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attached,
originalBaseColor, emissionEnabled, originalEmissionColor, originalEmissionIntensity);
attached.submoduleList.Add((attached as IHaveColorSubmodule).colorSubmodule);
}
}
}
}

View File

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

View File

@@ -0,0 +1,281 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Sirenix.Utilities;
using UnityEngine;
namespace Ichni.RhythmGame
{
/// <summary>
/// 包含效果的次级模块
/// </summary>
public partial class EffectSubmodule : SubmoduleBase
{
public Dictionary<string, List<EffectBase>> effectCollection;
public EffectSubmodule(GameElement attachedGameElement, EffectSubmodulePreset preset = EffectSubmodulePreset.Default)
: base(attachedGameElement)
{
effectCollection = new Dictionary<string, List<EffectBase>>();
if (preset == EffectSubmodulePreset.Default) //对于默认的效果次级模块只有Default效果集合
{
effectCollection.Add("Default", new List<EffectBase>());
}
else if (preset == EffectSubmodulePreset.Note) //对于Note的效果次级模块在Note的不同状态下有独立的效果集合
{
effectCollection.Add("Generate", new List<EffectBase>());
effectCollection.Add("GeneralJudge", new List<EffectBase>());
effectCollection.Add("Holding", new List<EffectBase>()); //仅用于Hold
effectCollection.Add("Perfect", new List<EffectBase>());
effectCollection.Add("Good", new List<EffectBase>());
effectCollection.Add("Bad", new List<EffectBase>());
effectCollection.Add("Miss", new List<EffectBase>());
}
}
public EffectSubmodule(GameElement attachedGameElement, Dictionary<string, List<EffectBase_BM>> effectList_BM) : base(attachedGameElement)
{
effectCollection = new Dictionary<string, List<EffectBase>>();
foreach (var effect in effectList_BM)
{
List<EffectBase> effectList = new List<EffectBase>();
foreach (var effectBM in effect.Value)
{
effectList.Add(effectBM.ConvertToGameType());
}
effectCollection.Add(effect.Key, effectList);
}
}
}
public partial class EffectSubmodule
{
public override void SaveBM()
{
matchedBM = new EffectSubmodule_BM(attachedGameElement);
}
public override void SetUpInspector()
{
foreach (var effect in effectCollection)
{
var container = inspector.GenerateContainer(effect.Key);
foreach (var effectBase in effect.Value)
{
effectBase.SetUpInspector();
}
}
}
}
public partial class EffectSubmodule
{
public enum EffectSubmodulePreset
{
Default,
Note,
}
}
public interface IHaveEffectSubmodule
{
public EffectSubmodule effectSubmodule { get; set; }
}
namespace Beatmap
{
public class EffectSubmodule_BM : Submodule_BM
{
public Dictionary<string, List<EffectBase_BM>> effectCollection;
public EffectSubmodule_BM()
{
}
public EffectSubmodule_BM(GameElement attachedElement) : base(attachedElement)
{
effectCollection = new Dictionary<string, List<EffectBase_BM>>();
IHaveEffectSubmodule element = attachedElement as IHaveEffectSubmodule;
foreach (var effect in element.effectSubmodule.effectCollection)
{
List<EffectBase_BM> effectList = new List<EffectBase_BM>();
foreach (var effectBase in effect.Value)
{
effectList.Add(effectBase.ConvertToBM());
}
effectCollection.Add(effect.Key, effectList);
}
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attachedElement, effectCollection);
attachedElement.submoduleList.Add((attachedElement as IHaveEffectSubmodule).effectSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attached, effectCollection);
attached.submoduleList.Add((attached as IHaveEffectSubmodule).effectSubmodule);
}
}
}
public abstract class EffectBase : IBaseElement
{
public enum EffectState
{
Before = -1,
Middle = 0,
After = 1,
Error = 100
}
public BaseElement_BM matchedBM { get; set; }
public Inspector inspector => EditorManager.instance.uiManager.inspector;
/// <summary>
/// 效果的持续时间如果为0则表示瞬间效果
/// </summary>
public float effectTime;
/// <summary>
/// 是否是瞬间效果
/// </summary>
public bool isInstantEffect => effectTime <= 0;
/// <summary>
/// 效果当前的状态
/// </summary>
public EffectState nowEffectState;
protected EffectBase()
{
this.effectTime = 0;
this.nowEffectState = EffectState.Before;
}
protected EffectBase(float effectTime)
{
this.effectTime = effectTime;
this.nowEffectState = EffectState.Before;
}
public void SaveBM()
{
throw new System.NotImplementedException();
}
public virtual void UpdateEffect(float triggerTime)
{
EffectState state = CheckEffectState(triggerTime);
if (state == EffectState.Before && nowEffectState != EffectState.Before)
{
nowEffectState = EffectState.Before;
Recover();
}
else if (state == EffectState.Middle)
{
nowEffectState = EffectState.Middle;
Execute();
}
else if (state == EffectState.After && nowEffectState != EffectState.After)
{
nowEffectState = EffectState.After;
Adjust();
}
}
protected virtual EffectState CheckEffectState(float triggerTime)
{
float songTime = EditorManager.instance.songInformation.songTime;
if (songTime < triggerTime)
{
return EffectState.Before;
}
if (songTime >= triggerTime &&
songTime <= triggerTime + effectTime)
{
return EffectState.Middle;
}
if (songTime > triggerTime + effectTime)
{
return EffectState.After;
}
return EffectState.Error;
}
/// <summary>
/// 在效果的持续时间内,触发这个方法
/// </summary>
public virtual void Execute()
{
}
/// <summary>
/// 如果是非瞬间效果,在效果完成后,触发这个方法;
/// 如果是瞬间效果则此方法即为Execute。原有的Execute方法不被调用。
/// </summary>
public virtual void Adjust()
{
}
/// <summary>
/// 如果时间轴回退到效果的触发时间之前,则触发这个方法
/// </summary>
public virtual void Recover()
{
}
/// <summary>
/// 转换为存档类
/// </summary>
/// <returns></returns>
public abstract EffectBase_BM ConvertToBM();
public void Refresh()
{
}
public abstract void SetUpInspector();
}
namespace Beatmap
{
public abstract class EffectBase_BM
{
public float effectTime;
public EffectBase_BM()
{
}
public EffectBase_BM(float effectTime)
{
this.effectTime = effectTime;
}
/// <summary>
/// 转换为游戏类
/// </summary>
/// <returns></returns>
public abstract EffectBase ConvertToGameType();
}
}
}

View File

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

View File

@@ -0,0 +1,76 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public abstract class SubmoduleBase : IBaseElement
{
public GameElement attachedGameElement;
public BaseElement_BM matchedBM { get; set; }
public Inspector inspector => EditorManager.instance.uiManager.inspector;
public SubmoduleBase(GameElement attachedGameElement)
{
this.attachedGameElement = attachedGameElement;
}
public virtual void InitialRefresh()
{
}
public abstract void SaveBM();
public virtual void OnDelete()
{
}
public virtual void Delete()
{
attachedGameElement.submoduleList.Remove(this);
}
public virtual void SetUpInspector()
{
}
public virtual void Refresh()
{
}
}
namespace Beatmap
{
public abstract class Submodule_BM : BaseElement_BM
{
[System.NonSerialized] public GameElement attachedElement; //存档类对应的游戏物体
public Guid attachedElementGuid;
public Submodule_BM()
{
}
public Submodule_BM(GameElement attachedElement)
{
this.attachedElement = attachedElement;
attachedElementGuid = attachedElement.elementGuid;
}
/// <summary>
/// 复制物体
/// </summary>
/// <param name="attached">(对于物体)父物体,(对于次级模块)或挂载物体</param>
public abstract void DuplicateBM(GameElement attached);
}
}
}

View File

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

View File

@@ -0,0 +1,146 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Ichni.RhythmGame.Beatmap;
using Unity.Mathematics;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class TimeDurationSubmodule : SubmoduleBase
{
public bool isOverridingDuration; //是否手动设置了时间区间,开启时,子物体的时间区间将被忽略,且在自动计算区间时跳过此模块
public float startTime, endTime; //起止时间
public TimeDurationSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
{
isOverridingDuration = false;
startTime = -32767;//TODO: 换为-delay
endTime = 32767;//TODO: 换为songLength
}
public TimeDurationSubmodule(GameElement attachedGameElement, bool isOverridingDuration, float startTime, float endTime) : base(attachedGameElement)
{
this.isOverridingDuration = isOverridingDuration;
this.startTime = startTime;
this.endTime = endTime;
}
public bool CheckTimeInDuration(float time, float offset = 0.2f)
{
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);
}
}
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 override void SaveBM()
{
matchedBM = new TimeDurationSubmodule_BM(attachedGameElement);
}
}
public partial class TimeDurationSubmodule
{
public override void SetUpInspector()
{
var container = inspector.GenerateContainer("Time Duration");
var overrideToggle = inspector.GenerateToggle(this, container, "Override Duration", nameof(isOverridingDuration));
var startTimeInputField = inspector.GenerateInputField(this, container, "Start Time", nameof(startTime));
var endTimeInputField = inspector.GenerateInputField(this, container, "End Time", nameof(endTime));
void SetInputFieldInteractable(bool interactable)
{
startTimeInputField.inputField.interactable = interactable;
endTimeInputField.inputField.interactable = interactable;
}
SetInputFieldInteractable(isOverridingDuration);
overrideToggle.AddListenerFunction(SetInputFieldInteractable);
}
}
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);
attachedElement.submoduleList.Add((attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attached, isOverridingDuration, startTime, endTime);
attached.submoduleList.Add((attached as IHaveTimeDurationSubmodule).timeDurationSubmodule);
}
}
}
}

View File

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

View File

@@ -0,0 +1,211 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
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 List<Vector3> positionOffset;
public List<Vector3> eulerAnglesOffset;
public List<Vector3> scaleOffset;
public Vector3 currentPosition;
public Vector3 currentEulerAngles;
public Vector3 currentScale;
public bool positionDirtyMark;
public bool eulerAnglesDirtyMark;
public bool scaleDirtyMark;
public bool eulerAnglesOffsetLock;
public TransformSubmodule(GameElement attachedGameElement) : base(attachedGameElement)
{
this.originalPosition = Vector3.zero;
this.originalEulerAngles = Vector3.zero;
this.originalScale = Vector3.one;
positionOffset = new List<Vector3>();
eulerAnglesOffset = new List<Vector3>();
scaleOffset = new List<Vector3>();
currentPosition = Vector3.zero;
currentEulerAngles = Vector3.zero;
currentScale = Vector3.one;
positionDirtyMark = false;
eulerAnglesDirtyMark = false;
scaleDirtyMark = false;
eulerAnglesOffsetLock = false;
// (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 = new List<Vector3>();
eulerAnglesOffset = new List<Vector3>();
scaleOffset = new List<Vector3>();
currentPosition = originalPosition;
currentEulerAngles = originalEulerAngles;
currentScale = originalScale;
positionDirtyMark = false;
eulerAnglesDirtyMark = false;
scaleDirtyMark = false;
eulerAnglesOffsetLock = false;
// (attachedGameElement as IHaveTransformSubmodule).SetTransformObserver();
}
public override void SaveBM()
{
matchedBM = new TransformSubmodule_BM(attachedGameElement);
}
public override void SetUpInspector()
{
var container = inspector.GenerateContainer("Transform");
var originalPosInputField =
inspector.GenerateVec3InputField(this, container, "Start Position", nameof(originalPosition));
var originalRotInputField =
inspector.GenerateVec3InputField(this, container, "Start Rotation", nameof(originalEulerAngles));
var originalScaleInputField =
inspector.GenerateVec3InputField(this, container, "Start Scale", nameof(originalScale));
var currentPosText =
inspector.GenerateText(this, container, "Current Position", nameof(currentPosition), true);
var currentRotText =
inspector.GenerateText(this, container, "Current Rotation", nameof(currentEulerAngles), true);
var currentScaleText =
inspector.GenerateText(this, container, "Current Scale", nameof(currentScale), true);
}
public override void Refresh()
{
positionDirtyMark = true;
eulerAnglesDirtyMark = true;
scaleDirtyMark = true;
}
}
public interface IHaveTransformSubmodule
{
TransformSubmodule transformSubmodule { get; set; }
/// <summary>
/// 设置物体Transform的监听顺序为Scale -> EulerAngles -> Position
/// 如果有一些特殊的物体例如CameraElementFolder需要自定义监听可以重写这个方法
/// </summary>
public void SetTransformObserver()
{
GameElement attachedGameElement = transformSubmodule.attachedGameElement;
Observable.EveryUpdate().Subscribe(_ =>
{
if (transformSubmodule == null)
{
return;
}
if (transformSubmodule.scaleDirtyMark)
{
Vector3 offset = Vector3.zero;
foreach (Vector3 scaleOffset in transformSubmodule.scaleOffset)
{
offset += scaleOffset;
}
transformSubmodule.currentScale = transformSubmodule.originalScale + offset;
attachedGameElement.transform.localScale = transformSubmodule.currentScale;
transformSubmodule.scaleDirtyMark = false;
}
if (transformSubmodule.eulerAnglesDirtyMark)
{
Vector3 offset = Vector3.zero;
foreach (Vector3 eulerOffset in transformSubmodule.eulerAnglesOffset)
{
offset += eulerOffset;
}
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + offset;
attachedGameElement.transform.localEulerAngles = transformSubmodule.currentEulerAngles;
transformSubmodule.eulerAnglesDirtyMark = false;
}
if (transformSubmodule.positionDirtyMark)
{
Vector3 offset = Vector3.zero;
foreach (Vector3 posOffset in transformSubmodule.positionOffset)
{
offset += posOffset;
}
transformSubmodule.currentPosition = transformSubmodule.originalPosition + offset;
attachedGameElement.transform.localPosition = transformSubmodule.currentPosition;
transformSubmodule.positionDirtyMark = false;
}
transformSubmodule.scaleOffset.Clear();
transformSubmodule.eulerAnglesOffset.Clear();
transformSubmodule.positionOffset.Clear();
}).AddTo(attachedGameElement);
}
}
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);
attachedElement.submoduleList.Add((attachedElement as IHaveTransformSubmodule).transformSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as IHaveTransformSubmodule).transformSubmodule = new TransformSubmodule(attached, originalPosition, originalEulerAngles, originalScale);
attached.submoduleList.Add((attached as IHaveTransformSubmodule).transformSubmodule);
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f915ace2766c54244aab864fb41d5a93
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class BeatmapContainer : IBaseElement
{
public List<GameElement> gameElementList;
public BaseElement_BM matchedBM { get; set; }
public BeatmapContainer()
{
gameElementList = new List<GameElement>();
}
public void SaveBM()
{
matchedBM = new BeatmapContainer_BM(gameElementList);
}
public void SetUpInspector()
{
throw new System.NotImplementedException();
}
public void Refresh()
{
throw new System.NotImplementedException();
}
}
namespace Beatmap
{
public class BeatmapContainer_BM : BaseElement_BM
{
public List<BaseElement_BM> elementList;
public BeatmapContainer_BM()
{
}
public BeatmapContainer_BM(List<GameElement> gameElementList)
{
elementList = new List<BaseElement_BM>();
gameElementList.ForEach(e =>
{
e.SaveBM();
e.submoduleList.RemoveAll(s=>s == null);
e.submoduleList.ForEach(s => s.SaveBM());
});
foreach (var gameElement in gameElementList)
{
elementList.Add(gameElement.matchedBM);
elementList.AddRange(gameElement.submoduleList.ConvertAll(submodule => submodule.matchedBM));
}
}
public override void ExecuteBM()
{
EditorManager.instance.beatmapContainer = new BeatmapContainer();
elementList.ForEach(element =>
{
if (element is GameElement_BM gameElement)
{
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
}
element.ExecuteBM();
});
}
}
}
}

View File

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

View File

@@ -0,0 +1,57 @@
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);
}
}
}
}

View File

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

View File

@@ -0,0 +1,90 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class ProjectInformation : IBaseElement
{
public string projectName;
public string creatorName;
public string editorVersion;
public string createTime;
public string lastSaveTime;
public List<string> selectedThemeBundleList;
public string projectPath;
public BaseElement_BM matchedBM { get; set; }
public string peojectInfoPath => projectPath + "/ProjectInfo.json";
public string songInfoPath => projectPath + "/SongInfo.json";
public string songPath => projectPath + EditorManager.instance.songInformation.songName + ".wav";
public string beatmapPath => projectPath + "/Beatmap.json";
public string CommandScriptsPath => projectPath + "/CommandScripts.json";
public ProjectInformation(string projectName, string creatorName, string editorVersion,
string createTime, string lastSaveTime, List<string> selectedThemeBundleList)
{
this.projectName = projectName;
this.creatorName = creatorName;
this.editorVersion = editorVersion;
this.createTime = createTime;
this.lastSaveTime = lastSaveTime;
this.selectedThemeBundleList = selectedThemeBundleList;
projectPath = Application.streamingAssetsPath + "/Projects/" + projectName;
}
public void SaveBM()
{
matchedBM = new ProjectInformation_BM(projectName, creatorName, editorVersion,
createTime, lastSaveTime, selectedThemeBundleList);
}
public void SetUpInspector()
{
throw new System.NotImplementedException();
}
public void Refresh()
{
throw new System.NotImplementedException();
}
}
namespace Beatmap
{
public class ProjectInformation_BM : BaseElement_BM
{
public string projectName;
public string creatorName;
public string editorVersion;
public string createTime;
public string lastSaveTime;
public List<string> selectedThemeBundleList;
public ProjectInformation_BM()
{
}
public ProjectInformation_BM(string projectName, string creatorName, string editorVersion,
string createTime, string lastSaveTime, List<string> selectedThemeBundleList)
{
this.projectName = projectName;
this.creatorName = creatorName;
this.editorVersion = editorVersion;
this.createTime = createTime;
this.lastSaveTime = lastSaveTime;
this.selectedThemeBundleList = selectedThemeBundleList;
}
public override void ExecuteBM()
{
EditorManager.instance.projectInformation = new ProjectInformation(projectName,
creatorName, editorVersion, createTime, lastSaveTime, selectedThemeBundleList);
}
}
}
}

View File

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

View File

@@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class SongInformation : IBaseElement
{
public AudioClip song; //曲目
public string songName;
public string songLocation; //曲名
public float bpm; //每分钟节拍数
public float delay; //设定音乐和谱面延迟Delay秒后开始在延迟中SongPosition为负数。
public float songTime;
public float songBeat => songTime / 60 * bpm;
public BaseElement_BM matchedBM { get; set; }
public SongInformation(string songName, float bpm, float delay)
{
this.songName = songName;
this.bpm = bpm;
this.delay = delay;
songLocation = EditorManager.instance.projectInformation.projectPath + "/" + songName + ".wav";
Debug.Log("Loading song from " + songLocation + " " + ES3.FileExists(songLocation));
song = ES3.LoadAudio(songLocation, AudioType.WAV);
}
public void SaveBM()
{
matchedBM = new SongInformation_BM(songName, bpm, delay);
}
public void SetUpInspector()
{
throw new System.NotImplementedException();
}
public void Refresh()
{
throw new System.NotImplementedException();
}
}
namespace Beatmap
{
public class SongInformation_BM : BaseElement_BM
{
public string songName;
public float bpm;
public float delay;
public SongInformation_BM()
{
}
public SongInformation_BM(string songName, float bpm, float delay)
{
this.songName = songName;
this.bpm = bpm;
this.delay = delay;
}
public override void ExecuteBM()
{
EditorManager.instance.songInformation = new SongInformation(songName, bpm, delay);
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 52e718a21001f425680a6ca7fd7558b3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6944ee6ee5d024c15a16862148361df3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
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 ElementFolder : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule
{
public List<Track> trackList;
public TransformSubmodule transformSubmodule { get; set; }
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
public static ElementFolder GenerateElement(string name, Guid id, List<string> tags, bool isFirstGenerated, GameElement parentElement)
{
ElementFolder elementFolder = Instantiate(EditorManager.instance.basePrefabs.elementFolder).GetComponent<ElementFolder>();
elementFolder.Initialize(name, id, tags, isFirstGenerated, parentElement);
return elementFolder;
}
protected override void SetDefaultSubmodules()
{
transformSubmodule = new TransformSubmodule(this);
timeDurationSubmodule = new TimeDurationSubmodule(this);
submoduleList.Add(transformSubmodule);
submoduleList.Add(timeDurationSubmodule);
}
}
public partial class ElementFolder
{
public override void SaveBM()
{
matchedBM = parentElement != null ?
new ElementFolder_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM) :
new ElementFolder_BM(elementName, elementGuid, tags, null);
}
}
namespace Beatmap
{
public class ElementFolder_BM : GameElement_BM
{
public ElementFolder_BM()
{
}
public ElementFolder_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement)
: base(elementName, elementGuid, tags, attachedElement)
{
}
public override void ExecuteBM()
{
matchedElement = ElementFolder.GenerateElement(elementName, elementGuid, tags,false, GetElement(attachedElementGuid));
}
public override GameElement DuplicateBM(GameElement parent)
{
return ElementFolder.GenerateElement(elementName, elementGuid, tags, false, parent);
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2f9d3b833668d4a309f2dc75315c18e8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BackgroundController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

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

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class EnvironmentObject : SubstantialObject
{
public bool isStatic;
public static SubstantialObject GenerateElement(string elementName, Guid id, List<string> tags,
bool isFirstGenerated, GameElement parentElement, string themeBundleName, string objectName, bool isStatic)
{
EnvironmentObject themeBundleObject =
ThemeBundleManager.instance.GetObject<EnvironmentObject>(themeBundleName, objectName);
EnvironmentObject environmentObject =
Instantiate(themeBundleObject, parentElement.transform).GetComponent<EnvironmentObject>();
environmentObject.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
environmentObject.isStatic = isStatic;
return environmentObject;
}
}
public partial class EnvironmentObject
{
public override void SaveBM()
{
matchedBM = new EnvironmentObject_BM(elementName, elementGuid, tags,
parentElement.matchedBM as GameElement_BM, themeBundleName, objectName, isStatic);
}
}
namespace Beatmap
{
public class EnvironmentObject_BM : SubstantialObject_BM
{
public bool isStatic;
public EnvironmentObject_BM()
{
}
public EnvironmentObject_BM(string elementName, Guid elementGuid, List<string> tags,
GameElement_BM attachedElement, string themeBundleName, string objectName, bool isStatic)
: base(elementName, elementGuid, tags, attachedElement, themeBundleName, objectName)
{
this.isStatic = isStatic;
}
public override void ExecuteBM()
{
matchedElement = EnvironmentObject.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid), themeBundleName, objectName, isStatic);
}
public override GameElement DuplicateBM(GameElement parent)
{
return EnvironmentObject.GenerateElement(elementName, elementGuid, tags, false,
parent, themeBundleName, objectName, isStatic);
}
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 56a4c0ac4ed204fcfb16a22f625230cd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;
namespace Ichni.RhythmGame
{
public partial class GameCamera : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule
{
public new Camera camera;
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; }
public static GameCamera GenerateElement(string elementName, Guid id,
List<string> tags, bool isFirstGenerated, GameElement parentElement,
CameraViewType cameraViewType, float perspectiveAngle, float orthographicSize)
{
GameCamera gameCamera =
Instantiate(EditorManager.instance.basePrefabs.gameCamera).GetComponent<GameCamera>();
gameCamera.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
gameCamera.parentElement = parentElement;
gameCamera.cameraViewType = cameraViewType;
gameCamera.camera.orthographic = cameraViewType == CameraViewType.Orthographic;
gameCamera.perspectiveAngle = perspectiveAngle;
gameCamera.orthographicSize = orthographicSize;
gameCamera.cameraTransform = gameCamera.transform;
return gameCamera;
}
protected override void SetDefaultSubmodules()
{
transformSubmodule = new TransformSubmodule(this);
submoduleList.Add(transformSubmodule);
}
}
public partial class GameCamera
{
public enum CameraViewType
{
None = -1,
Perspective = 0,
Orthographic = 1
}
}
public partial class GameCamera
{
public void SetTransformObserver()
{
Observable.EveryUpdate().Subscribe(_ =>
{
if (transformSubmodule.eulerAnglesOffsetLock)
{
rotationPoint.eulerAngles = transformSubmodule.currentEulerAngles;
}
else if (transformSubmodule.eulerAnglesDirtyMark)
{
Vector3 offset = Vector3.zero;
foreach (Vector3 eulerOffset in transformSubmodule.eulerAnglesOffset)
{
offset += eulerOffset;
}
transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + offset;
rotationPoint.eulerAngles = transformSubmodule.currentEulerAngles;
transformSubmodule.eulerAnglesDirtyMark = false;
}
if (transformSubmodule.positionDirtyMark)
{
Vector3 offset = Vector3.zero;
foreach (Vector3 posOffset in transformSubmodule.positionOffset)
{
offset += posOffset;
}
transformSubmodule.currentPosition = transformSubmodule.originalPosition + offset;
positionPoint.localPosition = transformSubmodule.currentPosition;
transformSubmodule.positionDirtyMark = false;
}
}).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()
{
GameCamera.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid), cameraViewType, perspectiveAngle, orthographicSize);
}
public override GameElement DuplicateBM(GameElement parent)
{
return GameCamera.GenerateElement(elementName, elementGuid, tags, false,
parent, cameraViewType, perspectiveAngle, orthographicSize);
}
}
}
}

View File

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

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Dreamteck.Splines;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Sirenix.OdinInspector;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using Inspector = Ichni.Editor.Inspector;
namespace Ichni.RhythmGame
{
public abstract partial class GameElement : SerializedMonoBehaviour, IBaseElement
{
//物体名
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 Inspector inspector => EditorManager.instance.uiManager.inspector;
/// <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);
EditorManager.instance.uiManager.hierarchy.GenerateTab(this, parentElement);
//GameManager.beatMapContainer.beatMapElementList.Add(this);
//serialNumber = totalSerialNumber++;
//SetTransformObserver();
}
/// <summary>
/// 设置次级模块
/// </summary>
protected abstract void SetDefaultSubmodules();
/// <summary>
/// 在所有物体生成完毕后,执行的初始化方法
/// </summary>
public virtual void AfterInitialize()
{
}
/// <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 abstract partial class GameElement //存档,删除,复制,粘贴
{
public virtual void Refresh()
{
}
/// <summary>
/// 用于生成存档
/// </summary>
public virtual void SaveBM()
{
throw new NotImplementedException();
}
/// <summary>
/// 当物体被删除时执行的方法
/// </summary>
public virtual void OnDelete()
{
throw new NotImplementedException();
}
/// <summary>
/// 删除物体,包括所有子物体
/// </summary>
public virtual void Delete()
{
if (this.childElementList != null)
{
for (int i = 0; i < childElementList.Count; i++)
{
childElementList[i].Delete(); //删除子GameElement、
}
}
OnDelete();
#if UNITY_EDITOR
Debug.Log("Delete " + elementName + "(" + elementGuid + ")");
#endif
EditorManager.instance.beatmapContainer.gameElementList.Remove(this); //从保存列表中剔除
this.parentElement.childElementList.Remove(this);
Destroy(gameObject); //销毁
}
}
public abstract partial class GameElement
{
public virtual void SetUpInspector() //被点击时设置第一层Inspector
{
var container = inspector.GenerateContainer("Element Info");
var nameInputField = inspector.GenerateInputField(this, container, GetType().Name + "'s Name", nameof(elementName));
var guidText = inspector.GenerateText(this, container, "Element GUID", nameof(elementGuid), true);
var tagsListButton = inspector.GenerateButton(this, container, "Tags List", () =>
{
inspector.GenerateCompositeParameterWindow(this, "Tags List", nameof(tags)).SetAsStringList();
});
foreach (var submodule in submoduleList)
{
submodule.SetUpInspector();
}
}
}
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 Guid attachedElementGuid;
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);
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22d9d055a57b4494a85bf79a857d96ed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using MoreMountains.Feedbacks;
using MoreMountains.FeedbacksForThirdParty;
using Sirenix.OdinInspector;
namespace Ichni.RhythmGame
{
public class BloomShake : EffectBase
{
public float bloomTime;
public float bloomPeak;
[Button("Test Bloom Shake")]
public override void Adjust()
{
MMF_Player effect = LeanPool.Spawn(EditorManager.instance.basePrefabs.bloomShake).GetComponent<MMF_Player>();
effect.GetFeedbackOfType<MMF_Bloom_URP>().ShakeDuration = bloomTime;
effect.GetFeedbackOfType<MMF_Bloom_URP>().RemapIntensityOne = bloomPeak;
effect.PlayFeedbacks();
LeanPool.Despawn(effect.gameObject, bloomTime);
}
public override EffectBase_BM ConvertToBM()
{
throw new NotImplementedException();
}
public override void SetUpInspector()
{
throw new NotImplementedException();
}
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Ichni.RhythmGame
{
public partial class TimeEffectsCollection : GameElement, IHaveEffectSubmodule
{
public EffectSubmodule effectSubmodule { get; set; }
public float time;
public static TimeEffectsCollection CreateTimeEffectsCollection(float time)
{
TimeEffectsCollection timeEffectsCollection = Instantiate(EditorManager.instance.basePrefabs.emptyObject)
.AddComponent<TimeEffectsCollection>();
timeEffectsCollection.time = time;
return timeEffectsCollection;
}
protected override void SetDefaultSubmodules()
{
effectSubmodule = new EffectSubmodule(this);
}
private void Update()
{
effectSubmodule.effectCollection["Default"].ForEach(effect => effect.UpdateEffect(time));
}
}
public partial class TimeEffectsCollection
{
public override void SaveBM()
{
}
public override void SetUpInspector()
{
var container = inspector.GenerateContainer("Time Effects Collection");
var timeInputField = inspector.GenerateInputField(this, container, "Time", nameof(time));
}
}
namespace Beatmap
{
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62e1a33dede934d3fb2c3282b6641d59
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: acc133c3d8ab345e1ac8d703e4ce2f18
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class FullScreenBalancedJudgeUnit : NoteJudgeUnit
{
}
}

View File

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

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class FullScreenNearTimeJudgeUnit : NoteJudgeUnit
{
}
}

View File

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

View File

@@ -0,0 +1,59 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class NoteJudgeSubmodule : SubmoduleBase
{
public List<NoteJudgeUnit> judgeUnitList;
public NoteJudgeSubmodule(NoteBase attachedGameElement) : base(attachedGameElement)
{
}
public override void SaveBM()
{
matchedBM = new NoteJudgeSubmodule_BM(attachedGameElement);
}
}
namespace Beatmap
{
public class NoteJudgeSubmodule_BM : Submodule_BM
{
public List<NoteJudgeUnit> judgeUnitList;
public NoteJudgeSubmodule_BM()
{
}
public NoteJudgeSubmodule_BM(GameElement attachedElement) : base(attachedElement)
{
judgeUnitList = new List<NoteJudgeUnit>();
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attachedElement as NoteBase);
attachedElement.submoduleList.Add((attachedElement as NoteBase).noteJudgeSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attached as NoteBase);
attached.submoduleList.Add((attached as NoteBase).noteJudgeSubmodule);
}
}
}
public class NoteJudgeUnit
{
}
}

View File

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

View File

@@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class TouchAreaJudgeUnit : NoteJudgeUnit
{
}
}

View File

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

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class TriggerConnectJudgeUnit : NoteJudgeUnit
{
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 084c7ad2bd4754df29e585542aaa5b37
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
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, Guid attachedNoteID) : base(effectTime, attachedNoteID)
{
}
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
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 Guid attachedNoteID;
public NoteEffectBase_BM()
{
}
public NoteEffectBase_BM(float effectTime, Guid attachedNoteID) : base(effectTime)
{
this.attachedNoteID = attachedNoteID;
}
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
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, Guid attachedNoteID) : base(effectTime, attachedNoteID)
{
}
}
}
}

View File

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

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.ThemeBundles.Basic;
using UnityEngine;
namespace Ichni.RhythmGame
{
public abstract class NoteGenerateEffect : NoteEffectBase
{
public float generateTime;
protected override EffectState CheckEffectState(float triggerTime)
{
float songTime = EditorManager.instance.songInformation.songTime;
if (songTime < triggerTime - generateTime)
{
return EffectState.Before;
}
if (songTime >= triggerTime - generateTime &&
songTime <= triggerTime - generateTime + effectTime)
{
return EffectState.Middle;
}
if (songTime > triggerTime - generateTime + effectTime)
{
return EffectState.After;
}
return EffectState.Error;
}
}
namespace Beatmap
{
public abstract class NoteGenerateEffect_BM : NoteEffectBase_BM
{
public float generateTime;
public NoteGenerateEffect_BM()
{
}
public NoteGenerateEffect_BM(float effectTime, float generateTime, Guid attachedNoteID) : base(effectTime, attachedNoteID)
{
this.generateTime = generateTime;
}
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
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, Guid attachedNoteID) : base(effectTime, attachedNoteID)
{
}
}
}
}

View File

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

View File

@@ -0,0 +1,29 @@
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, Guid attachedNoteID) : base(effectTime, attachedNoteID)
{
}
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More