基础内容11 - SAVE LOAD EXPORT

This commit is contained in:
SoulliesOfficial
2025-02-08 23:09:50 -05:00
parent 7ab738cb68
commit e3a8450a27
61 changed files with 1229 additions and 237 deletions

View File

@@ -100,7 +100,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
BaseColorChange.GenerateElement(elementName, elementGuid, tags, false,
matchedElement = BaseColorChange.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid), colorR.ConvertToGameType(),
colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorA.ConvertToGameType());
}

View File

@@ -101,7 +101,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
EmissionColorChange.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
matchedElement = EmissionColorChange.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
colorR.ConvertToGameType(), colorG.ConvertToGameType(), colorB.ConvertToGameType(), colorI.ConvertToGameType());
}

View File

@@ -76,7 +76,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
TrackTotalTimeChange.GenerateElement(elementName, elementGuid, tags, false,
matchedElement = TrackTotalTimeChange.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid) as Track, totalTime.ConvertToGameType());
}

View File

@@ -46,9 +46,18 @@ namespace Ichni.RhythmGame
positionY.UpdateFlexibleFloat(songTime);
positionZ.UpdateFlexibleFloat(songTime);
if (positionX.returnType is FlexibleReturnType.MiddleExecuting ||
positionY.returnType is FlexibleReturnType.MiddleExecuting ||
positionZ.returnType is FlexibleReturnType.MiddleExecuting)
if (positionX.returnType is FlexibleReturnType.After or FlexibleReturnType.Before
or FlexibleReturnType.MiddleInterval or FlexibleReturnType.None &&
positionY.returnType is FlexibleReturnType.After or FlexibleReturnType.Before
or FlexibleReturnType.MiddleInterval or FlexibleReturnType.None &&
positionZ.returnType is FlexibleReturnType.After or FlexibleReturnType.Before
or FlexibleReturnType.MiddleInterval or FlexibleReturnType.None)
{
// Out of range, do nothing
}
else 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);
@@ -59,18 +68,6 @@ namespace Ichni.RhythmGame
{
animationReturnType = FlexibleReturnType.MiddleInterval;
}
//本体使用,用于判断动画是否结束
// else if (positionX.returnType is FlexibleReturnType.After or FlexibleReturnType.None &&
// positionY.returnType is FlexibleReturnType.After or FlexibleReturnType.None &&
// positionZ.returnType is FlexibleReturnType.After or FlexibleReturnType.None)
// {
// animationReturnType = FlexibleReturnType.After;
// float3 currentPosition = new float3(positionX.value, positionY.value, positionZ.value);
// targetTransformSubmodule.positionOffset.Add(currentPosition);
// targetTransformSubmodule.positionDirtyMark = true;
// Destroy(gameObject);
// }
}
}
@@ -105,7 +102,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
Displacement.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
matchedElement = Displacement.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
positionX.ConvertToGameType(), positionY.ConvertToGameType(), positionZ.ConvertToGameType());
}

View File

@@ -93,7 +93,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
Scale.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
matchedElement = Scale.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
scaleX.ConvertToGameType(), scaleY.ConvertToGameType(), scaleZ.ConvertToGameType());
}

View File

@@ -94,7 +94,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
Swirl.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
matchedElement = Swirl.GenerateElement(elementName, elementGuid, tags, false, GetElement(attachedElementGuid),
eulerAngleX.ConvertToGameType(), eulerAngleY.ConvertToGameType(), eulerAngleZ.ConvertToGameType());
}

View File

