Files
ichni_Creator_Studio/Assets/Scripts/Manager/ProjectManager.cs
TRAfoer 84ff356427 musicplayer改
Signed-off-by: TRAfoer <lhf190@outlook.com>
2025-08-23 23:18:29 +08:00

534 lines
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Ichni.Editor;
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 BeatmapClipManager beatmapClipManager;
public BeatmapMergeManager beatmapMergeManager;
public NotePrefabManager notePrefabManager;
public AutoSaveManager autoSaveManager;
public ProjectManager()
{
saveManager = new SaveManager();
loadManager = new LoadManager();
exportManager = new ExportManager();
beatmapClipManager = new BeatmapClipManager();
beatmapMergeManager = new BeatmapMergeManager();
notePrefabManager = new NotePrefabManager();
autoSaveManager = new AutoSaveManager();
}
public void GenerateEmptyProject(ProjectInformation_BM projectInfo_BM, SongInformation_BM songInfo_BM)
{
projectInfo_BM.ExecuteBM();
songInfo_BM.ExecuteBM();
EditorManager.instance.beatmapContainer = new BeatmapContainer();
EditorManager.instance.commandScripts = new CommandScripts(new List<string>());
}
}
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";
LogWindow.Log("Start Exporting...");
ExportProjectInfo(projectInfoPath);
ExportSongInfo(songInfoPath);
ExportBeatMap(beatmapPath);
ExportCommandScripts(commandScriptsPath);
LogWindow.Log("Export Complete", Color.green);
}
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()
{
LogWindow.Log("Start Saving...");
SaveProjectInfo();
SaveSongInfo();
SaveBeatMap();
SaveCommandScripts();
LogWindow.Log("Save Complete", Color.green);
}
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();
LoadCommandScripts();
LoadBeatMap();
LogWindow.Log("Load Complete", Color.green);
}
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();
}
public void LoadExport(string projectName)
{
LoadProjectInfoExport(projectName);
LoadSongInfoExport(projectName);
LoadCommandScriptsExport(projectName);
LoadBeatMapExport(projectName);
LogWindow.Log("Load Export Complete,", new Color(0.5f, 0f, 1f));
LogWindow.Log("Please Save Your Project As You Can", new Color(0.5f, 0f, 1f));
}
private void LoadProjectInfoExport(string projectName)
{
string projectInfoPath = Application.streamingAssetsPath + "/Export/" + projectName + "/ProjectInfo.bytes";
ES3.Load<ProjectInformation_BM>("ProjectInformation", projectInfoPath, ProjectManager.ExportSettings).ExecuteBM();
}
private void LoadSongInfoExport(string projectName)
{
string songInfoPath = Application.streamingAssetsPath + "/Export/" + projectName + "/SongInfo.bytes";
ES3.Load<SongInformation_BM>("SongInformation", songInfoPath, ProjectManager.ExportSettings).ExecuteBM();
}
private void LoadBeatMapExport(string projectName)
{
string beatMapPath = Application.streamingAssetsPath + "/Export/" + projectName + "/Beatmap.bytes";
ES3.Load<BeatmapContainer_BM>("Beatmap", beatMapPath, ProjectManager.ExportSettings).ExecuteBM();
}
private void LoadCommandScriptsExport(string projectName)
{
string commandScriptsPath = Application.streamingAssetsPath + "/Export/" + projectName + "/CommandScripts.bytes";
ES3.Load<CommandScripts_BM>("CommandScripts", commandScriptsPath, ProjectManager.ExportSettings).ExecuteBM();
}
}
public class BeatmapClipManager
{
public void SaveClip(string clipName)
{
LogWindow.Log("Start Saving Clip...");
if (EditorManager.instance.operationManager.currentSelectedElements.Count != 1) // TODO: 后续适应多选
{
LogWindow.Log("Please select only one Game Element to save the beatmap clip.", Color.red);
return;
}
GameElement selectedElement = EditorManager.instance.operationManager.currentSelectedElements[0];
if (selectedElement is null)
{
LogWindow.Log("Please select a Game Element to save the beatmap clip.", Color.red);
return;
}
_SaveClip(selectedElement, clipName);
LogWindow.Log("Save Clip Complete", Color.green);
}
public void LoadClip(string clipName)
{
LogWindow.Log("Start Loading Clip...");
if (!ES3.FileExists(Application.streamingAssetsPath + "/Clips/" + clipName + ".json"))
{
LogWindow.Log("Clip not found", Color.red);
return;
}
if (EditorManager.instance.operationManager.currentSelectedElements.Count != 1) // TODO: 后续适应多选
{
LogWindow.Log("Please select only one Game Element to load the beatmap clip.", Color.red);
return;
}
GameElement selectedElement = EditorManager.instance.operationManager.currentSelectedElements[0];
if (selectedElement is null)
{
LogWindow.Log("Please select a Game Element to load the beatmap clip.", Color.red);
return;
}
Debug.Log(selectedElement.elementName + " " + selectedElement.elementGuid);
_LoadClip(selectedElement, clipName);
LogWindow.Log("Load Clip Complete", Color.green);
}
private void _SaveClip(GameElement element, string clipName)
{
List<BaseElement_BM> clip = new List<BaseElement_BM>();
element.GetAllGameElementsFromThis().ForEach(e =>
{
e.SaveBM();
clip.Add(e.matchedBM);
e.submoduleList.ForEach(s =>
{
s.SaveBM();
clip.Add(s.matchedBM);
});
});
string filePath = Application.streamingAssetsPath + "/Clips/" + clipName + ".json";
ES3.Save("Clip", clip, filePath, ProjectManager.SaveSettings);
}
private void _LoadClip(GameElement target, string clipName)
{
string filePath = Application.streamingAssetsPath + "/Clips/" + clipName + ".json";
List<BaseElement_BM> clip = ES3.Load<List<BaseElement_BM>>("Clip", filePath, ProjectManager.SaveSettings);
//对于第一个元素,需要特殊处理,将它放入目标物体的子物体列表中
GameElement_BM first = clip[0] as GameElement_BM;
List<BaseElement_BM> firstAttaches = GameElement_BM.GetAllAttachedBaseElements(first, clip);
first.elementGuid = Guid.NewGuid();
GameElement_BM.identifier.TryAdd(first.elementGuid, first);
firstAttaches.ForEach(e => { e.attachedElementGuid = first.elementGuid; });
//将目标物体临时存入读存档的Dictionary中
target.SaveBM();
GameElement_BM.identifier.TryAdd(target.elementGuid, target.matchedBM as GameElement_BM);
(target.matchedBM as GameElement_BM).matchedElement = target;
first.attachedElementGuid = target.elementGuid;
for (var index = 1; index < clip.Count; index++)
{
var element = clip[index];
if (element is GameElement_BM gameElement)
{
List<BaseElement_BM> attachedElements = GameElement_BM.GetAllAttachedBaseElements(gameElement, clip);
gameElement.elementGuid = Guid.NewGuid();
GameElement_BM.identifier.TryAdd(gameElement.elementGuid, gameElement);
attachedElements.ForEach(e => { e.attachedElementGuid = gameElement.elementGuid; });
}
}
first.ExecuteBM();
for (var index = 1; index < clip.Count; index++)
{
clip[index].ExecuteBM();
}
}
}
public class BeatmapMergeManager
{
public void MergeBeatmap(string mergeName)
{
string mergePath = Application.streamingAssetsPath + "/Merges/" + mergeName + ".json";
BeatmapContainer_BM merge = ES3.Load<BeatmapContainer_BM>("Beatmap", mergePath, ProjectManager.SaveSettings);
merge.elementList.ForEach(element =>
{
if (element == null)
{
Debug.LogError("Null element detected in elementList. Skipping execution.");
return;
}
if (BeatmapContainer_BM.LowPriorityGameElementTypes.Contains(element.GetType()))
{
return;
}
if (element is GameElement_BM gameElement)
{
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
}
if (element is GameCamera_BM || GameElement_BM.GetElementBM(element.attachedElementGuid) is GameCamera_BM)
{
return;
}
element.ExecuteBM();
});
merge.elementList.ForEach(element =>
{
if (element == null)
{
Debug.LogError("Null element detected in elementList during low-priority execution. Skipping execution.");
return;
}
if (BeatmapContainer_BM.LowPriorityGameElementTypes.Contains(element.GetType()))
{
element.ExecuteBM();
}
});
EditorManager.instance.beatmapContainer.ExecuteLowPriorityActions();
}
}
public class NotePrefabManager
{
private string notePrefabPath => Application.streamingAssetsPath + "/NotePrefabs";
private string GetNotePrefabPath(string notePrefabName) => notePrefabPath + "/" + notePrefabName + ".json";
public void SaveNotePrefab(NoteBase note, string noteName)
{
List<BaseElement_BM> clip = new List<BaseElement_BM>();
note.GetAllGameElementsFromThis().ForEach(e =>
{
e.SaveBM();
clip.Add(e.matchedBM);
e.submoduleList.ForEach(s =>
{
s.SaveBM();
if (s.matchedBM != null)
{
clip.Add(s.matchedBM);
}
});
});
ES3.Save("Note", clip, GetNotePrefabPath(noteName), ProjectManager.SaveSettings);
}
public void LoadNotePrefab(NoteBase target, string noteName)
{
if (target.noteVisual != null)
{
return;
}
List<BaseElement_BM> clip = ES3.Load<List<BaseElement_BM>>("Note", GetNotePrefabPath(noteName), ProjectManager.SaveSettings);
if (clip == null || clip.Count == 0)
{
LogWindow.Log("Note prefab not found", Color.red);
return;
}
target.SaveBM();
GameElement_BM.identifier.TryAdd(target.elementGuid, target.matchedBM as GameElement_BM);
(target.matchedBM as GameElement_BM).matchedElement = target;
GameElement_BM first = clip[0] as GameElement_BM;
List<BaseElement_BM> firstAttaches = GameElement_BM.GetAllAttachedBaseElements(first, clip);
first.elementGuid = target.elementGuid;
GameElement_BM.identifier.TryAdd(first.elementGuid, first);
firstAttaches.ForEach(e => { e.attachedElementGuid = first.elementGuid; });
for (var index = 1; index < clip.Count; index++)
{
var element = clip[index];
if (element is GameElement_BM gameElement)
{
List<BaseElement_BM> attachedElements = GameElement_BM.GetAllAttachedBaseElements(gameElement, clip);
gameElement.elementGuid = Guid.NewGuid();
GameElement_BM.identifier.TryAdd(gameElement.elementGuid, gameElement);
attachedElements.ForEach(e => { e.attachedElementGuid = gameElement.elementGuid; });
}
}
for (var index = 1; index < clip.Count; index++)
{
clip[index].ExecuteBM();
}
target.SetDefaultSubmodules();
}
}
public class AutoSaveManager
{
private string autoSavePath => Application.streamingAssetsPath + "/AutoSave/" +
EditorManager.instance.projectInformation.projectName;
private string GetAutoSavePath(string autoSaveName) => autoSavePath + "/" + autoSaveName + ".json";
private float autoSaveInterval => EditorManager.instance.editorSettings.autoSaveInterval;
private int maximumAutoSaveCount => EditorManager.instance.editorSettings.maximumAutoSaveCount;
public float autoSaveTimer;
public AutoSaveManager()
{
autoSaveTimer = 0;
}
public void UpdateAutoSave()
{
autoSaveTimer += Time.deltaTime;
if (autoSaveTimer >= autoSaveInterval)
{
AutoSave();
autoSaveTimer = 0;
}
}
private void AutoSave()
{
List<string> saveFiles = GetSortedSaveFiles();
if (saveFiles.Count > 0)
{
// 删除最旧的存档(如果超过数量)
if (saveFiles.Count >= maximumAutoSaveCount)
{
string oldestSave = saveFiles[saveFiles.Count - 1];
File.Delete(oldestSave);
saveFiles.RemoveAt(saveFiles.Count - 1);
LogWindow.Log("AutoSave finished, the oldest file deleted");
}
else
{
LogWindow.Log("AutoSave finished");
}
// 依次重命名存档
for (int i = saveFiles.Count - 1; i >= 0; i--)
{
string oldPath = saveFiles[i];
string newPath = GetAutoSavePath($"AutoSave_{i + 1}");
File.Move(oldPath, newPath);
}
}
// 保存最新存档
string newestSavePath = GetAutoSavePath("AutoSave_0");
SaveBeatMap(newestSavePath);
}
private void SaveBeatMap(string autoSavePath)
{
EditorManager.instance.beatmapContainer.SaveBM();
ES3.Save("Beatmap", EditorManager.instance.beatmapContainer.matchedBM as BeatmapContainer_BM,
autoSavePath, ProjectManager.SaveSettings);
}
private List<string> GetSortedSaveFiles()
{
if (!ES3.DirectoryExists(autoSavePath))
{
Directory.CreateDirectory(autoSavePath);
}
List<string> saveFiles = new List<string>(Directory.GetFiles(autoSavePath, "AutoSave_*.json"));
saveFiles.Sort(string.Compare);
return saveFiles;
}
}
}