using Cryville.Common; using Cryville.Crtr.Components; using Cryville.Crtr.Event; using System; using System.Collections.Generic; using UnityEngine; namespace Cryville.Crtr { public class NoteHandler : ContainerHandler { readonly GroupHandler gh; public readonly Chart.Note Event; public NoteHandler(Chart.Note ev, GroupHandler gh) : base() { Event = ev; this.gh = gh; } public override string TypeName { get { return "note"; } } SectionalGameObject[] sgos; readonly Dictionary judges = new Dictionary(); class JudgeState { static readonly int _var_judge_result = IdentifierManager.SharedInstance.Request("judge_result"); static readonly int _var_judge_time_absolute = IdentifierManager.SharedInstance.Request("judge_time_absolute"); static readonly int _var_judge_time_relative = IdentifierManager.SharedInstance.Request("judge_time_relative"); public Anchor StaticAnchor { get; private set; } public float AbsoluteTime { get; private set; } PropSrc _jtabsPropSrc; public float RelativeTime { get; private set; } PropSrc _jtrelPropSrc; public int Result { get; private set; } PropSrc _resultPropSrc; public JudgeState(NoteHandler handler, int name) { StaticAnchor = handler.RegisterAnchor(handler.judge.judgeMap[name], false, 3); } public void MarkJudged(float abs, float rel, int result) { AbsoluteTime = abs; RelativeTime = rel; Result = result; _jtabsPropSrc.Invalidate(); _jtrelPropSrc.Invalidate(); _resultPropSrc.Invalidate(); } public void InitPropSrcs() { StaticAnchor.PropSrcs.Add(_var_judge_result, _resultPropSrc = new PropSrc.Identifier(() => Result)); StaticAnchor.PropSrcs.Add(_var_judge_time_absolute, _jtabsPropSrc = new PropSrc.Float(() => AbsoluteTime)); StaticAnchor.PropSrcs.Add(_var_judge_time_relative, _jtrelPropSrc = new PropSrc.Float(() => RelativeTime)); } } public override void PreInit() { base.PreInit(); foreach (var j in Event.judges) { judges.Add(j, new JudgeState(this, j.Id.Key)); } } public override void Init() { base.Init(); sgos = RootTransform.GetComponentsInChildren(); foreach (var judge in judges) judge.Value.InitPropSrcs(); } public override void StartPhysicalUpdate(ContainerState s) { base.StartPhysicalUpdate(s); if (s.CloneType == 2) { TransformAwake(s); } } protected override void StartGraphicalUpdate(ContainerState s) { base.StartGraphicalUpdate(s); TransformAwake(s); if (RootTransform) { if (Event.IsLong) { foreach (var i in sgos) { i.Reset(); i.AppendPoint(Position, Rotation); } } else { #if UNITY_5_6_OR_NEWER RootTransform.SetPositionAndRotation(Position, Rotation); #else RootTransform.position = Position; RootTransform.rotation = Rotation; #endif } } } void TransformAwake(ContainerState s) { Position = GetFramePoint(s.Parent, s.Track); Rotation = GetFrameRotation(s.Parent, s.Track); } public override void Update(ContainerState s, StampedEvent ev) { if (s.CloneType <= 2) { Position = GetFramePoint(s.Parent, s.Track); Rotation = GetFrameRotation(s.Parent, s.Track); if (s.CloneType == 2 && RootTransform && Event.IsLong) { foreach (var i in sgos) i.AppendPoint(Position, Rotation); } } else if (s.CloneType == 16) { if (ev == null) { } else if (ev.Unstamped == null) { } else if (ev.Unstamped is Chart.Judge) { judge._etor.ContextEvent = ev.Unstamped; judge._etor.ContextState = s; judge.Prepare(ev, this); judge._etor.ContextState = null; judge._etor.ContextEvent = null; } } if (s.CloneType == 2 && ev != null && ev.Unstamped is Chart.Judge) { var anchor = judges[(Chart.Judge)ev.Unstamped].StaticAnchor; #if UNITY_5_6_OR_NEWER anchor.Transform.SetPositionAndRotation(Position, Rotation); #else anchor.Transform.position = Position; anchor.Transform.rotation = Rotation; #endif OpenAnchor(anchor); base.Update(s, ev); CloseAnchor(); } else base.Update(s, ev); } protected override void EndGraphicalUpdate(ContainerState s) { if (RootTransform) { foreach (var i in sgos) i.Seal(); } base.EndGraphicalUpdate(s); } Vector3 GetFramePoint(ContainerState state, float track) { return GetFrame(state, track, th => th.Handler.Position); } 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; return gh.GetCurrentFrame(func, track); } public void ReportJudge(Judge.JudgeEvent ev, float time, Identifier result) { JudgeState state; if (!judges.TryGetValue(ev.BaseEvent, out state)) return; state.MarkJudged(time, (float)(ev.StartTime - time), result.Key); } } }