@@ -21,12 +21,18 @@ namespace Ichni.RhythmGame
/// <summary>
/// 当物体被删除时执行的方法
/// </summary>
public void OnDelete();
public void OnDelete()
{
throw new NotImplementedException();
}
/// <summary>
/// 删除物体,包括所有子物体
/// </summary>
public void Delete();
public void Delete()
{
throw new NotImplementedException();
}
}
// public virtual void SetTimeDuration()
@@ -41,70 +47,16 @@ namespace Ichni.RhythmGame
// childElementList.Select(x => x.timeDurationSubmodule).ToList());
// }
//
// /// <summary>
// /// 设置物体Transform的监听顺序为Scale -> EulerAngles -> Position
// /// 如果有一些特殊的物体例如CameraElementFolder需要自定义监听可以重写这个方法
// /// </summary>
// public virtual void SetTransformObserver()
// {
// 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;
// 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;
// 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;
// transform.localPosition = transformSubmodule.currentPosition;
// transformSubmodule.positionDirtyMark = false;
// }
//
// transformSubmodule.scaleOffset.Clear();
// transformSubmodule.eulerAnglesOffset.Clear();
// transformSubmodule.positionOffset.Clear();
// }).AddTo(gameObject);
// }
namespace Beatmap
{
public abstract class BaseElement_BM
{
/// <summary>
/// 从存档类中生成游戏物体
/// </summary>
public abstract void ExecuteBM();
}
}
}

View File

@@ -106,14 +106,16 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attachedElement, originalBaseColor, emissionEnabled,
originalEmissionColor, originalEmissionIntensity);
(attachedElement as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attachedElement,
originalBaseColor, emissionEnabled, originalEmissionColor, originalEmissionIntensity);
attachedElement.submoduleList.Add((attachedElement as IHaveColorSubmodule).colorSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attachedElement as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attached, originalBaseColor, emissionEnabled,
originalEmissionColor, originalEmissionIntensity);
(attached as IHaveColorSubmodule).colorSubmodule = new ColorSubmodule(attached,
originalBaseColor, emissionEnabled, originalEmissionColor, originalEmissionIntensity);
attached.submoduleList.Add((attached as IHaveColorSubmodule).colorSubmodule);
}
}
}

View File

@@ -94,12 +94,14 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attachedElement);
(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);
(attached as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attached, effectCollection);
attached.submoduleList.Add((attached as IHaveEffectSubmodule).effectSubmodule);
}
}
}

View File

@@ -52,11 +52,6 @@ namespace Ichni.RhythmGame
this.attachedElement = attachedElement;
attachedElementGuid = attachedElement.elementGuid;
}
/// <summary>
/// 从存档类中生成游戏物体
/// </summary>
public abstract void ExecuteBM();
/// <summary>
/// 复制物体

View File

@@ -110,14 +110,14 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule =
new TimeDurationSubmodule(attachedElement, isOverridingDuration, startTime, endTime);
(attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attachedElement, isOverridingDuration, startTime, endTime);
attachedElement.submoduleList.Add((attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attachedElement as IHaveTimeDurationSubmodule).timeDurationSubmodule =
new TimeDurationSubmodule(attached, isOverridingDuration, startTime, endTime);
(attached as IHaveTimeDurationSubmodule).timeDurationSubmodule = new TimeDurationSubmodule(attached, isOverridingDuration, startTime, endTime);
attached.submoduleList.Add((attached as IHaveTimeDurationSubmodule).timeDurationSubmodule);
}
}
}

View File

@@ -88,6 +88,10 @@ namespace Ichni.RhythmGame
{
TransformSubmodule transformSubmodule { get; set; }
/// <summary>
/// 设置物体Transform的监听顺序为Scale -> EulerAngles -> Position
/// 如果有一些特殊的物体例如CameraElementFolder需要自定义监听可以重写这个方法
/// </summary>
public void SetTransformObserver()
{
GameElement attachedGameElement = transformSubmodule.attachedGameElement;
@@ -169,14 +173,14 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as IHaveTransformSubmodule).transformSubmodule =
new TransformSubmodule(attachedElement, originalPosition, originalEulerAngles, originalScale);
(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 as IHaveTransformSubmodule).transformSubmodule = new TransformSubmodule(attached, originalPosition, originalEulerAngles, originalScale);
attached.submoduleList.Add((attached as IHaveTransformSubmodule).transformSubmodule);
}
}
}

