using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Ichni.RhythmGame.Beatmap; using Sirenix.OdinInspector; using UniRx; using UnityEngine; namespace Ichni.RhythmGame { [System.Serializable] public abstract partial class BaseElement : SerializedMonoBehaviour { //物体名 public string elementName; //标识 GUID public Guid elementGuid; //标签 public List tags; //存档 public BaseElement_BM matchedBM; //父游戏物体 public BaseElement parentElement; //子物体列表 public List childElementList = new List(); //次级模块 public TimeDurationSubmodule timeDurationSubmodule; public TransformSubmodule transformSubmodule; public ColorSubmodule colorSubmodule; /// /// 首次初始化 /// /// 物体名 public virtual void Initialize(string name, Guid elementGuid, List tags) { this.elementName = name; this.elementGuid = elementGuid; this.tags = tags; EditorManager.instance.elementList.Add(this); //GameManager.beatMapContainer.beatMapElementList.Add(this); //serialNumber = totalSerialNumber++; //SetTransformObserver(); } /// /// 在所有物体生成完毕后,执行的初始化方法 /// public virtual void AfterInitialize() { } /// /// 刷新物体的状态 /// public virtual void Refresh() { } /// /// 设置父物体 /// /// 父物体 public void SetParent(BaseElement parentElement) { if (parentElement != null) { parentElement.childElementList.Add(this); this.parentElement = parentElement; transform.SetParent(parentElement.transform); } } } public abstract partial class BaseElement { private void Start() { SetTransformObserver(); } public virtual void SetTimeDuration() { } public void ApplyTimeDuration() { childElementList.ForEach(x => x.ApplyTimeDuration()); timeDurationSubmodule?.SetDurationFromChildren(childElementList.Select(x => x.timeDurationSubmodule) .ToList()); } /// /// 设置物体Transform的监听,顺序为Scale -> EulerAngles -> Position /// 如果有一些特殊的物体(例如Camera,ElementFolder),需要自定义监听,可以重写这个方法 /// 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); } } public abstract partial class BaseElement //存档,删除,复制,粘贴 { /// /// 用于生成存档 /// public abstract void SaveBM(); /// /// 当物体被删除时执行的方法 /// public virtual void OnDelete() { } /// /// 删除物体,包括所有子物体 /// [Button("Delete")] public virtual void Delete() { if (this.childElementList != null) { for (int i = 0; i < childElementList.Count; i++) { childElementList[i].Delete(); //删除子GameElement、 } } OnDelete(); #if UNITY_EDITOR Debug.Log("Delete " + elementName + "(" + elementGuid + ")"); #endif EditorManager.instance.elementList.Remove(this); //从保存列表中剔除 this.parentElement.childElementList.Remove(this); Destroy(gameObject); //销毁 } } namespace Beatmap { [System.Serializable] public abstract class BaseElement_BM { [System.NonSerialized] public static Dictionary identifier; //存档类的标识符 [System.NonSerialized] public BaseElement matchedElement; //存档类对应的游戏物体 public string elementName; public List tags; public Guid elementGuid; public Guid attachedElementGuid; public BaseElement_BM() { } public BaseElement_BM(string elementName, Guid elementGuid, List tags, BaseElement_BM attachedElement) { this.elementName = elementName; this.elementGuid = elementGuid; this.tags = tags; this.attachedElementGuid = attachedElement?.elementGuid ?? Guid.Empty; identifier.TryAdd(this.elementGuid, this); } public static BaseElement_BM GetElementBM(Guid id) { if (identifier.TryGetValue(id, out BaseElement_BM element_BM)) { return element_BM; } Debug.LogAssertion("Element not found or do not have id"); return null; } public static BaseElement GetElement(Guid id) { return GetElementBM(id)?.matchedElement; } /// /// 用于从存档中生成物体 /// public abstract void ExecuteBM(); /// /// 用于复制物体 /// public abstract BaseElement DuplicateBM(BaseElement parent); } } }