using Cryville.Common; using Cryville.Common.Buffers; using Cryville.Crtr.Components; using System; using System.Collections.Generic; using System.Globalization; using UnityEngine; namespace Cryville.Crtr.Event { public abstract class ContainerHandler : IDisposable { /// /// Prehandling , prehandling the events. /// public ContainerState ps; /// /// Backward , disposing events at the backward clipping plane, firing anchor state and temporary state. /// public ContainerState bs; /// /// Current , handling events occuring at the current time. /// public ContainerState cs; /// /// Anchor , computing the start position of the temporary state. /// public ContainerState ns; /// /// Temporary , rendering events between the clipping planes. /// public ContainerState ts; /// /// group, the containing all the generated elements in the . /// public Transform gogroup; public Vector3 Position { get; protected set; } public Quaternion Rotation { get; protected set; } public bool Alive { get; private set; } public bool Awoken { get; private set; } public bool Disposed { get; private set; } public EventContainer Container { get { return cs.Container; } } SkinContainer skinContainer; protected Judge judge; public void AttachSystems(PdtSkin skin, Judge judge) { skinContainer = new SkinContainer(skin); this.judge = judge; } public ContainerHandler() { } public abstract string TypeName { get; } public readonly Dictionary> Anchors = new Dictionary>(); public Anchor OpenedAnchor; protected Anchor a_cur; protected Anchor a_head; protected Anchor a_tail; protected readonly static int _a_cur = IdentifierManager.SharedInstance.Request("cur"); protected readonly static int _a_head = IdentifierManager.SharedInstance.Request("head"); protected readonly static int _a_tail = IdentifierManager.SharedInstance.Request("tail"); public virtual void PreInit() { gogroup = new GameObject(TypeName + ":" + Container.GetHashCode().ToString(CultureInfo.InvariantCulture)).transform; if (cs.Parent != null) gogroup.SetParent(cs.Parent.Handler.gogroup, false); a_cur = RegisterAnchor(_a_cur); a_head = RegisterAnchor(_a_head); a_tail = RegisterAnchor(_a_tail); } protected Anchor RegisterAnchor(int name) { var go = new GameObject("." + IdentifierManager.SharedInstance.Retrieve(name)).transform; go.SetParent(gogroup, false); var result = new Anchor(name, go); List list; if (!Anchors.TryGetValue(name, out list)) Anchors.Add(name, list = new List()); list.Add(result); return result; } /// /// Called upon StartUpdate of ps 17. /// public virtual void Init() { skinContainer.MatchStatic(ps); foreach (var i in gogroup.GetComponentsInChildren()) i.Init(); } public virtual void PostInit() { gogroup.gameObject.SetActive(false); } public virtual void Dispose() { if (Disposed) return; Disposed = true; if (gogroup) GameObject.Destroy(gogroup.gameObject); // gogroup.gameObject.SetActive(false); Alive = false; } protected virtual void PreAwake(ContainerState s) { if (gogroup) { gogroup.gameObject.SetActive(true); OpenAnchor(a_head); } Awoken = true; Alive = true; } protected virtual void Awake(ContainerState s) { if (gogroup) CloseAnchor(); } protected virtual void GetPosition(ContainerState s) { } public virtual void StartUpdate(ContainerState s) { if (s.CloneType >= 2 && s.CloneType < 16) { PreAwake(s); Awake(s); } else if (s.CloneType == 17) { Init(); } } static readonly SimpleObjectPool anchorEvPool = new SimpleObjectPool(1024); protected void PushAnchorEvent(double time, Anchor anchor) { var tev = anchorEvPool.Rent(); tev.Time = time; tev.Container = Container; tev.Target = anchor; ts.Bus.PushTempEvent(tev); } public virtual void Update(ContainerState s, StampedEvent ev) { bool flag = !Awoken && s.CloneType >= 2 && s.CloneType < 16; if (flag) PreAwake(s); if (gogroup && s.CloneType <= 2) skinContainer.MatchDynamic(s); if (flag) Awake(s); } public virtual void ExUpdate(ContainerState s, StampedEvent ev) { if (ev is StampedEvent.Anchor) { var tev = (StampedEvent.Anchor)ev; if (gogroup) { OpenAnchor(tev.Target); #if UNITY_5_6_OR_NEWER tev.Target.Transform.SetPositionAndRotation(Position, Rotation); #else tev.Target.Transform.position = GetCurrentWorldPoint(); tev.Target.Transform.rotation = Quaternion.Euler(s.Direction); #endif skinContainer.MatchDynamic(s); CloseAnchor(); } anchorEvPool.Return(tev); } } public virtual void MotionUpdate(byte ct, Chart.Motion ev) { } public virtual void EndUpdate(ContainerState s) { if (s.CloneType < 16) { Awoken = false; if (gogroup && s.CloneType <= 2) { OpenAnchor(a_tail); skinContainer.MatchDynamic(s); CloseAnchor(); } } } public virtual void Anchor() { if (cs.Working) PushAnchorEvent(cs.Time, a_cur); } protected void OpenAnchor(Anchor anchor) { if (OpenedAnchor != null) throw new InvalidOperationException("An anchor has been opened"); OpenedAnchor = anchor; } protected void CloseAnchor() { OpenedAnchor = null; } } }