View File

@@ -14,73 +14,84 @@ namespace Ichni
public static EditorManager instance;
public SongModule songModule;
public ProjectManager projectManager;
public EditorSettings editorSettings;
public ProjectInformation projectInformation;
public SongInformation songInformation;
public BeatmapContainer beatmapContainer;
public CommandScripts commandScripts;
public NoteBase.NoteJudgeType currentJudgeType;
public BasePrefabsCollection basePrefabs;
public List<GameElement> elementList = new List<GameElement>();
public List<BaseElement_BM> elementList_BM = new List<BaseElement_BM>();
public List<Submodule_BM> submoduleList_BM = new List<Submodule_BM>();
private void Awake()
{
instance = this;
projectManager = new ProjectManager();
}
private void Start()
{
//CreateNew();
projectManager.loadManager.Load("TestProject");
AudioSource.PlayClipAtPoint(songInformation.song, Vector3.zero);
//currentJudgeType = NoteBase.NoteJudgeType.Perfect;
var f0 = ElementFolder.GenerateElement("Folder", Guid.NewGuid(), new List<string>(), true, null);
var dis0 = Displacement.GenerateElement("Displacement-0",Guid.NewGuid(), new List<string>(),true, f0,
new FlexibleFloat(),
new FlexibleFloat(new List<AnimatedFloat>(){new (0,2,0,10, AnimationCurveType.Linear)}),
new FlexibleFloat());
var t0 = Track.GenerateElement("Track", Guid.NewGuid(), new List<string>(), true, f0);
t0.trackPathSubmodule = new TrackPathSubmodule(t0, Track.TrackSpaceType.Linear,
Track.TrackSamplingType.TimeDistributed, false);
t0.trackTimeSubmodule = new TrackTimeSubmoduleMovable(t0, 0, 2, 1, AnimationCurveType.OutQuad);
var pp0 = TrackPercentPoint.GenerateElement("TrackPercentPoint-0", Guid.NewGuid(), new List<string>(), true, t0,
new FlexibleFloat(new List<AnimatedFloat>() { new(0, 2, 0, 1, AnimationCurveType.OutQuad) }));
var tr0 = Trail.GenerateElement("Trail-0", Guid.NewGuid(), new List<string>(), true, pp0, 5);
// t0.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(t0);
var p0 = PathNode.GenerateElement("PathNode-0", Guid.NewGuid(), new List<string>(), true, t0);
p0.transformSubmodule = new TransformSubmodule(p0, new Vector3(-5, 5, 10), Vector3.forward, Vector3.one);
p0.colorSubmodule = new ColorSubmodule(p0, Color.white);
var p1 = PathNode.GenerateElement("PathNode-1", Guid.NewGuid(), new List<string>(), true, t0);
p1.transformSubmodule = new TransformSubmodule(p1, new Vector3(5, -5, 10), Vector3.forward, Vector3.one);
p1.colorSubmodule = new ColorSubmodule(p1, Color.red);
var n0 = Tap.GenerateElement("Note-0", Guid.NewGuid(), new List<string>(), true, t0, 1f);
var n0v = BasicNoteVisual.GenerateElement("Note-0-V", Guid.NewGuid(), new List<string>(), true, n0,
"basic", "BasicNoteTap3D");
elementList.ForEach(e =>
beatmapContainer.gameElementList.ForEach(gameElement =>
{
e.AfterInitialize();
e.Refresh();
if (gameElement is IHaveTransformSubmodule transformedElement)
{
transformedElement.SetTransformObserver();
}
gameElement.AfterInitialize();
gameElement.Refresh();
});
elementList.ForEach(e =>
{
e.SaveBM();
e.submoduleList.RemoveAll(s=>s == null);
e.submoduleList.ForEach(s => s.SaveBM());
});
//Save
elementList.ForEach(x => elementList_BM.Add(x.matchedBM));
elementList.ForEach(x => submoduleList_BM.AddRange(x.submoduleList.ConvertAll(s => s.matchedBM as Submodule_BM)));
ES3.Save<List<Submodule_BM>>("submoduleList", submoduleList_BM);
ES3.Save<List<BaseElement_BM>>("elementList", elementList_BM);
}
private void Update()
{
songModule.songTime += Time.deltaTime;
}
private void CreateNew()
{
projectManager.GenerateProject("TestProject");
var f0 = ElementFolder.GenerateElement("Folder", Guid.NewGuid(), new List<string>(), true, null);
var dis0 = Displacement.GenerateElement("Displacement-0",Guid.NewGuid(), new List<string>(),true, f0,
new FlexibleFloat(),
new FlexibleFloat(new List<AnimatedFloat>(){new (0,2,0,10, AnimationCurveType.Linear)}),
new FlexibleFloat());
var t0 = Track.GenerateElement("Track", Guid.NewGuid(), new List<string>(), true, f0);
t0.trackPathSubmodule = new TrackPathSubmodule(t0, Track.TrackSpaceType.Linear, Track.TrackSamplingType.TimeDistributed, false);
t0.submoduleList.Add(t0.trackPathSubmodule);
t0.trackTimeSubmodule = new TrackTimeSubmoduleMovable(t0, 0, 2, 1, AnimationCurveType.OutQuad);
t0.submoduleList.Add(t0.trackTimeSubmodule);
var pp0 = TrackPercentPoint.GenerateElement("TrackPercentPoint-0", Guid.NewGuid(), new List<string>(), true, t0,
new FlexibleFloat(new List<AnimatedFloat>() { new(0, 2, 0, 1, AnimationCurveType.OutQuad) }));
var tr0 = Trail.GenerateElement("Trail-0", Guid.NewGuid(), new List<string>(), true, pp0, 5);
// t0.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(t0);
var p0 = PathNode.GenerateElement("PathNode-0", Guid.NewGuid(), new List<string>(), true, t0);
p0.transformSubmodule = new TransformSubmodule(p0, new Vector3(-5, 5, 10), Vector3.zero, Vector3.one);
p0.colorSubmodule = new ColorSubmodule(p0, Color.white);
var p1 = PathNode.GenerateElement("PathNode-1", Guid.NewGuid(), new List<string>(), true, t0);
p1.transformSubmodule = new TransformSubmodule(p1, new Vector3(5, -5, 10), Vector3.zero, Vector3.one);
p1.colorSubmodule = new ColorSubmodule(p1, Color.red);
var n0 = Tap.GenerateElement("Note-0", Guid.NewGuid(), new List<string>(), true, t0, 1f);
var n0v = BasicNoteVisual.GenerateElement("Note-0-V", Guid.NewGuid(), new List<string>(), true, n0,
"basic", "BasicNoteTap3D");
beatmapContainer.gameElementList.ForEach(e =>
{
e.AfterInitialize();
e.Refresh();
});
projectManager.saveManager.Save();
projectManager.exportManager.Export();
}
}
public class SongModule

