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

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

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: