Add state-based effect.
This commit is contained in:
@@ -35,10 +35,14 @@ namespace Cryville.Crtr {
|
|||||||
while (_endQueue.Count > 0) {
|
while (_endQueue.Count > 0) {
|
||||||
var item = _endQueue[0];
|
var item = _endQueue[0];
|
||||||
if (item.EndTime > _time) break;
|
if (item.EndTime > _time) break;
|
||||||
item.OnDone();
|
|
||||||
_instances.Remove(item.Index);
|
|
||||||
_pool.Return(item);
|
|
||||||
_endQueue.RemoveAt(0);
|
_endQueue.RemoveAt(0);
|
||||||
|
if (item.OnStateDone()) {
|
||||||
|
QueueInstance(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_instances.Remove(item.Index);
|
||||||
|
_pool.Return(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (var instance in _instances) {
|
foreach (var instance in _instances) {
|
||||||
instance.Value.Tick(time);
|
instance.Value.Tick(time);
|
||||||
@@ -46,18 +50,21 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
public void Emit(float index) {
|
public void Emit(float index) {
|
||||||
EffectInstance instance;
|
EffectInstance instance;
|
||||||
if (_instances.TryGetValue(index, out instance)) {
|
bool flag = _instances.TryGetValue(index, out instance);
|
||||||
var i = _endQueue.BinarySearch(instance);
|
if (!flag) _instances.Add(index, instance = _pool.Rent());
|
||||||
_endQueue.RemoveAt(i);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_instances.Add(index, instance = _pool.Rent());
|
|
||||||
}
|
|
||||||
instance.Rewind(_time);
|
|
||||||
instance.Index = index;
|
instance.Index = index;
|
||||||
instance.OnEmit(_time);
|
if (instance.CanEmit()) {
|
||||||
var i2 = ~_endQueue.BinarySearch(instance);
|
if (flag) {
|
||||||
_endQueue.Insert(i2, instance);
|
var i = _endQueue.BinarySearch(instance);
|
||||||
|
_endQueue.RemoveAt(i);
|
||||||
|
}
|
||||||
|
instance.OnEmit(_time);
|
||||||
|
QueueInstance(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void QueueInstance(EffectInstance i) {
|
||||||
|
var index = ~_endQueue.BinarySearch(i);
|
||||||
|
_endQueue.Insert(index, i);
|
||||||
}
|
}
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
_pool.DisposeAll();
|
_pool.DisposeAll();
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
using Cryville.Crtr.Components;
|
using Cryville.Crtr.Components;
|
||||||
|
using Cryville.Crtr.Event;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -25,6 +26,7 @@ namespace Cryville.Crtr {
|
|||||||
_durationOp = new PropOp.Float(v => _duration = v);
|
_durationOp = new PropOp.Float(v => _duration = v);
|
||||||
}
|
}
|
||||||
public void Rewind(double time) {
|
public void Rewind(double time) {
|
||||||
|
_startTime = time;
|
||||||
foreach (var i in _comps) i.Rewind(time);
|
foreach (var i in _comps) i.Rewind(time);
|
||||||
}
|
}
|
||||||
private float m_index;
|
private float m_index;
|
||||||
@@ -36,6 +38,10 @@ namespace Cryville.Crtr {
|
|||||||
_indexSrc.Invalidate();
|
_indexSrc.Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Identifier _currentStateName = Identifier.Empty;
|
||||||
|
EffectState _currentState;
|
||||||
|
ChartEvent _ctxev;
|
||||||
|
ContainerState _ctxstate;
|
||||||
internal static readonly int _VAR_EFFECT_INDEX = IdentifierManager.SharedInstance.Request("effect_index");
|
internal static readonly int _VAR_EFFECT_INDEX = IdentifierManager.SharedInstance.Request("effect_index");
|
||||||
readonly PropSrc _indexSrc;
|
readonly PropSrc _indexSrc;
|
||||||
double _startTime;
|
double _startTime;
|
||||||
@@ -45,17 +51,47 @@ namespace Cryville.Crtr {
|
|||||||
public void Tick(double time) {
|
public void Tick(double time) {
|
||||||
foreach (var i in _comps) i.Tick(_skinContainer, time);
|
foreach (var i in _comps) i.Tick(_skinContainer, time);
|
||||||
}
|
}
|
||||||
|
public bool CanEmit() {
|
||||||
|
return _currentStateName.Key == 0 || _currentState.rewind.Key != 0;
|
||||||
|
}
|
||||||
public void OnEmit(double time) {
|
public void OnEmit(double time) {
|
||||||
_startTime = time;
|
_ctxev = ChartPlayer.etor.ContextEvent;
|
||||||
|
_ctxstate = ChartPlayer.etor.ContextState;
|
||||||
|
if (_currentStateName.Key == 0) {
|
||||||
|
EnterState(_def.init, time, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (_currentState.rewind.Key == 0) throw new InvalidOperationException("Cannot rewind");
|
||||||
|
EnterState(_currentState.rewind, time, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EnterState(Identifier name, double time, bool emitting) {
|
||||||
|
_currentStateName = name;
|
||||||
|
_currentState = _def.states[name];
|
||||||
|
Rewind(time);
|
||||||
RootTransform.gameObject.SetActive(true);
|
RootTransform.gameObject.SetActive(true);
|
||||||
ChartPlayer.etor.ContextCascadeInsert();
|
ChartPlayer.etor.ContextCascadeInsert();
|
||||||
ChartPlayer.etor.ContextCascadeUpdate(_VAR_EFFECT_INDEX, _indexSrc);
|
ChartPlayer.etor.ContextCascadeUpdate(_VAR_EFFECT_INDEX, _indexSrc);
|
||||||
ChartPlayer.etor.Evaluate(_durationOp, _def.duration);
|
ChartPlayer.etor.Evaluate(_durationOp, _currentState.duration);
|
||||||
_skinContainer.MatchDynamic(0);
|
if (emitting) _skinContainer.MatchDynamic(0);
|
||||||
|
_skinContainer.MatchDynamic(1);
|
||||||
ChartPlayer.etor.ContextCascadeDiscard();
|
ChartPlayer.etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
public void OnDone() {
|
public bool OnStateDone() {
|
||||||
RootTransform.gameObject.SetActive(false);
|
if (_currentState.next.Key == 0) {
|
||||||
|
RootTransform.gameObject.SetActive(false);
|
||||||
|
_currentStateName = Identifier.Empty;
|
||||||
|
_currentState = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ChartPlayer.etor.ContextEvent = _ctxev;
|
||||||
|
ChartPlayer.etor.ContextState = _ctxstate;
|
||||||
|
EnterState(_currentState.next, EndTime, false);
|
||||||
|
ChartPlayer.etor.ContextEvent = null;
|
||||||
|
ChartPlayer.etor.ContextState = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
GameObject.Destroy(RootTransform.gameObject);
|
GameObject.Destroy(RootTransform.gameObject);
|
||||||
@@ -63,7 +99,7 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
public string TypeName { get { throw new InvalidOperationException("Type name undefined"); } }
|
public string TypeName { get { throw new InvalidOperationException("Type name undefined"); } }
|
||||||
public SkinContext SkinContext { get; private set; }
|
public SkinContext SkinContext { get; private set; }
|
||||||
public int OpenedAnchorName { get { throw new InvalidOperationException("Anchor not supported"); } }
|
public int OpenedAnchorName { get { return _currentStateName.Key; } }
|
||||||
public void PushAnchorEvent(double time, int name) {
|
public void PushAnchorEvent(double time, int name) {
|
||||||
throw new InvalidOperationException("Anchor not supported");
|
throw new InvalidOperationException("Anchor not supported");
|
||||||
}
|
}
|
||||||
|
@@ -101,11 +101,11 @@ namespace Cryville.Crtr {
|
|||||||
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", IdentifierManager.SharedInstance.Retrieve(name)));
|
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", IdentifierManager.SharedInstance.Retrieve(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChartEvent ContextEvent { private get; set; }
|
public ChartEvent ContextEvent { get; set; }
|
||||||
public ContainerState ContextState { private get; set; }
|
public ContainerState ContextState { get; set; }
|
||||||
public Transform ContextTransform { private get; set; }
|
public Transform ContextTransform { get; set; }
|
||||||
public Judge ContextJudge { private get; set; }
|
public Judge ContextJudge { get; set; }
|
||||||
public PropSrc ContextSelfValue { private get; set; }
|
public PropSrc ContextSelfValue { get; set; }
|
||||||
|
|
||||||
readonly Stack<int> ContextCascadeBlocks = new Stack<int>();
|
readonly Stack<int> ContextCascadeBlocks = new Stack<int>();
|
||||||
public void ContextCascadeInsertBlock() {
|
public void ContextCascadeInsertBlock() {
|
||||||
|
@@ -60,7 +60,9 @@ namespace Cryville.Crtr {
|
|||||||
var effect = e.Value;
|
var effect = e.Value;
|
||||||
etor.ContextCascadeInsert();
|
etor.ContextCascadeInsert();
|
||||||
etor.ContextCascadeUpdate(EffectInstance._VAR_EFFECT_INDEX, PropSrc.Error);
|
etor.ContextCascadeUpdate(EffectInstance._VAR_EFFECT_INDEX, PropSrc.Error);
|
||||||
etor.Optimize(effect.duration);
|
foreach(var s in effect.states) {
|
||||||
|
etor.Optimize(s.Value.duration);
|
||||||
|
}
|
||||||
effect.elements.Optimize(etor);
|
effect.elements.Optimize(etor);
|
||||||
etor.ContextCascadeDiscard();
|
etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
@@ -99,10 +101,30 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class EffectDefinition {
|
public class EffectDefinition {
|
||||||
public PdtExpression duration;
|
static Identifier _ident_init = new Identifier("init");
|
||||||
|
#pragma warning disable IDE1006
|
||||||
|
public PdtExpression duration {
|
||||||
|
set {
|
||||||
|
EffectState s;
|
||||||
|
if (!states.TryGetValue(_ident_init, out s))
|
||||||
|
throw new InvalidOperationException("Cannot set duration and states at the same time");
|
||||||
|
s.duration = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma warning restore IDE1006
|
||||||
|
public Identifier init = _ident_init;
|
||||||
|
public Dictionary<Identifier, EffectState> states = new Dictionary<Identifier, EffectState> {
|
||||||
|
{ _ident_init, new EffectState() { rewind = _ident_init } }
|
||||||
|
};
|
||||||
public SkinElement elements;
|
public SkinElement elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class EffectState {
|
||||||
|
public PdtExpression duration;
|
||||||
|
public Identifier rewind;
|
||||||
|
public Identifier next;
|
||||||
|
}
|
||||||
|
|
||||||
public class AnimationSpan {
|
public class AnimationSpan {
|
||||||
[ElementList]
|
[ElementList]
|
||||||
public Dictionary<Clip, AnimationSpan> spans
|
public Dictionary<Clip, AnimationSpan> spans
|
||||||
|
Reference in New Issue
Block a user