效果模块,以及代码位置整理
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8671bc8338e5d4e93814ee040ac71b87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67578ca8780234f6d9108a4ea88a5c82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07275dc5f06cf4169bd386786acff3a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d84c0a008a0e7478b91b1cbd5f0f5f74
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
/// 如果有一些特殊的物体(例如Camera,ElementFolder),需要自定义监听,可以重写这个方法
|
||||
/// </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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e65eb5e3a5ce94b709db07ff3ea3d1e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user