View File

@@ -0,0 +1,173 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni
{
public class ProjectManager
{
public static readonly ES3Settings SaveSettings = new ES3Settings
{
compressionType = ES3.CompressionType.None,
encryptionType = ES3.EncryptionType.None,
format = ES3.Format.JSON,
};
public static readonly ES3Settings ExportSettings = new ES3Settings
{
compressionType = ES3.CompressionType.Gzip,
encryptionType = ES3.EncryptionType.AES,
encryptionPassword = "Soullies515",
format = ES3.Format.JSON,
};
public SaveManager saveManager;
public LoadManager loadManager;
public ExportManager exportManager;
public ProjectManager()
{
saveManager = new SaveManager();
loadManager = new LoadManager();
exportManager = new ExportManager();
}
public void GenerateProject(string projectName)
{
EditorManager.instance.projectInformation = new ProjectInformation(projectName, "Soullies",
"2.0", "2025-02-08", "2025-02-08", new List<string>());
EditorManager.instance.songInformation = new SongInformation("TestSong", 120, 0);
EditorManager.instance.beatmapContainer = new BeatmapContainer();
EditorManager.instance.commandScripts = new CommandScripts(new List<string>());
//Create project folder
if (!System.IO.Directory.Exists(EditorManager.instance.projectInformation.projectPath))
{
System.IO.Directory.CreateDirectory(EditorManager.instance.projectInformation.projectPath);
}
}
}
public class ExportManager
{
public void Export()
{
string exportPath = Application.streamingAssetsPath + "/Export/" +
EditorManager.instance.projectInformation.projectName;
string projectInfoPath = exportPath + "/ProjectInfo.bytes";
string songInfoPath = exportPath + "/SongInfo.bytes";
string beatmapPath = exportPath + "/BeatMap.bytes";
string commandScriptsPath = exportPath + "/CommandScripts.bytes";
ExportProjectInfo(projectInfoPath);
ExportSongInfo(songInfoPath);
ExportBeatMap(beatmapPath);
ExportCommandScripts(commandScriptsPath);
}
private void ExportProjectInfo(string exportPath)
{
EditorManager.instance.projectInformation.SaveBM();
ES3.Save("ProjectInformation", EditorManager.instance.projectInformation.matchedBM as ProjectInformation_BM,
exportPath, ProjectManager.ExportSettings);
}
private void ExportSongInfo(string exportPath)
{
EditorManager.instance.songInformation.SaveBM();
ES3.Save("SongInformation", EditorManager.instance.songInformation.matchedBM as SongInformation_BM,
exportPath, ProjectManager.ExportSettings);
}
private void ExportBeatMap(string exportPath)
{
EditorManager.instance.beatmapContainer.SaveBM();
ES3.Save("BeatMap", EditorManager.instance.beatmapContainer.matchedBM as BeatmapContainer_BM,
exportPath, ProjectManager.ExportSettings);
}
private void ExportCommandScripts(string exportPath)
{
EditorManager.instance.commandScripts.SaveBM();
ES3.Save("CommandScripts", EditorManager.instance.commandScripts.matchedBM as CommandScripts_BM,
exportPath, ProjectManager.ExportSettings);
}
}
public class SaveManager
{
public void Save()
{
SaveProjectInfo();
SaveSongInfo();
SaveBeatMap();
SaveCommandScripts();
}
private void SaveProjectInfo()
{
EditorManager.instance.projectInformation.SaveBM();
ES3.Save("ProjectInformation", EditorManager.instance.projectInformation.matchedBM as ProjectInformation_BM,
EditorManager.instance.projectInformation.peojectInfoPath, ProjectManager.SaveSettings);
}
private void SaveSongInfo()
{
EditorManager.instance.songInformation.SaveBM();
ES3.Save("SongInformation", EditorManager.instance.songInformation.matchedBM as SongInformation_BM,
EditorManager.instance.projectInformation.songInfoPath, ProjectManager.SaveSettings);
}
private void SaveBeatMap()
{
EditorManager.instance.beatmapContainer.SaveBM();
ES3.Save("BeatMap", EditorManager.instance.beatmapContainer.matchedBM as BeatmapContainer_BM,
EditorManager.instance.projectInformation.beatmapPath, ProjectManager.SaveSettings);
}
private void SaveCommandScripts()
{
EditorManager.instance.commandScripts.SaveBM();
ES3.Save("CommandScripts", EditorManager.instance.commandScripts.matchedBM as CommandScripts_BM,
EditorManager.instance.projectInformation.CommandScriptsPath, ProjectManager.SaveSettings);
}
}
public class LoadManager
{
public void Load(string projectName)
{
LoadProjectInfo(projectName);
LoadSongInfo();
LoadBeatMap();
LoadCommandScripts();
}
private void LoadProjectInfo(string projectName)
{
string projectInfoPath = Application.streamingAssetsPath + "/Projects/" + projectName + "/ProjectInfo.json";
ES3.Load<ProjectInformation_BM>("ProjectInformation", projectInfoPath, ProjectManager.SaveSettings).ExecuteBM();
}
private void LoadSongInfo()
{
ES3.Load<SongInformation_BM>("SongInformation", EditorManager.instance.projectInformation.songInfoPath,
ProjectManager.SaveSettings).ExecuteBM();
}
private void LoadBeatMap()
{
ES3.Load<BeatmapContainer_BM>("BeatMap", EditorManager.instance.projectInformation.beatmapPath,
ProjectManager.SaveSettings).ExecuteBM();
}
private void LoadCommandScripts()
{
ES3.Load<CommandScripts_BM>("CommandScripts", EditorManager.instance.projectInformation.CommandScriptsPath,
ProjectManager.SaveSettings).ExecuteBM();
}
}
}

