Clip保存与读取

This commit is contained in:
SoulliesOfficial
2025-03-01 12:50:13 -05:00
parent ed863d6591
commit 6aba331079
27 changed files with 3573 additions and 32 deletions

View File

@@ -0,0 +1,71 @@
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Ichni.Editor
{
public class ClipManagementWindow : MovableWindow
{
public TMP_InputField clipNameInputField;
public Button applyClipButton;
public void InitializeAsSaveClip()
{
GameElement currentElement = EditorManager.instance.operationManager.currentSelectedElement;
if (currentElement == null)
{
LogWindow.Log("No Game Element selected.", Color.red);
return;
}
if (!OpenWindow())
{
return;
}
InitializeWindow("Save Clip: " + currentElement.elementName);
clipNameInputField.text = currentElement.elementName;
applyClipButton.onClick.RemoveAllListeners();
applyClipButton.onClick.AddListener(() =>
{
EditorManager.instance.projectManager.beatmapClipManager.Save(clipNameInputField.text);
gameObject.SetActive(false);
});
}
public void InitializeAsLoadClip()
{
if (!OpenWindow())
{
return;
}
InitializeWindow("Load Clip");
clipNameInputField.text = "";
applyClipButton.onClick.RemoveAllListeners();
applyClipButton.onClick.AddListener(() =>
{
EditorManager.instance.projectManager.beatmapClipManager.Load(clipNameInputField.text);
gameObject.SetActive(false);
});
}
private bool OpenWindow()
{
if (EditorManager.instance.uiManager.mainPage.toolBar.clipManagementWindow.gameObject.activeSelf)
{
LogWindow.Log("Clip Management Window is already active.");
return false;
}
gameObject.SetActive(true);
return true;
}
}
}

View File

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

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UI;
@@ -8,16 +9,24 @@ namespace Ichni.Editor
{
public partial class ToolBar : StaticWindow
{
[Title("Buttons")]
public Button projectInfoButton;
public Button songInfoButton;
public Button saveButton;
public Button exportButton;
public Button clipSaveButton;
public Button clipLoadButton;
[Title("Windows")]
public ClipManagementWindow clipManagementWindow;
protected override void Start()
{
base.Start();
saveButton.onClick.AddListener(EditorManager.instance.projectManager.saveManager.Save);
exportButton.onClick.AddListener(EditorManager.instance.projectManager.exportManager.Export);
clipSaveButton.onClick.AddListener(clipManagementWindow.InitializeAsSaveClip);
clipLoadButton.onClick.AddListener(clipManagementWindow.InitializeAsLoadClip);
}
}

View File

@@ -12,5 +12,14 @@ namespace Ichni.Editor
public RectTransform windowRect;
public Button closeButton;
public TMP_Text title;
protected void InitializeWindow(string titleText)
{
title.text = titleText;
closeButton.onClick.AddListener(() =>
{
gameObject.SetActive(false);
});
}
}
}

View File

@@ -70,6 +70,8 @@ namespace Ichni.RhythmGame
{
public abstract class BaseElement_BM
{
public Guid attachedElementGuid;
/// <summary>
/// 从存档类中生成游戏物体
/// </summary>

View File

@@ -126,14 +126,12 @@ namespace Ichni.RhythmGame
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

@@ -143,13 +143,11 @@ namespace Ichni.RhythmGame
{
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);
}
}
}

View File

