Files
crtr/Assets/Cryville/Crtr/Event/NoteHandler.cs

155 lines
4.8 KiB
C#

using Cryville.Common;
using Cryville.Crtr.Ruleset;
using Cryville.Crtr.Skin.Components;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Event {
public class NoteHandler : ContainerHandler {
readonly GroupHandler gh;
readonly Chart.Note _note;
public NoteHandler(Chart.Note ev, GroupHandler gh) : base() {
_note = ev;
this.gh = gh;
}
public override string TypeName { get { return "note"; } }
SectionalGameObject[] sgos;
readonly Dictionary<Chart.Judge, JudgeState> judges = new();
class JudgeState {
static readonly int _var_judge_result = IdentifierManager.Shared.Request("judge_result");
static readonly int _var_judge_time_absolute = IdentifierManager.Shared.Request("judge_time_absolute");
static readonly int _var_judge_time_relative = IdentifierManager.Shared.Request("judge_time_relative");
public Anchor StaticAnchor { get; private set; }
readonly PropStores.Float _jtabsst = new();
readonly PropStores.Float _jtrelst = new();
readonly PropStores.Identifier _resultst = new();
public JudgeState(NoteHandler handler, int name) {
StaticAnchor = handler.RegisterAnchor(handler.judge.judgeMap[name], false, 3);
}
public void MarkJudged(float abs, float rel, int result) {
_jtabsst.Value = abs;
_jtrelst.Value = rel;
_resultst.Value = result;
}
public void InitPropSrcs() {
StaticAnchor.PropSrcs.Add(_var_judge_result, _resultst.Source);
StaticAnchor.PropSrcs.Add(_var_judge_time_absolute, _jtabsst.Source);
StaticAnchor.PropSrcs.Add(_var_judge_time_relative, _jtrelst.Source);
}
}
public override void PreInit() {
base.PreInit();
foreach (var j in _note.judges) {
judges.Add(j, new JudgeState(this, j.Id.Key));
}
}
public override void Init() {
base.Init();
sgos = RootTransform.GetComponentsInChildren<SectionalGameObject>();
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 (_note.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 && _note.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 => th.Handler.Rotation * Vector3.forward);
return Quaternion.LookRotation(r, state.Normal);
}
Vector3 GetFrame(ContainerState state, float track, Func<ContainerState, Vector3> func) {
// TODO
int id = Mathf.FloorToInt(track);
if (track == id) {
var ts0 = state.GetChild(id, typeof(Chart.Track));
var p1 = func(ts0);
return p1;
}
return gh.GetCurrentFrame(func, track);
}
internal void ReportJudge(JudgeEvent ev, float time, Identifier result) {
if (!judges.TryGetValue(ev.BaseEvent, out JudgeState state)) return;
state.MarkJudged(time, (float)(ev.StartTime - time), result.Key);
}
}
}