View File

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

View File

@@ -1,18 +1,69 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
public class BeatmapContainer : MonoBehaviour
namespace Ichni.RhythmGame
{
// Start is called before the first frame update
void Start()
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);
}
}
// Update is called once per frame
void Update()
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

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

View File

@@ -0,0 +1,47 @@
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);
}
}
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,13 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni
{
public class EditorSettings
{
public int autoSaveInterval = 300;
}
}

View File

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

View File

@@ -1,18 +1,80 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
public class ProjectInformation : MonoBehaviour
namespace Ichni.RhythmGame
{
// Start is called before the first frame update
void Start()
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);
}
}
// Update is called once per frame
void Update()
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

@@ -1,18 +1,60 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
public class SongInformation : MonoBehaviour
namespace Ichni.RhythmGame
{
// Start is called before the first frame update
void Start()
public class SongInformation : IBaseElement
{
public AudioClip song; //曲目
public string songName;
public string songLocation; //曲名
public float bpm; //每分钟节拍数
public float delay; //设定音乐和谱面延迟Delay秒后开始在延迟中SongPosition为负数。
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);
}
}
// Update is called once per frame
void Update()
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

@@ -39,7 +39,7 @@ namespace Ichni.RhythmGame
this.elementName = name;
this.elementGuid = elementGuid;
this.tags = tags;
EditorManager.instance.elementList.Add(this);
EditorManager.instance.beatmapContainer.gameElementList.Add(this);
submoduleList = new List<SubmoduleBase>();
if (isFirstGenerated)
{
@@ -123,7 +123,7 @@ namespace Ichni.RhythmGame
#if UNITY_EDITOR
Debug.Log("Delete " + elementName + "(" + elementGuid + ")");
#endif
EditorManager.instance.elementList.Remove(this); //从保存列表中剔除
EditorManager.instance.beatmapContainer.gameElementList.Remove(this); //从保存列表中剔除
this.parentElement.childElementList.Remove(this);
Destroy(gameObject); //销毁
}
@@ -167,20 +167,19 @@ namespace Ichni.RhythmGame
{
return element_BM;
}
Debug.LogAssertion("Element not found or do not have id");
return null;
}
public static GameElement GetElement(Guid id)
{
return GetElementBM(id)?.matchedElement;
if(identifier.TryGetValue(id, out GameElement_BM element_BM))
{
return element_BM.matchedElement;
}
return null;
}
/// <summary>
/// 从存档类中生成游戏物体
/// </summary>
public abstract void ExecuteBM();
/// <summary>
/// 复制物体

