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(Chart.Track ev, GroupHandler gh) : base() { track = ev; this.gh = gh; } public override string TypeName { get { return "track"; } } public override void Init() { base.Init(); sgos = RootTransform.GetComponentsInChildren(); } SectionalGameObject[] sgos; Vector3 bpos; Quaternion brot; Vector3 spos; public override void StartPhysicalUpdate(ContainerState s) { base.StartPhysicalUpdate(s); if (CanDoGraphicalUpdate(s)) { TransformAwake(s); } } protected override void StartPreGraphicalUpdate(ContainerState s) { base.StartPreGraphicalUpdate(s); spos = Vector3.zero; TransformAwake(s); bpos = Position; brot = Rotation; } protected override void StartGraphicalUpdate(ContainerState s) { base.StartGraphicalUpdate(s); if (RootTransform) { TransformAwake(s); var p = Position; foreach (var i in sgos) { i.Reset(); i.AppendPoint(p, s.QuatDir); } } } void TransformAwake(ContainerState s) { pwp = Vector3.zero; cpt = s.ScreenPoint; ptime = s.Time; Position = pwp + cpt + spos; Rotation = Quaternion.Euler(s.Direction); } Vector3 cpt; // Current point Vector3 ppt = Vector3.zero; // Previous point Vector3 pwp = Vector3.zero; // Previous world point double ptime; // Previous time float length; public override void Update(ContainerState s, StampedEvent ev) { base.Update(s, ev); if (CanDoGraphicalUpdate(s)) { var tpt = s.ScreenPoint; var tsv = s.ScrollVelocity; Vector3 dpt = (Vector3)tpt - ppt; // Delta 2D point dpt.z = (float)((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; Position = pwp + cpt + spos; Rotation = Quaternion.Euler(s.Direction); if (!RootTransform || s.CloneType == 3) return; foreach (var i in sgos) i.AppendPoint(Position, s.QuatDir); } else UpdatePosition(s); } void UpdatePosition(ContainerState s) { cpt = s.ScreenPoint; ppt = cpt; pwp = Vector3.zero; ptime = s.Time; length = 0; Position = pwp + cpt + spos; Rotation = Quaternion.Euler(s.Direction); } // TODO Fix anchor rotation public override void Anchor() { base.Anchor(); spos = bpos - Position; } protected override void EndGraphicalUpdate(ContainerState s) { base.EndGraphicalUpdate(s); EndUpdatePosition(s); var p = Position; foreach (var i in sgos) { i.AppendPoint(p, s.QuatDir); i.Seal(); } } void EndUpdatePosition(ContainerState s) { var tpt = s.ScreenPoint; var tsv = s.ScrollVelocity; Vector3 dpt = (Vector3)tpt - ppt; dpt.z = (float)((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; Position = pwp + cpt + spos; Rotation = Quaternion.Euler(s.Direction); } } }