using Cryville.Common.Math; using Cryville.Crtr.Components; using Cryville.Crtr.Event; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Cryville.Crtr { class NoteHandler : ContainerHandler { readonly GroupHandler gh; public readonly Chart.Note Event; readonly Judge judge; public NoteHandler(GroupHandler gh, Chart.Note ev, Judge j) : base() { this.gh = gh; Event = ev; judge = j; } public override string TypeName { get { return "note"; } } /*public override void Dispose() { base.Dispose(); for (int i = notePool.Count - 1; i >= 0; i--) { var t = notePool.ElementAt(i); GameObject.Destroy(t.Value); } }*/ //Dictionary notePool = new Dictionary(); // Trail trail; SectionalGameObject[] sgos; public override void Init() { base.Init(); sgos = gogroup.GetComponentsInChildren(); } protected override void PreAwake(ContainerState s) { base.PreAwake(s); /*var attev = StampedEvent.AttackEvent; if (attev != null) { GameObject headObj = null; bool pooledh = notePool.TryGetValue(attev, out headObj); if (pooledh) GameObject.Destroy(headObj); }*/ #if UNITY_5_6_OR_NEWER a_head.SetPositionAndRotation(Position = GetFramePoint(s.Parent, s.Track), Rotation = GetFrameRotation(s.Parent, s.Track)); #else a_head.position = Position = GetFramePoint(s.Parent, s.Track); a_head.rotation = Rotation = GetFrameRotation(s.Parent, s.Track); #endif } protected override void Awake(ContainerState s) { base.Awake(s); if (!gogroup) return; Chart.Note tev = Event; if (tev.IsLong) { foreach (var i in sgos) { i.Reset(); i.AppendPoint(Position, Rotation); } } else { #if UNITY_5_6_OR_NEWER gogroup.SetPositionAndRotation(Position, Rotation); #else gogroup.position = Position; gogroup.rotation = Rotation; #endif } } readonly Dictionary phMotions = new Dictionary(); bool invalidated = false; readonly List patchedJudgeEvents = new List(); public override void StartUpdate(ContainerState s) { base.StartUpdate(s); if (s.CloneType == 16 && Event.judge != null) { // var etor = new Evaluator(); //CompiledRuleset.PatchJudge(Event, ChartPlayer.cruleset.primary_judges[Event.judge], s.Time, etor, patchedJudgeEvents, !Event.@long); } } public override void Update(ContainerState s, StampedEvent ev) { base.Update(s, ev); if (s.CloneType == 1) { Position = GetFramePoint(bs.Parent, bs.Track); Rotation = GetFrameRotation(bs.Parent, bs.Track); } else if (s.CloneType == 2) { /*for (int i = notePool.Count - 1; i >= 0; i--) { var t = notePool.ElementAt(i); var eev = t.Key; var rev = t.Key.ReleaseEvent; if (rev != null) { eev = rev; } if (eev.Time < cs.Time) { GameObject.Destroy(t.Value); notePool.Remove(t.Key); } }*/ Position = GetFramePoint(ts.Parent, ts.Track); Rotation = GetFrameRotation(ts.Parent, ts.Track); if (!gogroup) return; // sgos = gogroup.GetComponentsInChildren(); Chart.Note tev = Event; if (tev.IsLong) { foreach (var i in sgos) i.AppendPoint(Position, Rotation); } /*else { gogroup.position = p; gogroup.rotation = Quaternion.Euler(ts.Direction); }*/ } else if (s.CloneType == 16) { if (ev == null) { } else if (ev.Unstamped == null) { } else if (ev.Unstamped is Chart.Motion) { var tev = (Chart.Motion)ev.Unstamped; if (tev.Name.MainName != "judge") return; phMotions.Add(tev, (Vec1)s.GetRawValue(tev.Name).Clone()); } else if (ev.Unstamped is InstantEvent) { var oev = ((InstantEvent)ev.Unstamped).Original; if (oev is Chart.Motion) { var tev = (Chart.Motion)oev; if (tev.Name.MainName != "judge") return; var v0 = phMotions[tev]; var v1 = s.GetRawValue(tev.Name); // var etor = new Evaluator(); for (var vi = Mathf.Ceil(v0.Value); vi < v1.Value; vi++) { var v = new Vec1(vi); var t = MotionLerper.Delerp(v, ev.Time, v1, ev.Origin.Time, v0, tev.transition, tev.rate); /*CompiledRuleset.PatchJudge( Event, ChartPlayer.cruleset.primary_judges[tev.Name.SubName], t, etor, patchedJudgeEvents );*/ } phMotions.Remove(tev); } } } } public override void ExUpdate(ContainerState s, StampedEvent ev) { base.ExUpdate(s, ev); if (ev is StampedEvent.Judge) { var tev = (StampedEvent.Judge)ev; if (tev.TargetJudge != null && s.CloneType == 0 && !invalidated) { //judge.Issue(tev, this); } else if (tev.TargetJudge == null && s.CloneType == 17) { //judge.RecordPos(tev.StartEvent, GetFramePoint(s.Parent, s.Track)); } else return; patchedJudgeEvents.Remove(tev); // Logger.Log("main", 0, "Judge", "ir {0}", patchedJudgeEvents.Count); } } public override void MotionUpdate(byte ct, Chart.Motion ev) { base.MotionUpdate(ct, ev); if (ct == 0) { if (ev.Name.MainName == "judge") { if (invalidated) return; if (ev.Name.SubName == null) throw new InvalidOperationException(); // judge.IssueImmediate(this, ev.Name.SubName, GetFramePoint(cs.Parent, cs.Track)); } } else if (ct == 16) { /*var etor = new EvalImpl(); if (ev.MotionName == "judge") { if (ev.MotionSubName == null) throw new InvalidOperationException(); var l = new List(); float t = ps.Time; CompiledRuleset.PatchJudge( Event, ChartPlayer.cruleset.primary_judges[ev.MotionSubName], t, etor, ref l ); cs.Bus.IssueEventPatch(l); }*/ } } public override void EndUpdate(ContainerState s) { if (s.CloneType == 0 || s.CloneType == 2) { if (!gogroup) goto return_ahead; // sgos = gogroup.GetComponentsInChildren(); foreach (var i in sgos) i.Seal(); #if UNITY_5_6_OR_NEWER a_tail.SetPositionAndRotation(GetFramePoint(ts.Parent, ts.Track), Quaternion.Euler(ts.Direction)); #else a_tail.position = GetFramePoint(ts.Parent, ts.Track); a_tail.rotation = Quaternion.Euler(ts.Direction); #endif } else if (s.CloneType == 16) { if (Event.endjudge != null) { //var etor = new Evaluator(); //CompiledRuleset.PatchJudge(Event, ChartPlayer.cruleset.primary_judges[Event.endjudge], ps.Time, etor, patchedJudgeEvents, true); } cs.Bus.IssuePatch(patchedJudgeEvents.Cast()); } return_ahead: OpenAnchor("tail"); base.EndUpdate(s); CloseAnchor("tail"); } Vector3 GetFramePoint(ContainerState state, float track) { return GetFrame(state, track, th => ((TrackHandler)th.Handler).GetCurrentWorldPoint()); } Quaternion GetFrameRotation(ContainerState state, float track) { var r = GetFrame(state, track, th => Quaternion.Euler(th.Direction) * Vector3.forward); return Quaternion.LookRotation(r, state.Normal); } Vector3 GetFrame(ContainerState state, float track, Func func) { // TODO int id = Mathf.FloorToInt(track); var ts0 = state.GetChild(id, typeof(Chart.Track)); var p1 = func(ts0); if (track == id) return p1; var ts1 = state.GetChild(id + 1, typeof(Chart.Track)); var p2 = func(ts1); bool c0 = ts0.Corner; bool c1 = ts1.Corner; float t = track - id; float deltaz = p2.z - p1.z; float nt = 1 - t; if (c0 && c1) return (1 - t) * p1 + t * p2; else { var ctrl = new List(2); if (!c0) { var tp = ts0.GetControlPoint(true, deltaz); if (tp != Vector3.zero) ctrl.Add(tp); } if (!c1) { var tp = ts1.GetControlPoint(false, -deltaz); if (tp != Vector3.zero) ctrl.Add(tp); } if (ctrl.Count == 0) { /* // Early algorithm Vector3 m0, m1; bool flag0 = id == 0; bool flag1 = id == state.Children.Where(i => i.Key.Event is Chart.Track).Count() - 2; if (flag0 && flag1) // Only two tracks exist return (1 - t) * p1 + t * p2; else { Vector3 p0, p3; if (!flag1) p3 = ((TrackHandler)tl.ElementAt(id + 2).Value.Handler).GetCurrentWorldPoint(); if (!flag0) p0 = ((TrackHandler)tl.ElementAt(id - 1).Value.Handler).GetCurrentWorldPoint(); if (flag0) m0 = 2 * (p2-p1).normalized - (p3-p1).normalized; else m0 = 1f*((p1-p0).normalized + (p2-p1).normalized); if (flag1) m1 = 2 * (p2-p1).normalized - (p2-p0).normalized; else m1 = 1f*((p2-p1).normalized + (p3-p2).normalized); return t*t*(2*t-3)*(p1-p2)+p1 + t*(t-1)*((t-1)*m0+t*m1); }*/ var frame = gh.GetCurrentFrame(func); return frame.Dot( ColumnVector.WithPolynomialCoefficients( frame.Size, track ), new Vector3Operator() ); } else if (ctrl.Count == 1) { return nt * (nt * p1 + t * (ctrl[0] + p1)) + t * t * p2; } else { var t2 = t * t; return nt * (nt * (nt * p1 + t * (ctrl[0] + p1)) + t2 * (ctrl[1] + p1)) + t2 * t * p2; } } } public List Invalidate() { invalidated = true; return patchedJudgeEvents; } } }