View File

@@ -39,12 +39,14 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
//(attachedElement as NoteElement).noteJudgeSubmodule = new NoteJudgeSubmodule(attachedElement);
(attachedElement as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attachedElement as NoteBase);
attachedElement.submoduleList.Add((attachedElement as NoteBase).noteJudgeSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
//(attached as NoteElement).noteJudgeSubmodule = new NoteJudgeSubmodule(attached);
(attached as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attached as NoteBase);
attached.submoduleList.Add((attached as NoteBase).noteJudgeSubmodule);
}
}

View File

@@ -7,7 +7,7 @@ using UnityEngine;
namespace Ichni.RhythmGame
{
public abstract partial class NoteBase : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule, IHaveEffectSubmodule
public abstract partial class NoteBase : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule
{
[Title("Basic Info")]
public float exactJudgeTime;
@@ -23,7 +23,6 @@ namespace Ichni.RhythmGame
[Title("Submodules")]
public TransformSubmodule transformSubmodule { get; set; }
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
public EffectSubmodule effectSubmodule { get; set; }
public NoteJudgeSubmodule noteJudgeSubmodule { get; set; }
[Title("In-Game Info")]
@@ -59,12 +58,10 @@ namespace Ichni.RhythmGame
{
transformSubmodule = new TransformSubmodule(this);
timeDurationSubmodule = new TimeDurationSubmodule(this);
effectSubmodule = new EffectSubmodule(this, EffectSubmodule.EffectSubmodulePreset.Note);
noteJudgeSubmodule = new NoteJudgeSubmodule(this);
submoduleList.Add(transformSubmodule);
submoduleList.Add(timeDurationSubmodule);
submoduleList.Add(effectSubmodule);
submoduleList.Add(noteJudgeSubmodule);
}
@@ -93,24 +90,27 @@ namespace Ichni.RhythmGame
isJudged = true;
}
}
effectSubmodule.effectCollection["Generate"].ForEach(e => e.UpdateEffect());
effectSubmodule.effectCollection["GeneralJudge"].ForEach(e => e.UpdateEffect());
switch (EditorManager.instance.currentJudgeType)
if (noteVisual != null)
{
case NoteJudgeType.Perfect:
effectSubmodule.effectCollection["Perfect"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Good:
effectSubmodule.effectCollection["Good"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Bad:
effectSubmodule.effectCollection["Bad"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Miss:
effectSubmodule.effectCollection["Miss"].ForEach(e => e.UpdateEffect());
break;
noteVisual.effectSubmodule.effectCollection["Generate"].ForEach(e => e.UpdateEffect());
noteVisual.effectSubmodule.effectCollection["GeneralJudge"].ForEach(e => e.UpdateEffect());
switch (EditorManager.instance.currentJudgeType)
{
case NoteJudgeType.Perfect:
noteVisual.effectSubmodule.effectCollection["Perfect"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Good:
noteVisual.effectSubmodule.effectCollection["Good"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Bad:
noteVisual.effectSubmodule.effectCollection["Bad"].ForEach(e => e.UpdateEffect());
break;
case NoteJudgeType.Miss:
noteVisual.effectSubmodule.effectCollection["Miss"].ForEach(e => e.UpdateEffect());
break;
}
}
}

View File

@@ -4,7 +4,7 @@ using UnityEngine;
namespace Ichni.RhythmGame
{
public abstract class NoteVisualBase : SubstantialObject
public abstract class NoteVisualBase : SubstantialObject, IHaveEffectSubmodule
{
public NoteBase note;
@@ -13,5 +13,14 @@ namespace Ichni.RhythmGame
public List<GameObject> notePartList;
public List<GameObject> effectPartList;
public EffectSubmodule effectSubmodule { get; set; }
protected override void SetDefaultSubmodules()
{
base.SetDefaultSubmodules();
effectSubmodule = new EffectSubmodule(this, EffectSubmodule.EffectSubmodulePreset.Note);
submoduleList.Add(effectSubmodule);
}
}
}

View File

@@ -39,6 +39,8 @@ namespace Ichni.RhythmGame
private void Update()
{
Debug.Log(timeDurationSubmodule == null);
if (timeDurationSubmodule.CheckTimeInDuration(EditorManager.instance.songModule.songTime))
{
(trackTimeSubmodule as TrackTimeSubmoduleMovable)?.UpdateTrackPart();

View File

@@ -98,7 +98,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
CrossTrackPoint.GenerateElement(elementName, elementGuid, tags, false,
matchedElement = CrossTrackPoint.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid) as ElementFolder, trackSwitch, trackPercent);
}

View File

@@ -71,7 +71,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
TrackHeadPoint.GenerateElement(elementName, elementGuid, tags, false,
matchedElement = TrackHeadPoint.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid) as Track);
}

View File

@@ -98,7 +98,7 @@ namespace Ichni.RhythmGame
public override void ExecuteBM()
{
TrackPercentPoint.GenerateElement(elementName, elementGuid, tags, false,
matchedElement = TrackPercentPoint.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid) as Track, trackPercent.ConvertToGameType());
}

View File

@@ -19,7 +19,7 @@ namespace Ichni.RhythmGame
public TrackPathSubmodule(Track track, Track.TrackSpaceType trackSpaceType, Track.TrackSamplingType trackSamplingType, bool isClosed) : base(track)
{
this.path = track.AddComponent<SplineComputer>();
track.trackPathSubmodule = this;
this.track.trackPathSubmodule = this;
this.pathNodeList = new List<PathNode>();
this.trackSpaceType = trackSpaceType;
this.trackSamplingType = trackSamplingType;
@@ -100,12 +100,14 @@ namespace Ichni.RhythmGame
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed);
track.submoduleList.Add(track.trackPathSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
Track track = attachedElement as Track;
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed);
track.submoduleList.Add(track.trackPathSubmodule);
}
}

