Files
crtr/Assets/Cryville/Crtr/TrackHandler.cs
2022-11-21 18:16:12 +08:00

154 lines
3.9 KiB
C#

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(GroupHandler gh, Chart.Track _track) : base() {
track = _track;
this.gh = gh;
}
public override string TypeName {
get {
return "track";
}
}
public override void Init() {
base.Init();
sgos = gogroup.GetComponentsInChildren<SectionalGameObject>();
}
SectionalGameObject[] sgos;
Vector3 bpos; Quaternion brot;
Vector3 spos;
protected override void PreAwake(ContainerState s) {
base.PreAwake(s);
pwp = Vector3.zero;
cpt = s.ScreenPoint;
ptime = s.Time;
if (s.CloneType == 2) {
#if UNITY_5_6_OR_NEWER
a_head.SetPositionAndRotation(GetCurrentWorldPoint(), Quaternion.Euler(s.Direction));
#else
a_head.position = GetCurrentWorldPoint();
a_head.rotation = Quaternion.Euler(s.Direction);
#endif
}
else if (s.CloneType == 3) {
spos = Vector3.zero;
bpos = cpt;
brot = Quaternion.Euler(s.Direction);
}
}
protected override void Awake(ContainerState s) {
base.Awake(s);
if (!gogroup) return;
var p = GetCurrentWorldPoint();
foreach (var i in sgos) {
i.Reset();
i.AppendPoint(p, s.QuatDir);
}
}
Vector3 cpt; // Current point
Vector3 ppt = Vector3.zero; // Previous point
Vector3 pwp = Vector3.zero; // Previous world point
float ptime; // Previous time
float length;
public override void Update(ContainerState s, StampedEvent ev) {
base.Update(s, ev);
if (s.CloneType == 2 || s.CloneType == 3) {
var tpt = s.ScreenPoint;
var tsv = s.ScrollVelocity;
Vector3 dpt = (Vector3)tpt - ppt; // Delta 2D point
dpt.z = (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;
if (!gogroup || s.CloneType == 3) return;
var p = GetCurrentWorldPoint();
foreach (var i in sgos)
i.AppendPoint(p, s.QuatDir);
}
else UpdatePosition(s);
}
void UpdatePosition(ContainerState s) {
cpt = s.ScreenPoint;
ppt = cpt;
pwp = Vector3.zero;
ptime = s.Time;
length = 0;
// Logger.LogFormat("main", 0, "Debug", "SV: {0}", cs.GetRawValue<Vec1m>("svm").Value);
}
// TODO Fix anchor rotation
public override void Anchor() {
base.Anchor();
spos = bpos - GetCurrentWorldPoint();
}
public override void EndUpdate(ContainerState s) {
OpenAnchor("tail");
base.EndUpdate(s);
CloseAnchor("tail");
if (s.CloneType == 0 || s.CloneType == 2) {
EndUpdatePosition(ts);
var p = GetCurrentWorldPoint();
foreach (var i in sgos) {
i.AppendPoint(p, s.QuatDir);
i.Seal();
}
#if UNITY_5_6_OR_NEWER
a_tail.SetPositionAndRotation(GetCurrentWorldPoint(), Quaternion.Euler(ts.Direction));
#else
a_tail.position = GetCurrentWorldPoint();
a_tail.rotation = Quaternion.Euler(ts.Direction);
#endif
}
else if (s.CloneType == 3) EndUpdatePosition(ns);
else if (s.CloneType >= 16) EndUpdatePosition(ps);
}
void EndUpdatePosition(ContainerState s) {
var tpt = s.ScreenPoint;
var tsv = s.ScrollVelocity;
Vector3 dpt = (Vector3)tpt - ppt;
dpt.z = (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;
}
public Vector3 GetCurrentWorldPoint() {
return pwp + cpt + spos;
}
}
}