@@ -16,6 +16,7 @@ namespace Ichni.RhythmGame
public SubmoduleBase(GameElement attachedGameElement)
{
this.attachedGameElement = attachedGameElement;
this.attachedGameElement.submoduleList.Add(this);
}
public abstract void SaveBM();
@@ -46,9 +47,8 @@ namespace Ichni.RhythmGame
{
public abstract class Submodule_BM : BaseElement_BM
{
[System.NonSerialized] public GameElement attachedElement; //存档类对应的游戏物体
public Guid attachedElementGuid;
[System.NonSerialized] protected GameElement attachedElement; //存档类对应的游戏物体
public Submodule_BM()
{

View File

@@ -136,13 +136,11 @@ namespace Ichni.RhythmGame
{
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

@@ -228,13 +228,11 @@ namespace Ichni.RhythmGame
{
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

@@ -69,7 +69,7 @@ namespace Ichni.RhythmGame
if (element is GameElement_BM gameElement)
{
#if UNITY_EDITOR
Debug.Log("Adding element to identifier: " + gameElement.elementName + " " + gameElement.elementGuid);
//Debug.Log("Adding element to identifier: " + gameElement.elementName + " " + gameElement.elementGuid);
#endif
GameElement_BM.identifier.Add(gameElement.elementGuid, gameElement);
}

View File

@@ -163,9 +163,10 @@ namespace Ichni.RhythmGame
}
/// <summary>
/// 获取自身和所有子GameElement
/// 获取所有子GameElement
/// </summary>
public List<GameElement> GetAllGameElementsFromThis()
/// <param name="includeThis">是否包括自身</param>
public List<GameElement> GetAllGameElementsFromThis(bool includeThis = true)
{
void GetAllChildrenRecursively(GameElement parent, List<GameElement> elements)
{
@@ -178,6 +179,8 @@ namespace Ichni.RhythmGame
List<GameElement> gameElements = new List<GameElement> { this };
GetAllChildrenRecursively(this, gameElements);
if(!includeThis) gameElements.Remove(this);
return gameElements;
}
@@ -197,7 +200,6 @@ namespace Ichni.RhythmGame
public string elementName;
public List<string> tags;
public Guid elementGuid;
public Guid attachedElementGuid;
public GameElement_BM()
{

View File

@@ -40,13 +40,11 @@ namespace Ichni.RhythmGame
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
(attachedElement as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attachedElement as NoteBase);
attachedElement.submoduleList.Add((attachedElement as NoteBase).noteJudgeSubmodule);
}
public override void DuplicateBM(GameElement attached)
{
(attached as NoteBase).noteJudgeSubmodule = new NoteJudgeSubmodule(attached as NoteBase);
attached.submoduleList.Add((attached as NoteBase).noteJudgeSubmodule);
}
}

View File

@@ -11,7 +11,6 @@ namespace Ichni.RhythmGame
public TrackSubmodule(Track track) : base(track)
{
this.track = track;
this.track.submoduleList.Add(this);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using Ichni.Editor;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
@@ -28,18 +29,21 @@ namespace Ichni
public SaveManager saveManager;
public LoadManager loadManager;
public ExportManager exportManager;
public BeatmapClipManager beatmapClipManager;
public ProjectManager()
{
saveManager = new SaveManager();
loadManager = new LoadManager();
exportManager = new ExportManager();
beatmapClipManager = new BeatmapClipManager();
}
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.projectInformation = new ProjectInformation(projectName, "Soullies", "2.0",
DateTime.Now.ToString(CultureInfo.CurrentCulture), DateTime.Now.ToString(CultureInfo.CurrentCulture),
new List<string>());
EditorManager.instance.songInformation = new SongInformation("TestSong", 120, 0);
EditorManager.instance.beatmapContainer = new BeatmapContainer();
EditorManager.instance.commandScripts = new CommandScripts(new List<string>());
@@ -156,6 +160,7 @@ namespace Ichni
{
yield return new WaitForEndOfFrame();
}
LoadBeatMap();
LogWindow.Log("Load Complete", Color.green);
}
@@ -184,4 +189,101 @@ namespace Ichni
ProjectManager.SaveSettings).ExecuteBM();
}
}
public class BeatmapClipManager
{
public void Save(string clipName)
{
LogWindow.Log("Start Saving Clip...");
GameElement selectedElement = EditorManager.instance.operationManager.currentSelectedElement;
if (selectedElement is not ElementFolder folder)
{
LogWindow.Log("Please select a folder to save the beatmap clip.", Color.red);
return;
}
SaveClip(folder, clipName);
LogWindow.Log("Save Clip Complete", Color.green);
}
public void Load(string clipName)
{
LogWindow.Log("Start Loading Clip...");
if(!ES3.FileExists(Application.streamingAssetsPath + "/Clips/" + clipName + ".json"))
{
LogWindow.Log("Clip not found", Color.red);
return;
}
LoadClip(clipName);
LogWindow.Log("Load Clip Complete", Color.green);
}
public void SaveClip(ElementFolder folder, string clipName)
{
List<BaseElement_BM> clip = new List<BaseElement_BM>();
folder.SaveBM();
folder.matchedBM.attachedElementGuid = Guid.Empty;
clip.Add(folder.matchedBM);
folder.submoduleList.ForEach(s =>
{
s.SaveBM();
clip.Add(s.matchedBM);
});
folder.GetAllGameElementsFromThis(false).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);
}
public void LoadClip(string clipName)
{
List<BaseElement_BM> GetAllAttachedBaseElements(GameElement_BM gameElement, List<BaseElement_BM> clip)
{
Guid elementGuid = gameElement.elementGuid;
List<BaseElement_BM> result = new List<BaseElement_BM>();
foreach (BaseElement_BM element in clip)
{
if (element.attachedElementGuid == elementGuid)
{
result.Add(element);
}
}
return result;
}
string filePath = Application.streamingAssetsPath + "/Clips/" + clipName + ".json";
List<BaseElement_BM> clip = ES3.Load<List<BaseElement_BM>>("Clip", filePath, ProjectManager.SaveSettings);
foreach (BaseElement_BM element in clip)
{
if (element is GameElement_BM gameElement)
{
List<BaseElement_BM> attachedElements = GetAllAttachedBaseElements(gameElement, clip);
gameElement.elementGuid = Guid.NewGuid();
GameElement_BM.identifier.TryAdd(gameElement.elementGuid, gameElement);
attachedElements.ForEach(e => { e.attachedElementGuid = gameElement.elementGuid; });
}
}
clip.ForEach(e => e.ExecuteBM());
}
}
}