View File

@@ -14,7 +14,6 @@ namespace Ichni.RhythmGame
public TrackRendererSubmodule(Track track) : base(track)
{
this.track = track;
this.track.trackRendererSubmodule = this;
}
@@ -78,12 +77,14 @@ namespace Ichni.RhythmGame
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule = new TrackRendererSubmodule(track);//TODO: Implement Material
track.submoduleList.Add(track.trackRendererSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule = new TrackRendererSubmodule(track);//TODO: Implement Material
track.submoduleList.Add(track.trackRendererSubmodule);
}
}
}

View File

@@ -39,9 +39,7 @@ namespace Ichni.RhythmGame
this.trackTotalTime = trackEndTime - trackStartTime;
this.visibleTrackTimeLength = visibleTrackTimeLength;
this.animationCurveType = animationCurveType;
track.timeDurationSubmodule.startTime = trackStartTime;
track.timeDurationSubmodule.endTime = trackEndTime + visibleTrackTimeLength;
//timeDurationSubmodule 根据下辖Note的时间来设置
}
public void UpdateTrackPart()
@@ -98,12 +96,14 @@ namespace Ichni.RhythmGame
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackTimeSubmodule = new TrackTimeSubmoduleMovable(track, trackStartTime, trackEndTime, visibleTrackTimeLength, animationCurveType);
track.submoduleList.Add(track.trackTimeSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackTimeSubmodule = new TrackTimeSubmoduleMovable(track, trackStartTime, trackEndTime, visibleTrackTimeLength, animationCurveType);
track.submoduleList.Add(track.trackTimeSubmodule);
}
}
}
@@ -123,9 +123,6 @@ namespace Ichni.RhythmGame
this.animationCurveType = animationCurveType;
this.headPercent = 0;
this.tailPercent = 1;
track.timeDurationSubmodule.startTime = -999;
track.timeDurationSubmodule.endTime = 999;
//timeDurationSubmodule 根据下辖Note的时间来设置
}
@@ -158,12 +155,14 @@ namespace Ichni.RhythmGame
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackTimeSubmodule = new TrackTimeSubmoduleStatic(track, trackTotalTime, animationCurveType);
track.submoduleList.Add(track.trackTimeSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackTimeSubmodule = new TrackTimeSubmoduleStatic(track, trackTotalTime, animationCurveType);
track.submoduleList.Add(track.trackTimeSubmodule);
}
}
}