Add project files.

This commit is contained in:
2022-09-30 17:32:21 +08:00
parent df69e65c88
commit e8e36b83bd
561 changed files with 40626 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
using Cryville.Crtr.Components;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Event {
public abstract class ContainerHandler : IDisposable {
/// <summary>
/// Prehandling <see cref="ContainerState"/>, prehandling the events.
/// </summary>
public ContainerState ps;
/// <summary>
/// Backward <see cref="ContainerState"/>, disposing events at the backward clipping plane, firing anchor state and temporary state.
/// </summary>
public ContainerState bs;
/// <summary>
/// Current <see cref="ContainerState"/>, handling events occuring at the current time.
/// </summary>
public ContainerState cs;
/// <summary>
/// Anchor <see cref="ContainerState"/>, computing the start position of the temporary state.
/// </summary>
public ContainerState ns;
/// <summary>
/// Temporary <see cref="ContainerState"/>, rendering events between the clipping planes.
/// </summary>
public ContainerState ts;
/// <summary>
/// <see cref="GameObject"/> group, the <see cref="Transform"/> containing all the generated elements in the <see cref="ContainerHandler"/>.
/// </summary>
public Transform gogroup;
public readonly Dictionary<string, Anchor> Anchors = new Dictionary<string, Anchor>();
public Transform a_head;
public Transform a_tail;
public Vector3 Position {
get;
protected set;
}
public Quaternion Rotation {
get;
protected set;
}
public bool Alive {
get;
private set;
}
public bool Awoken {
get;
private set;
}
public bool Disposed {
get;
private set;
}
public EventContainer Container {
get { return cs.Container; }
}
public ContainerHandler() { }
public abstract string TypeName {
get;
}
public virtual void PreInit() {
gogroup = new GameObject(TypeName + ":" + Container.GetHashCode().ToString()).transform;
if (cs.Parent != null)
gogroup.SetParent(cs.Parent.Handler.gogroup, false);
a_head = new GameObject("::head").transform;
a_head.SetParent(gogroup, false);
Anchors.Add("head", new Anchor() { Transform = a_head });
a_tail = new GameObject("::tail").transform;
a_tail.SetParent(gogroup, false);
Anchors.Add("tail", new Anchor() { Transform = a_tail });
}
/// <summary>
/// Called upon initialization of <see cref="cs" />.
/// </summary>
public virtual void Init() {
cs.skinContainer.MatchStatic(cs);
foreach (var i in gogroup.GetComponentsInChildren<SkinComponent>())
i.Init();
}
public virtual void PostInit() {
gogroup.gameObject.SetActive(false);
}
public virtual void Dispose() {
if (Disposed) return;
Disposed = true;
if (gogroup)
GameObject.Destroy(gogroup.gameObject);
// gogroup.gameObject.SetActive(false);
Alive = false;
}
protected virtual void PreAwake(ContainerState s) {
if (gogroup) gogroup.gameObject.SetActive(true);
Awoken = true; Alive = true;
OpenAnchor("head");
}
protected virtual void Awake(ContainerState s) {
CloseAnchor("head");
}
protected virtual void GetPosition(ContainerState s) { }
public virtual void StartUpdate(ContainerState s) {
if (s.CloneType >= 2 && s.CloneType < 16) {
PreAwake(s);
Awake(s);
}
}
public virtual void Update(ContainerState s, StampedEvent ev) {
bool flag = !Awoken && s.CloneType >= 2 && s.CloneType < 16;
if (flag) PreAwake(s);
if (Awoken && s.CloneType <= 2) if (gogroup) cs.skinContainer.MatchDynamic(s);
if (flag) Awake(s);
}
public virtual void ExUpdate(ContainerState s, StampedEvent ev) { }
public virtual void MotionUpdate(byte ct, Chart.Motion ev) { }
public virtual void EndUpdate(ContainerState s) {
if (s.CloneType < 16) {
Awoken = false;
if (gogroup && s.CloneType <= 2) cs.skinContainer.MatchDynamic(s);
}
}
public virtual void Anchor() { }
protected void OpenAnchor(string name) {
if (Anchors.ContainsKey(name)) Anchors[name].Open();
}
protected void CloseAnchor(string name) {
if (Anchors.ContainsKey(name)) Anchors[name].Close();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: da65ca35eb403a94ab9a1e07f7b3100c
timeCreated: 1617788981
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,485 @@
//#define DISABLE_CACHE
using Cryville.Common;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Event {
public class ContainerState {
public EventBus Bus;
public EventContainer Container;
public ContainerState Parent = null;
public ushort Depth;
public Dictionary<EventContainer, ContainerState> Children
= new Dictionary<EventContainer, ContainerState>();
HashSet<EventContainer> WorkingChildren
= new HashSet<EventContainer>();
HashSet<EventContainer> InvalidatedChildren
= new HashSet<EventContainer>();
public Dictionary<Type, List<ContainerState>> TypedChildren
= new Dictionary<Type, List<ContainerState>>();
public ContainerState GetChild(int index, Type handlerType) {
return TypedChildren[handlerType][index];
}
public ContainerState GetChild(EventContainer ev) {
/*if (!Children.ContainsKey(ev)) {
Children[ev] = prototype.FetchChildClone(ev, CloneType);
}*/
return Children[ev];
}
/*ContainerState FetchChildClone(EventContainer ev, byte ct) {
return Children[ev].Clone(ct);
}*/
void NotifyWorkingChanged(EventContainer key) {
InvalidatedChildren.Add(key);
}
void ValidateChildren() {
foreach (var cev in InvalidatedChildren)
if (Children[cev].Working && !WorkingChildren.Contains(cev)) WorkingChildren.Add(cev);
else if (!Children[cev].Working && WorkingChildren.Contains(cev)) WorkingChildren.Remove(cev);
InvalidatedChildren.Clear();
}
private bool m_Working;
public bool Working {
get { return m_Working; }
set {
m_Working = value;
if (Parent != null) Parent.NotifyWorkingChanged(Container);
Bus.NotifyWorkingChanged(this);
}
}
public byte CloneType;
private ContainerState rootPrototype = null;
private ContainerState prototype = null;
// public SkinManager skinManager;
public SkinContainer skinContainer;
public Judge judge;
public ContainerHandler Handler {
get;
private set;
}
public float Time {
get {
return Bus.Time;
}
}
readonly RMVPool RMVPool = new RMVPool();
protected Dictionary<StampedEvent, RealtimeMotionValue> PlayingMotions = new Dictionary<StampedEvent, RealtimeMotionValue>();
protected Dictionary<MotionName, RealtimeMotionValue> Values = new Dictionary<MotionName, RealtimeMotionValue>();
protected Dictionary<MotionName, Vector> CachedValues = new Dictionary<MotionName, Vector>();
protected Dictionary<MotionName, bool> CachedValueStates = new Dictionary<MotionName, bool>();
/// <summary>
/// Gets a motion value.
/// </summary>
/// <param name="name">The motion name.</param>
/// <param name="clone">Returns a cloned motion value instead.</param>
/// <returns>A motion value.</returns>
RealtimeMotionValue GetMotionValue(MotionName name, bool clone = false) {
RealtimeMotionValue value;
if (!Values.TryGetValue(name, out value)) {
value = new RealtimeMotionValue().Init(Parent == null
? ChartPlayer.motionRegistry[name.MainName].GlobalInitValue
: ChartPlayer.motionRegistry[name.MainName].InitValue
);
Values.Add(name, value);
}
if (clone) return value.Clone();
return value;
}
void InvalidateMotion(MotionName name) {
// if (CachedValues.ContainsKey(name))
CachedValueStates[name] = false;
foreach (var c in Children)
c.Value.InvalidateMotion(name);
}
public ContainerState(Chart c, EventContainer _ev, ContainerState parent = null) {
Container = _ev;
if (parent != null) {
AddChild(_ev, this, parent);
Parent = parent;
}
foreach (var m in ChartPlayer.motionRegistry)
Values.Add(new MotionName(m.Key), new RealtimeMotionValue().Init(Parent == null ? m.Value.GlobalInitValue : m.Value.InitValue));
//skinManager = new SkinManager(skin, this);
//events.Sort((a, b) => a.Time.CompareTo(b.Time));
}
static void AddChild(EventContainer c, ContainerState s, ContainerState target) {
target.Children.Add(c, s);
Type t = c.GetType();
if (!target.TypedChildren.ContainsKey(t)) target.TypedChildren.Add(t, new List<ContainerState>());
target.TypedChildren[t].Add(s);
}
public ContainerState Clone(byte ct) {
/*if (prototype != null)
throw new InvalidOperationException();*/
var r = (ContainerState)MemberwiseClone();
var mvs = new Dictionary<MotionName, RealtimeMotionValue>(Values.Count);
foreach (var mv in Values) {
mvs.Add(mv.Key, mv.Value.Clone());
}
r.Values = mvs;
var cvs = new Dictionary<MotionName, Vector>(CachedValues.Count);
foreach (var cv in CachedValues) {
cvs.Add(cv.Key, cv.Value.Clone());
}
r.CachedValues = cvs;
var cvss = new Dictionary<MotionName, bool>(CachedValueStates.Count);
foreach (var cv in CachedValueStates) {
cvss.Add(cv.Key, cv.Value);
}
r.CachedValueStates = cvss;
r.Children = new Dictionary<EventContainer, ContainerState>();
foreach (var child in Children) {
// if (!child.Value.Working && ct != 1) continue;
var cc = child.Value.Clone(ct);
cc.Parent = r;
AddChild(child.Key, cc, r);
}
var pms = new Dictionary<StampedEvent, RealtimeMotionValue>(PlayingMotions.Count);
foreach (var m in PlayingMotions)
pms.Add(m.Key, m.Value);
r.PlayingMotions = pms;
if (ct == 1) Handler.bs = r;
else if (ct == 2) Handler.ts = r;
else if (ct == 3) Handler.ns = r;
else if (ct >= 16) Handler.ps = r;
else throw new InvalidOperationException("Invalid clone type");
r.prototype = this;
if (prototype == null) r.rootPrototype = this;
else r.rootPrototype = rootPrototype;
r.CloneType = ct;
return r;
}
public void CopyTo(byte ct, ContainerState dest) {
dest.Working = Working;
foreach (var mv in Values) {
RealtimeMotionValue dv;
if (dest.Values.TryGetValue(mv.Key, out dv)) mv.Value.CopyTo(dv);
else dest.Values.Add(mv.Key, mv.Value.Clone());
}
// dest.CachedValues.Clear();
foreach (var cv in CachedValues) {
Vector dv;
if(dest.CachedValues.TryGetValue(cv.Key, out dv)) cv.Value.CopyTo(dv);
else dest.CachedValues.Add(cv.Key, cv.Value.Clone());
}
foreach (var cvs in CachedValueStates) dest.CachedValueStates[cvs.Key] = cvs.Value;
if (ct != 1) foreach (var cev in WorkingChildren)
Children[cev].CopyTo(ct, dest.Children[cev]);
else foreach (var child in Children)
child.Value.CopyTo(ct, dest.Children[child.Key]);
ValidateChildren();
RMVPool.ReturnAll();
dest.PlayingMotions.Clear();
foreach (var m in PlayingMotions) dest.PlayingMotions.Add(m.Key, m.Value);
}
public bool Disposed {
get;
private set;
}
public void Dispose() {
if (Disposed) return;
Disposed = true;
if (Handler != null) Handler.Dispose();
foreach (var s in Children)
s.Value.Dispose();
RMVPool.ReturnAll();
}
public void AttachHandler(ContainerHandler h) {
if (Handler != null)
throw new InvalidOperationException();
Handler = h;
h.cs = this;
}
public void AttachSystems(PdtSkin skin, Judge judge) {
// skinManager = new SkinManager(skin);
skinContainer = new SkinContainer(skin);
this.judge = judge;
}
public T GetRawValue<T>(MotionName key) where T : Vector {
Vector tr;
if (!CachedValues.TryGetValue(key, out tr)) {
tr = (Vector)ReflectionHelper.InvokeEmptyConstructor(typeof(T));
CachedValues.Add(key, tr);
CachedValueStates[key] = false;
}
T r = (T)tr;
#if !DISABLE_CACHE
if (CachedValueStates[key]) return r;
#endif
float reltime = 0;
if (rootPrototype != null) reltime = Time - rootPrototype.Time;
GetMotionValue(key).GetValue(reltime, ref r);
if (Parent != null) r.ApplyFrom(Parent.GetRawValue<T>(key));
#if !DISABLE_CACHE
CachedValueStates[key] = true;
#endif
return r;
}
static readonly MotionName n_dir = new MotionName("dir");
public Vector3 Direction {
get {
Vec3 r = GetRawValue<Vec3>(n_dir);
return r.ToVector3();
}
}
static readonly MotionName n_normal = new MotionName("normal");
public Vector3 Normal {
get {
Vec3 r = GetRawValue<Vec3>(n_normal);
return r.ToVector3();
}
}
public Quaternion QuatDir {
get {
return Quaternion.LookRotation(Quaternion.Euler(Direction) * Vector3.forward, Normal);
}
}
static readonly MotionName n_pt = new MotionName("pt");
public Vector2 ScreenPoint {
get {
var mv = GetRawValue<VecPt>(n_pt);
return mv.ToVector2(ChartPlayer.hitRect);
}
}
static readonly MotionName n_visible = new MotionName("visible");
public bool Visible {
get {
return GetRawValue<VecI1>(n_visible).Value % 2 >= 1;
}
}
static readonly MotionName n_sv = new MotionName("sv");
static readonly MotionName n_svm = new MotionName("svm");
public float ScrollVelocity {
get {
return GetRawValue<VecPtComp>(n_sv).ToFloat(ChartPlayer.hitRect)
* GetRawValue<Vec1m>(n_svm).Value;
}
}
static readonly MotionName n_dist = new MotionName("dist");
public float Distance {
get {
var mv = GetRawValue<VecPtComp>(n_dist);
return mv.ToFloat(ChartPlayer.hitRect);
}
}
static readonly MotionName n_corner = new MotionName("corner");
public bool Corner {
get {
return GetRawValue<VecI1>(n_corner).Value % 2 >= 1;
}
}
static readonly MotionName n_ctrl0 = new MotionName("ctrl0");
static readonly MotionName n_ctrl1 = new MotionName("ctrl1");
public Vector3 GetControlPoint(bool alt1, float deltaz) {
var mv = GetRawValue<VecCtrl>(alt1 ? n_ctrl1 : n_ctrl0);
if (alt1 && mv.IsZero()) {
mv = GetRawValue<VecCtrl>(n_ctrl0);
}
return mv.ToVector3(ChartPlayer.hitRect, deltaz);
}
static readonly MotionName n_track = new MotionName("track");
public float Track {
get {
return GetRawValue<Vec1>(n_track).Value;
}
}
bool breakflag = false;
public void Break() {
Handler.EndUpdate(this);
breakflag = true;
Working = false;
}
public void Handle(StampedEvent ev, Action<StampedEvent> callback = null) {
if (breakflag) {
// Time = toTime;
return;
}
if (ev != null) {
bool flag = false;
if (ev.Unstamped is Chart.Motion) {
var tev = (Chart.Motion)ev.Unstamped;
// tev._apply(Values);
var mv = RMVPool.Rent(tev.Name);
GetMotionValue(tev.Name).CopyTo(mv);
PlayingMotions.Add(ev, mv);
Callback(ev, callback);
// UpdateMotions();
if (!ev.Unstamped.IsLong)
PlayingMotions.Remove(ev);
}
else if (ev.Unstamped is EventContainer) {
var cev = (EventContainer)ev.Unstamped;
var ccs = GetChild(cev);
ccs.Working = true;
ccs.StartUpdate();
UpdateMotions();
if (!ev.Unstamped.IsLong) {
ccs.Working = false;
ccs.BroadcastEndUpdate();
if (CloneType == 1) ccs.Dispose();
}
}
else if (ev.Unstamped is InstantEvent) {
var tev = (InstantEvent)ev.Unstamped;
if (tev.IsRelease) {
var nev = tev.Original;
if (nev is Chart.Motion) {
// var tnev = (Chart.Motion)nev;
Callback(ev, callback);
// UpdateMotions();
PlayingMotions.Remove(ev.Origin);
}
else if (nev is EventContainer) {
var cev = (EventContainer)ev.Origin.Unstamped;
var ccs = GetChild(cev);
UpdateMotions();
ccs.Working = false;
ccs.BroadcastEndUpdate();
if (CloneType == 1) ccs.Dispose();
}
}
}
if (ev.Unstamped == null) {
Callback(ev, callback);
flag = true;
}
else if (ev.Unstamped.Priority >= 0) {
Callback(ev, callback);
flag = true;
}
if (!flag) Callback(null, callback);
return;
}
// Time = toTime;
Callback(null, callback);
}
void Callback(StampedEvent ev, Action<StampedEvent> callback) {
UpdateMotions();
if (callback != null)
callback(ev);
if (ev == null || ev.Unstamped != null) Handler.Update(this, ev);
else Handler.ExUpdate(this, ev);
/*if (CloneType == 1) {
if (ev == null || ev.Event != null) Handler.Forward(ev);
else Handler.ExUpdate(CloneType, ev);
}
else if (CloneType == 0) {
if (ev == null || ev.Event != null) Handler.Update(ev);
else Handler.ExUpdate(CloneType, ev);
}
else if (CloneType == 2) {
// TODO Do nothing atm
}
else if (CloneType >= 16) {
if (ev == null || ev.Event != null) Handler.PreUpdate(CloneType, ev);
else Handler.ExUpdate(CloneType, ev);
}*/
foreach (var m in PlayingMotions)
Handler.MotionUpdate(CloneType, (Chart.Motion)m.Key.Unstamped);
}
private void UpdateMotions() {
foreach (var m in PlayingMotions) {
var tev = (Chart.Motion)m.Key.Unstamped;
if (tev.RelativeNode != null && CloneType == 2) continue;
var value = GetMotionValue(tev.Name/*, true*/);
InvalidateMotion(tev.Name);
if (m.Key.Duration == 0) {
if (tev.RelativeNode != null) {
value.SetRelativeNode(tev.RelativeNode);
}
else {
value.AbsoluteValue.ReplaceFrom(tev.AbsoluteValue);
}
}
else {
var scaledTime = (Time - m.Key.Time - ChartPlayer.actualRenderStep * tev.sumfix) / m.Key.Duration;
var lerpedTime = MotionLerper.GetEaseTime(scaledTime, tev.transition, tev.rate);
if (tev.RelativeNode != null) {
var target = value.QueryRelativeNode(tev.RelativeNode.Id);
tev.RelativeNode.LerpWith(m.Value.GetRelativeNode(tev.RelativeNode.Id), lerpedTime, ref target);
}
else {
tev.AbsoluteValue.LerpWith(m.Value.AbsoluteValue, lerpedTime, ref value.AbsoluteValue);
}
}
Values[tev.Name] = value;
}
}
public void BroadcastInit() {
Handler.PreInit();
Handler.Init();
foreach (var s in Children) {
s.Value.BroadcastInit();
}
Handler.PostInit();
}
public void StartUpdate() {
Handler.StartUpdate(this);
}
public void BroadcastEndUpdate() {
Handler.EndUpdate(this);
foreach (var ls in Children.Values) {
if (ls.Working) ls.BroadcastEndUpdate();
}
}
public void Anchor() {
Handler.Anchor();
foreach (var ls in Children.Values) {
if (ls.Handler.Alive) ls.Anchor();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a2ebe22dbedf60c4b96dd6ae834a740f
timeCreated: 1617701716
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Cryville.Crtr.Event {
public class EventBatch : IComparable<EventBatch>, IEnumerable<StampedEvent> {
public float Time {
get;
private set;
}
readonly List<StampedEvent> queue = new List<StampedEvent>();
public int Count {
get { return queue.Count; }
}
public EventBatch(float time) {
Time = time;
}
public StampedEvent this[int index] {
get { return queue[index]; }
}
public void Add(StampedEvent ev) {
Enqueue(ev);
}
public void Enqueue(StampedEvent ev) {
int i = queue.BinarySearch(ev);
if (i < 0) queue.Insert(~i, ev);
}
public int CompareTo(EventBatch other) {
return this.Time.CompareTo(other.Time);
}
public IEnumerator<StampedEvent> GetEnumerator() {
return queue.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 532772ba68ebf6d49a83a49e9e13cbdd
timeCreated: 1617673011
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Cryville.Crtr.Event {
public class EventBatcher : StateBase<ChartEvent> {
public EventBus Bus {
get;
private set;
}
ContainerState RootState;
/// <summary>
/// event => the container state that handles the event
/// </summary>
readonly Dictionary<ChartEvent, ContainerState> table
= new Dictionary<ChartEvent, ContainerState>();
public List<StampedEvent> stampedEvents = new List<StampedEvent>();
readonly List<EventBatch> batches = new List<EventBatch>();
float beat;
float tempo;
public EventBatcher(Chart c) : base(c, new List<ChartEvent>()) {
beat = chart.BeatPosition;
tempo = (float)c.sigs[0].tempo;
events.Add(c);
events.Add(c.ReleaseEvent);
AddEventContainer(c);
events.Sort((a, b) => a.BeatPosition.CompareTo(b.BeatPosition));
}
void AddEventContainer(EventContainer c, ContainerState parent = null) {
var cs = new ContainerState(chart, c, parent);
if (parent == null) {
cs.Depth = 0;
RootState = cs;
}
else {
cs.Depth = (ushort)(parent.Depth + 1);
}
foreach (var ev in c.Events) {
if (ev.time == null) {
ev.time = c.time;
if (ev is EventContainer)
ev.endtime = c.endtime;
}
if (ev.IsLong) {
events.Add(ev.ReleaseEvent);
table.Add(ev.ReleaseEvent, cs);
/*if (ev is Chart.Note) {
events.Add(ev.AttackEvent);
}*/
}
events.Add(ev);
table.Add(ev, cs);
if (ev is EventContainer)
AddEventContainer((EventContainer)ev, cs);
}
}
public override void ForwardOnceToTime(float toTime, Action<ChartEvent> callback) {
float toBeat = (float)Math.Round(beat + (toTime - Time) * tempo / 60f, 6);
if (EventId >= events.Count)
goto return_ahead;
float ebeat = events[EventId].BeatPosition;
float etime = (float)Math.Round((ebeat - beat) / tempo * 60f + Time, 6);
if (etime > toTime)
goto return_ahead;
var batch = GetEventBatch();
Time = etime;
beat = ebeat;
bool flag = false;
foreach (var ev in batch) {
EventContainer con = null;
if (table.ContainsKey(ev)) con = table[ev].Container;
var sev = new StampedEvent() {
Time = etime,
Unstamped = ev,
Container = con
};
if (ev is InstantEvent) {
var tev = (InstantEvent)ev;
var pev = stampedEvents.First(tpev => tpev.Unstamped == tev.Original);
pev.Subevents.Add(sev);
sev.Origin = pev;
}
stampedEvents.Add(sev);
if (ev.Priority >= 0) {
if (callback != null) callback(ev);
flag = true;
}
if (ev is Chart.Signature) {
var tev = (Chart.Signature)ev;
if (tev.tempo != null) tempo = (float)tev.tempo;
}
EventId++;
}
if (callback != null && !flag) callback(batch.First());
return;
return_ahead:
Time = toTime;
beat = toBeat;
// foreach (var c in Children) c.ForwardToTime(Time);
if (callback != null) callback(null);
}
IOrderedEnumerable<ChartEvent> GetEventBatch() {
float cbeat = events[EventId].BeatPosition;
int b = EventId;
while (Mathf.Approximately(events[b].BeatPosition, cbeat)) {
b--;
if (b == -1) break;
}
int a = EventId;
while (Mathf.Approximately(events[a].BeatPosition, cbeat)) {
a++;
if (a == events.Count) break;
}
return from ev in events.GetRange(b + 1, a - b - 1) orderby ev.Priority select ev;
}
public EventBus Batch() {
stampedEvents.Sort((a, b) => {
int u = a.CompareTo(b);
if (u != 0) return u;
if (a.Unstamped != null && b.Unstamped != null)
if (table.ContainsKey(a.Unstamped) && table.ContainsKey(b.Unstamped)) {
u = table[a.Unstamped].Depth.CompareTo(table[b.Unstamped].Depth);
if (u != 0) return u;
}
return a.GetHashCode().CompareTo(b.GetHashCode());
});
var cb = new EventBatch(stampedEvents[0].Time);
foreach (var ev in stampedEvents) {
if (ev.Time != cb.Time) {
batches.Add(cb);
cb = new EventBatch(ev.Time);
}
cb.Enqueue(ev);
}
batches.Add(cb);
Bus = new EventBus(chart, RootState, batches);
return Bus;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 494728f9d5dcbd443b5e109420c02d2a
timeCreated: 1617663907
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Event {
public class EventBus : StateBase<EventBatch>, IDisposable {
EventBus prototype = null;
public ContainerState RootState {
get;
private set;
}
Dictionary<EventContainer, ContainerState> states
= new Dictionary<EventContainer, ContainerState>();
List<EventContainer> activeContainers
= new List<EventContainer>();
HashSet<ContainerState> workingStates
= new HashSet<ContainerState>();
HashSet<ContainerState> invalidatedStates
= new HashSet<ContainerState>();
public EventBus(Chart c, ContainerState root, List<EventBatch> b)
: base(c, b) {
RootState = root;
Expand();
AttachBus();
RootState.Working = true;
}
public EventBus Clone(byte ct, float offsetTime = 0) {
var r = (EventBus)MemberwiseClone();
r.prototype = this;
r.states = new Dictionary<EventContainer, ContainerState>();
r.activeContainers = new List<EventContainer>();
r.workingStates = new HashSet<ContainerState>();
r.invalidatedStates = new HashSet<ContainerState>();
r.Time += offsetTime;
r.RootState = RootState.Clone(ct);
r.Expand();
r.AttachBus();
foreach (var s in r.states) r.invalidatedStates.Add(s.Value);
r.ValidateStates();
return r;
}
public void CopyTo(byte ct, EventBus dest) {
base.CopyTo(dest);
// dest.states.Clear();
dest.workingStates.Clear();
dest.invalidatedStates.Clear();
RootState.CopyTo(ct, dest.RootState);
// foreach (var s in dest.states) dest.invalidatedStates.Add(s.Value);
dest.ValidateStates();
if (ct >= 2) {
dest.activeContainers.Clear();
foreach (var c in activeContainers) {
if (states[c].Working) {
states[c].CopyTo(ct, dest.states[c]);
dest.activeContainers.Add(c);
}
}
}
}
public void Dispose() {
RootState.Dispose();
}
public void NotifyWorkingChanged(ContainerState state) {
invalidatedStates.Add(state);
}
void Expand(ContainerState s = null) {
if (s == null) {
states.Clear();
s = RootState;
}
AddState(s);
foreach (var c in s.Children.Values)
Expand(c);
}
public void AddState(ContainerState s) {
states[s.Container] = s;
s.Bus = this;
}
/*
public void AddChildState(EventContainer p, EventContainer c) {
if (!states.ContainsKey(p)) AddChildState(prototype.states[p].Parent.Container, p);
if (!states.ContainsKey(c)) AddState(states[p].GetChild(c));
// if (prototype != null) prototype.states[c].CopyTo(RootState.CloneType, states[c]);
}*/
void EnsureActivity(EventContainer c) {
if (activeContainers.Contains(c)) return;
if (RootState.CloneType >= 2) prototype.states[c].CopyTo(RootState.CloneType, states[c]);
activeContainers.Add(c);
}
void AttachBus() {
foreach (var s in states.Values)
s.Bus = this;
}
public void AttachSystems(PdtSkin skin, Judge judge) {
foreach (var s in states.Values)
s.AttachSystems(skin, judge);
}
readonly List<StampedEvent> patch = new List<StampedEvent>();
public void IssuePatch(IEnumerable<StampedEvent> l) {
patch.AddRange(l);
}
public void DoPatch() {
foreach (var ev in patch) {
var batch = new EventBatch(ev.Time);
var batchIndex = events.BinarySearch(batch);
if (batchIndex >= 0) batch = events[batchIndex];
else events.Insert(~batchIndex, batch);
batch.Add(ev);
}
patch.Clear();
}
public override void ForwardOnceToTime(float toTime, Action<EventBatch> callback = null) {
if (EventId < events.Count && events[EventId].Time <= toTime) {
Time = events[EventId].Time;
var batch = events[EventId];
foreach (var s in workingStates) s.Handle(null);
ValidateStates();
for (var i = 0; i < batch.Count; i++) {
var ev = batch[i];
if (ev.Container != null) {
/* if (prototype != null && !states.ContainsKey(ev.Container))
AddChildState(prototype.states[ev.Container].Parent.Container, ev.Container); */
// TODO
// if (prototype != null) prototype.states[ev.Container].CopyTo(RootState.CloneType, states[ev.Container]);
EnsureActivity(ev.Container);
states[ev.Container].Handle(ev);
}
if (ev.Unstamped is EventContainer) {
if (ev.Container != null) EnsureActivity((EventContainer)ev.Unstamped);
// AddChildState(ev.Container, (EventContainer)ev.Unstamped);
}
}
ValidateStates();
EventId++;
}
else {
Time = toTime;
foreach (var s in workingStates) s.Handle(null);
ValidateStates();
}
}
private void ValidateStates() {
foreach (var s in invalidatedStates)
if (s.Working && !workingStates.Contains(s)) workingStates.Add(s);
else if (!s.Working && workingStates.Contains(s)) workingStates.Remove(s);
invalidatedStates.Clear();
}
public void BroadcastInit() {
RootState.BroadcastInit();
}
public void BroadcastEndUpdate() {
RootState.BroadcastEndUpdate();
}
public void Anchor() {
RootState.Anchor();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 61741923e2c1d9c43b2d1b457a54ed4c
timeCreated: 1617701716
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using Cryville.Common.Buffers;
using System.Collections.Generic;
namespace Cryville.Crtr.Event {
internal class RMVPool {
private class Bucket : ObjectPool<RealtimeMotionValue> {
MotionRegistry _reg;
public Bucket(string name, int capacity) : base(capacity) {
_reg = ChartPlayer.motionRegistry[name];
}
protected override RealtimeMotionValue Construct() {
return new RealtimeMotionValue().Init(_reg.InitValue);
}
}
static Dictionary<string, Bucket> _buckets;
public static void Prepare() {
_buckets = new Dictionary<string, Bucket>(ChartPlayer.motionRegistry.Count);
foreach (var reg in ChartPlayer.motionRegistry)
_buckets.Add(reg.Key, new Bucket(reg.Key, 4096));
}
Dictionary<RealtimeMotionValue, string> _rented = new Dictionary<RealtimeMotionValue, string>();
public RealtimeMotionValue Rent(MotionName name) {
var n = name.MainName;
var obj = _buckets[n].Rent();
_rented.Add(obj, n);
return obj;
}
public void Return(RealtimeMotionValue obj) {
_buckets[_rented[obj]].Return(obj);
_rented.Remove(obj);
}
public void ReturnAll() {
foreach (var obj in _rented)
_buckets[obj.Value].Return(obj.Key);
_rented.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 765cb7bc1f7fe3e4db42f09a939fc393
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: