203 lines
5.9 KiB
C#
203 lines
5.9 KiB
C#
using Cryville.Common;
|
|
using Cryville.Common.Math;
|
|
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;
|
|
readonly PdtRuleset ruleset;
|
|
public NoteHandler(GroupHandler gh, Chart.Note ev, PdtRuleset rs) : base() {
|
|
this.gh = gh;
|
|
Event = ev;
|
|
ruleset = rs;
|
|
}
|
|
|
|
public override string TypeName {
|
|
get {
|
|
return "note";
|
|
}
|
|
}
|
|
|
|
SectionalGameObject[] sgos;
|
|
readonly Dictionary<Chart.Judge, JudgeState> judges = new Dictionary<Chart.Judge, JudgeState>();
|
|
class JudgeState {
|
|
public Anchor AbsoluteAnchor { get; private set; }
|
|
public Anchor RelativeAnchor { get; private set; }
|
|
public bool Judged { get; private set; }
|
|
public float AbsoluteTime { get; private set; }
|
|
public float RelativeTime { get; private set; }
|
|
public JudgeState(NoteHandler handler, int name) {
|
|
AbsoluteAnchor = handler.RegisterAnchor(handler.judge.jtabsMap[name]);
|
|
RelativeAnchor = handler.RegisterAnchor(handler.judge.jtrelMap[name]);
|
|
}
|
|
public void MarkJudged(float abs, float rel) {
|
|
Judged = true;
|
|
AbsoluteTime = abs;
|
|
RelativeTime = rel;
|
|
}
|
|
}
|
|
|
|
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 = gogroup.GetComponentsInChildren<SectionalGameObject>();
|
|
}
|
|
protected override void PreAwake(ContainerState s) {
|
|
base.PreAwake(s);
|
|
#if UNITY_5_6_OR_NEWER
|
|
a_head.Transform.SetPositionAndRotation(Position = GetFramePoint(s.Parent, s.Track), Rotation = GetFrameRotation(s.Parent, s.Track));
|
|
#else
|
|
a_head.Transform.position = Position = GetFramePoint(s.Parent, s.Track);
|
|
a_head.Transform.rotation = Rotation = GetFrameRotation(s.Parent, s.Track);
|
|
#endif
|
|
}
|
|
protected override void Awake(ContainerState s) {
|
|
base.Awake(s);
|
|
if (s.CloneType == 2) {
|
|
if (!gogroup) return;
|
|
if (Event.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
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Update(ContainerState s, StampedEvent ev) {
|
|
base.Update(s, ev);
|
|
if (s.CloneType <= 2) {
|
|
Position = GetFramePoint(s.Parent, s.Track);
|
|
Rotation = GetFrameRotation(s.Parent, s.Track);
|
|
}
|
|
if (s.CloneType == 2) {
|
|
if (!gogroup) return;
|
|
Chart.Note tev = Event;
|
|
if (tev.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) {
|
|
var tev = (Chart.Judge)ev.Unstamped;
|
|
Identifier name = default(Identifier);
|
|
ChartPlayer.etor.ContextEvent = tev;
|
|
ChartPlayer.etor.ContextState = s;
|
|
ChartPlayer.etor.Evaluate(new PropOp.Identifier(v => name = new Identifier(v)), ruleset.judges[tev.Id].input);
|
|
judge.Prepare(ev.Time, ev.Time + ev.Duration, name, tev.Id, this);
|
|
ChartPlayer.etor.ContextState = null;
|
|
ChartPlayer.etor.ContextEvent = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Anchor() {
|
|
base.Anchor();
|
|
if (cs.Working) {
|
|
foreach (var j in judges.Values) {
|
|
if (!j.Judged) continue;
|
|
PushAnchorEvent(j.AbsoluteTime, j.AbsoluteAnchor);
|
|
PushAnchorEvent(j.RelativeTime + cs.Time, j.RelativeAnchor);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void EndUpdate(ContainerState s) {
|
|
if (s.CloneType == 2 && gogroup) {
|
|
foreach (var i in sgos) i.Seal();
|
|
#if UNITY_5_6_OR_NEWER
|
|
a_tail.Transform.SetPositionAndRotation(GetFramePoint(ts.Parent, ts.Track), Quaternion.Euler(ts.Direction));
|
|
#else
|
|
a_tail.Transform.position = GetFramePoint(ts.Parent, ts.Track);
|
|
a_tail.Transform.rotation = Quaternion.Euler(ts.Direction);
|
|
#endif
|
|
}
|
|
OpenAnchor(_a_tail);
|
|
base.EndUpdate(s);
|
|
CloseAnchor(_a_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);
|
|
}
|
|
|
|
readonly List<Vector3> ctrl = new List<Vector3>(2);
|
|
Vector3 GetFrame(ContainerState state, float track, Func<ContainerState, Vector3> 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 {
|
|
ctrl.Clear();
|
|
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) {
|
|
var frame = gh.GetCurrentFrame(func);
|
|
return frame.Dot(
|
|
ColumnVector<float>.WithPolynomialCoefficients(
|
|
frame.Size, track
|
|
),
|
|
Vector3Operator.Instance
|
|
);
|
|
}
|
|
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 void ReportJudge(Judge.JudgeEvent ev, float time, Identifier result) {
|
|
JudgeState state;
|
|
if (!judges.TryGetValue(ev.BaseEvent, out state)) return;
|
|
state.MarkJudged(time, (float)(time - cs.Time));
|
|
}
|
|
}
|
|
}
|