using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
using Sirenix.OdinInspector;
using SLSUtilities.General;
using UnityEngine;
namespace Ichni
{
///
/// 谱面数据容器。
/// 继承自 GameElement,作为编辑器中"游戏世界"的根节点,
/// 持有 projectInformation / songInformation / beatmapContainer / commandScripts
/// 等所有与谱面/游戏内容直接相关的数据。
/// 由 EditorManager 在场景中持有引用,并通过 EditorManager 的转发属性对外暴露,
/// 以实现零调用点改动的架构迁移。
///
public class ProjectContainer : GameElement
{
#region [单例] Singleton
private static ProjectContainer _instance;
public static ProjectContainer instance =>
_instance != null ? _instance : _instance = FindFirstObjectByType();
#endregion
#region [谱面数据] Project Data
public ProjectInformation projectInformation;
public SongInformation songInformation;
public BeatmapContainer beatmapContainer;
public CommandScripts commandScripts;
#endregion
#region [游戏全局元素] Global Game Elements
[Title("Runtime Global Elements")]
public VariablesContainer variablesContainer;
public BackgroundSetter backgroundSetter;
#endregion
#region [编辑器首选项] Editor Preferences
// 这些首选项字段放在 ProjectContainer 中,以便 SetUpInspector 将 this 作为 IBaseElement owner 传给 GenerateToggle
public NoteBase.NoteJudgeType currentJudgeType;
public bool useClickSelect = true;
public bool useNotePrefab = true;
public bool useQuickMove = false;
#endregion
#region [生成与初始化] Generation & Initialization
private void Awake()
{
_instance = this;
}
#endregion
#region [编辑器界面] Inspector
public override void SetUpInspector()
{
InspectorBuilder.For(this)
.Section("Editor Manager")
.Dropdown(nameof(currentJudgeType), typeof(NoteBase.NoteJudgeType), "Judge Type")
.OnChanged(() =>
{
foreach (GameElement gameElement in beatmapContainer.gameElementList)
{
if (gameElement is NoteVisualBase noteVisual)
noteVisual.Recover();
}
})
.Toggle(nameof(useNotePrefab), "Use Note Prefab")
.Toggle(nameof(useClickSelect), "Use Click Select")
.Toggle(nameof(useQuickMove), "Use Quick Move")
.Button("Generate Folder", () =>
ElementFolder.GenerateElement("Folder", Guid.NewGuid(), new List(), true, null))
.Button("Generate Background Setter", () =>
BackgroundSetter.GenerateElement("Background Setter", Guid.NewGuid(),
new List(), true, null, false, "basic", "Skybox", "Background"))
.Button("Generate Variables Container", () =>
VariablesContainer.GenerateElement("Variables Container", Guid.NewGuid(),
new List(), true, null, new Dictionary()))
.Build();
projectInformation.SetUpInspector();
songInformation.SetUpInspector();
EditorManager.instance.cameraManager.SetUpInspector();
// Grid 设置使用 RawSection 处理无绑定 Toggle/InputField 交互
var gridToggleRef = new ElementRef();
var gridSizeRef = new ElementRef();
var showCoordsRef = new ElementRef();
InspectorBuilder.For(this)
.RawSection("Grid", int.MaxValue, (insp, container) =>
{
var p = container.GenerateSubcontainer(3);
var gridToggle = insp.GenerateToggle(this, p, "Enable Grid");
gridToggle.AddListenerFunction(() =>
{
EditorManager.instance.gridController.gameObject.SetActive(gridToggle.toggle.isOn);
});
var gridSizeInput = insp.GenerateInputField(p, "Grid Size",
(EditorManager.instance.gridController.baseGridSize * 10).ToString());
gridSizeInput.AddListenerFunction(() =>
{
EditorManager.instance.gridController.baseGridSize = float.Parse(gridSizeInput.inputField.text) / 10;
});
var showCoords = insp.GenerateToggle(this, p, "Show Coordinates");
showCoords.toggle.isOn = EditorManager.instance.gridController.showCoordinates;
showCoords.AddListenerFunction(() =>
{
EditorManager.instance.gridController.showCoordinates = showCoords.toggle.isOn;
});
})
.Build();
}
#endregion
}
}