using Cryville.Crtr.Components; using Cryville.Crtr.Event; using UnityEngine; namespace Cryville.Crtr { class TrackHandler : ContainerHandler { readonly GroupHandler gh; readonly Chart.Track track; public TrackHandler(GroupHandler gh, Chart.Track _track) : base() { track = _track; this.gh = gh; } public override string TypeName { get { return "track"; } } public override void Init() { base.Init(); sgos = gogroup.GetComponentsInChildren(); } SectionalGameObject[] sgos; Vector3 bpos; Quaternion brot; Vector3 spos; protected override void PreAwake(ContainerState s) { base.PreAwake(s); pwp = Vector3.zero; cpt = s.ScreenPoint; ptime = s.Time; if (s.CloneType == 2) { #if UNITY_5_6_OR_NEWER a_head.SetPositionAndRotation(GetCurrentWorldPoint(), Quaternion.Euler(s.Direction)); #else a_head.position = GetCurrentWorldPoint(); a_head.rotation = Quaternion.Euler(s.Direction); #endif } else if (s.CloneType == 3) { spos = Vector3.zero; bpos = cpt; brot = Quaternion.Euler(s.Direction); } } protected override void Awake(ContainerState s) { base.Awake(s); if (!gogroup) return; var p = GetCurrentWorldPoint(); foreach (var i in sgos) { i.Reset(); i.AppendPoint(p, s.QuatDir); } } Vector3 cpt; // Current point Vector3 ppt = Vector3.zero; // Previous point Vector3 pwp = Vector3.zero; // Previous world point float ptime; // Previous time float length; public override void Update(ContainerState s, StampedEvent ev) { base.Update(s, ev); if (s.CloneType == 2 || s.CloneType == 3) { var tpt = s.ScreenPoint; var tsv = s.ScrollVelocity; Vector3 dpt = (Vector3)tpt - ppt; // Delta 2D point dpt.z = (s.Time - ptime) * ChartPlayer.sv * tsv; // Delta Z Quaternion rotq = Quaternion.Euler(s.Direction); // Rotation var dwp = rotq * dpt; // Delta world point var nl = length + dwp.magnitude; // New length var tdist = s.Distance; if (nl >= tdist) { s.Break(); return; } length = nl; var wp = pwp + dwp; // World point pwp = wp; ppt += dpt; ptime = s.Time; if (!gogroup || s.CloneType == 3) return; var p = GetCurrentWorldPoint(); foreach (var i in sgos) i.AppendPoint(p, s.QuatDir); } else UpdatePosition(s); } void UpdatePosition(ContainerState s) { cpt = s.ScreenPoint; ppt = cpt; pwp = Vector3.zero; ptime = s.Time; length = 0; //Logger.LogFormat("main", 0, "Debug", "SV: {0}", cs.GetRawValue("svm").Value); } // TODO Fix anchor rotation public override void Anchor() { base.Anchor(); spos = bpos - GetCurrentWorldPoint(); } public override void EndUpdate(ContainerState s) { OpenAnchor("tail"); base.EndUpdate(s); CloseAnchor("tail"); if (s.CloneType == 0 || s.CloneType == 2) { EndUpdatePosition(ts); var p = GetCurrentWorldPoint(); foreach (var i in sgos) { i.AppendPoint(p, s.QuatDir); i.Seal(); } #if UNITY_5_6_OR_NEWER a_tail.SetPositionAndRotation(GetCurrentWorldPoint(), Quaternion.Euler(ts.Direction)); #else a_tail.position = GetCurrentWorldPoint(); a_tail.rotation = Quaternion.Euler(ts.Direction); #endif } else if (s.CloneType == 3) EndUpdatePosition(ns); else if (s.CloneType >= 16) EndUpdatePosition(ps); } void EndUpdatePosition(ContainerState s) { var tpt = s.ScreenPoint; var tsv = s.ScrollVelocity; Vector3 dpt = (Vector3)tpt - ppt; dpt.z = (s.Time - ptime) * ChartPlayer.sv * tsv; Quaternion rotq = Quaternion.Euler(s.Direction); var dwp = rotq * dpt; // Delta world point var nl = length + dwp.magnitude; // New length var tdist = s.Distance; if (nl >= tdist) dwp *= (tdist - length) / (nl - length); length = nl; var wp = pwp + dwp; // World point pwp = wp; ppt += dpt; } public Vector3 GetCurrentWorldPoint() { return pwp + cpt + spos; } } }