Note Prefab功能

This commit is contained in:
SoulliesOfficial
2025-03-24 13:41:50 -04:00
parent 54de98b0fa
commit 188f05182b
22 changed files with 756 additions and 33 deletions

View File

@@ -250,6 +250,22 @@ namespace Ichni.RhythmGame
/// </summary>
/// <param name="attached">父物体</param>
public abstract GameElement DuplicateBM(GameElement attached);
public static 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;
}
}
}
}

View File

@@ -43,6 +43,11 @@ namespace Ichni.RhythmGame
flick.track = null;
flick.isOnTrack = false;
}
if (EditorManager.instance.useNotePrefab)
{
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(flick,GetNoteTypeName(flick) + "_Prefab");
}
return flick;
}
@@ -66,6 +71,11 @@ namespace Ichni.RhythmGame
{
TemporaryObject.GenerateElement("New Note Visual", Guid.NewGuid(), new List<string>(), true, this);
});
if (noteVisual != null)
{
generateNoteVisualButton.button.interactable = false;
}
}
}

View File

@@ -47,6 +47,11 @@ namespace Ichni.RhythmGame
hold.track = null;
hold.isOnTrack = false;
}
if (EditorManager.instance.useNotePrefab)
{
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(hold,GetNoteTypeName(hold) + "_Prefab");
}
return hold;
}
@@ -112,6 +117,11 @@ namespace Ichni.RhythmGame
{
TemporaryObject.GenerateElement("New Note Visual", Guid.NewGuid(), new List<string>(), true, this);
});
if (noteVisual != null)
{
generateNoteVisualButton.button.interactable = false;
}
}
}

View File

@@ -159,6 +159,12 @@ namespace Ichni.RhythmGame
exactJudgeTimeInputField.AddListenerFunction(UpdateNoteInTrack);
exactJudgeTimeInputField.Mark(inspector, "ExactJudgeTime");
var saveNotePrefabButton =
inspector.GenerateButton(this, container, "Save Note Prefab", () =>
{
EditorManager.instance.projectManager.notePrefabManager.SaveNotePrefab(this, GetNoteTypeName(this) + "_Prefab");
});
var noteScreenPositionText = inspector.GenerateHintText(this, container, () => "Note Screen Position: " + noteScreenPosition);
}
}
@@ -173,6 +179,18 @@ namespace Ichni.RhythmGame
Miss
}
public static string GetNoteTypeName(NoteBase note)
{
return note switch
{
Tap => "Tap",
Stay => "Stay",
Hold => "Hold",
Flick => "Flick",
_ => throw new NotImplementedException("Note type not recognized")
};
}
}
namespace Beatmap

View File

@@ -39,6 +39,11 @@ namespace Ichni.RhythmGame
stay.track = null;
stay.isOnTrack = false;
}
if (EditorManager.instance.useNotePrefab)
{
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(stay,GetNoteTypeName(stay) + "_Prefab");
}
return stay;
}
@@ -61,6 +66,11 @@ namespace Ichni.RhythmGame
{
TemporaryObject.GenerateElement("New Note Visual", Guid.NewGuid(), new List<string>(), true, this);
});
if (noteVisual != null)
{
generateNoteVisualButton.button.interactable = false;
}
}
}

View File

@@ -41,6 +41,11 @@ namespace Ichni.RhythmGame
tap.isOnTrack = false;
}
if (EditorManager.instance.useNotePrefab)
{
EditorManager.instance.projectManager.notePrefabManager.LoadNotePrefab(tap,GetNoteTypeName(tap) + "_Prefab");
}
return tap;
}
}
@@ -62,6 +67,11 @@ namespace Ichni.RhythmGame
{
TemporaryObject.GenerateElement("New Note Visual", Guid.NewGuid(), new List<string>(), true, this);
});
if (noteVisual != null)
{
generateNoteVisualButton.button.interactable = false;
}
}
}

View File

@@ -19,7 +19,7 @@ namespace Ichni.RhythmGame
string themeBundleName, string objectName, GameElement parentElement)
{
GameObject themeBundleObject = ThemeBundleManager.instance.GetObject<GameObject>(themeBundleName, objectName);
Debug.Log(parentElement.elementName);
SubstantialObject substantialObject = Instantiate(themeBundleObject, parentElement.transform).GetComponent<SubstantialObject>();
substantialObject.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
substantialObject.themeBundleName = themeBundleName;

View File

@@ -35,6 +35,7 @@ namespace Ichni
public CommandScripts commandScripts;
public NoteBase.NoteJudgeType currentJudgeType;
public bool useNotePrefab;
public BasePrefabsCollection basePrefabs;
[Title("Runtime Global Elements")]
@@ -117,6 +118,9 @@ namespace Ichni
inspector.GenerateButton(this, container, "Generate Variables Container",
() => VariablesContainer.GenerateElement("Variables Container", Guid.NewGuid(),
new List<string>(), true, null, new Dictionary<string, int>()));
var useNotePrefabToggle =
inspector.GenerateToggle(this, container, "Use Note Prefab", nameof(useNotePrefab));
projectInformation.SetUpInspector();
songInformation.SetUpInspector();

View File

@@ -31,6 +31,7 @@ namespace Ichni
public LoadManager loadManager;
public ExportManager exportManager;
public BeatmapClipManager beatmapClipManager;
public NotePrefabManager notePrefabManager;
public AutoSaveManager autoSaveManager;
public ProjectManager()
@@ -39,6 +40,7 @@ namespace Ichni
loadManager = new LoadManager();
exportManager = new ExportManager();
beatmapClipManager = new BeatmapClipManager();
notePrefabManager = new NotePrefabManager();
autoSaveManager = new AutoSaveManager();
}
@@ -245,27 +247,12 @@ namespace Ichni
private void _LoadClip(GameElement target, 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);
//对于第一个元素,需要特殊处理,将它放入目标物体的子物体列表中
GameElement_BM first = clip[0] as GameElement_BM;
List<BaseElement_BM> firstAttaches = GetAllAttachedBaseElements(first, clip);
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; });
@@ -281,7 +268,7 @@ namespace Ichni
var element = clip[index];
if (element is GameElement_BM gameElement)
{
List<BaseElement_BM> attachedElements = GetAllAttachedBaseElements(gameElement, clip);
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; });
@@ -297,6 +284,68 @@ namespace Ichni
}
}
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();
clip.Add(s.matchedBM);
});
});
ES3.Save("Note", clip, GetNotePrefabPath(noteName), ProjectManager.SaveSettings);
}
public void LoadNotePrefab(NoteBase target, string noteName)
{
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();
}
}
}
public class AutoSaveManager
{
private string autoSavePath => Application.streamingAssetsPath + "/AutoSave/" +