From 76df4929a72094fec4f877e68030e7ac6ecd5ace Mon Sep 17 00:00:00 2001 From: PopSlime Date: Thu, 9 Mar 2023 11:38:49 +0800 Subject: [PATCH] Implement set variable annotation. --- Assets/Cryville/Crtr/EffectInstance.cs | 4 +- Assets/Cryville/Crtr/PdtEvaluator.cs | 6 ++- Assets/Cryville/Crtr/SkinContainer.cs | 30 ++++++++++++--- Assets/Cryville/Crtr/SkinPropertyKey.cs | 50 +++++++++++++++++++------ 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/Assets/Cryville/Crtr/EffectInstance.cs b/Assets/Cryville/Crtr/EffectInstance.cs index be69c8a..b8202a3 100644 --- a/Assets/Cryville/Crtr/EffectInstance.cs +++ b/Assets/Cryville/Crtr/EffectInstance.cs @@ -73,8 +73,8 @@ namespace Cryville.Crtr { ChartPlayer.etor.ContextCascadeInsert(); ChartPlayer.etor.ContextCascadeUpdate(_VAR_EFFECT_INDEX, _indexSrc); ChartPlayer.etor.Evaluate(_durationOp, _currentState.duration); - if (emitting) _skinContainer.MatchDynamic(0); - _skinContainer.MatchDynamic(1); + if (emitting) _skinContainer.MatchDynamic(0, true); + _skinContainer.MatchDynamic(1, emitting); ChartPlayer.etor.ContextCascadeDiscard(); } public bool OnStateDone() { diff --git a/Assets/Cryville/Crtr/PdtEvaluator.cs b/Assets/Cryville/Crtr/PdtEvaluator.cs index 01e714f..5796d06 100644 --- a/Assets/Cryville/Crtr/PdtEvaluator.cs +++ b/Assets/Cryville/Crtr/PdtEvaluator.cs @@ -32,7 +32,7 @@ namespace Cryville.Crtr { else if (name == _var_null) { LoadIdent(0); type = PdtInternalType.Undefined; value = _numbuf; } else { var id = new Identifier(name); - PropSrc prop; + PropSrc prop; SkinVariable variable; if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) { prop.Get(out type, out value); } @@ -45,6 +45,9 @@ namespace Cryville.Crtr { prop.Get(out type, out value); RevokePotentialConstant(); } + else if (ContextSkinContainer != null && ContextSkinContainer.Variables.TryGetValue(name, out variable)) { + variable.Src.Get(out type, out value); + } else if (ContextJudge != null && ContextJudge.TryGetScoreSrc(name, out prop)) { prop.Get(out type, out value); RevokePotentialConstant(); @@ -106,6 +109,7 @@ namespace Cryville.Crtr { public ChartEvent ContextEvent { get; set; } public ContainerState ContextState { get; set; } + public SkinContainer ContextSkinContainer { get; set; } public Transform ContextTransform { get; set; } public Judge ContextJudge { get; set; } public PropSrc ContextSelfValue { get; set; } diff --git a/Assets/Cryville/Crtr/SkinContainer.cs b/Assets/Cryville/Crtr/SkinContainer.cs index b1b4c1d..0af87a4 100644 --- a/Assets/Cryville/Crtr/SkinContainer.cs +++ b/Assets/Cryville/Crtr/SkinContainer.cs @@ -9,6 +9,7 @@ namespace Cryville.Crtr { readonly SkinElement _rootElement; readonly DynamicStack[] _stacks = new DynamicStack[2]; readonly HashSet _once = new HashSet(); + public readonly Dictionary Variables = new Dictionary(); class DynamicStack { public readonly List Properties = new List(); @@ -45,7 +46,7 @@ namespace Cryville.Crtr { if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs); foreach (var p in rel.properties) { try { - p.Key.ExecuteStatic(_group, ctx, p.Value); + p.Key.ExecuteStatic(_group, ctx, p.Value, Variables); } catch (EvaluationFailureException) { } if (p.Key.IsValueRequired && !p.Value.IsConstant) stack.Properties.Add( @@ -73,15 +74,16 @@ namespace Cryville.Crtr { } if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard(); } - public void MatchDynamic(int dl) { + public void MatchDynamic(int dl, bool recursive = false) { var stack = _stacks[dl]; if (stack.Properties.Count == 0 && stack.Elements.Count == 0) return; var nstack = dl + 1 < _stacks.Length ? _stacks[dl + 1] : null; if (nstack != null) nstack.Clear(); Profiler.BeginSample("SkinContainer.MatchDynamic"); + if (!recursive) ChartPlayer.etor.ContextSkinContainer = this; for (int i = 0; i < stack.Properties.Count; i++) { DynamicProperty p = stack.Properties[i]; - p.Key.ExecuteDynamic(_group, p.Context, p.Value, dl); + p.Key.ExecuteDynamic(_group, p.Context, p.Value, Variables, dl); if (p.Key.annotations.Contains("once")) { stack.Properties.RemoveAt(i--); } @@ -108,6 +110,7 @@ namespace Cryville.Crtr { } if (psrcs != null) ChartPlayer.etor.ContextCascadeDiscard(); } + if (!recursive) ChartPlayer.etor.ContextSkinContainer = null; Profiler.EndSample(); } void MatchDynamic(SkinElement rel, int dl, DynamicStack stack, RuntimeSkinContext ctx) { @@ -117,11 +120,11 @@ namespace Cryville.Crtr { foreach (var p in rel.properties) { if (p.Key.annotations.Contains("once")) { if (_once.Contains(p.Key)) continue; - p.Key.ExecuteDynamic(_group, ctx, p.Value, dl); + p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, dl); _once.Add(p.Key); } else { - p.Key.ExecuteDynamic(_group, ctx, p.Value, dl); + p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, dl); } } ChartPlayer.etor.ContextTransform = null; @@ -144,15 +147,17 @@ namespace Cryville.Crtr { float _rtime; readonly PropSrc _rtimeSrc; public void MatchAnimation(AnimationSpan span, float rtime, RuntimeSkinContext ctx) { + ChartPlayer.etor.ContextSkinContainer = this; ChartPlayer.etor.ContextSelfValue = _rtimeSrc; MatchAnimationInternal(span, rtime, ctx); ChartPlayer.etor.ContextSelfValue = null; + ChartPlayer.etor.ContextSkinContainer = null; } void MatchAnimationInternal(AnimationSpan span, float rtime, RuntimeSkinContext ctx) { _rtime = rtime; _rtimeSrc.Invalidate(); foreach (var p in span.properties) { - p.Key.ExecuteDynamic(_group, ctx, p.Value, 0); + p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, 0); } foreach (var s in span.spans) { if (rtime < s.Key.Behind || rtime >= s.Key.Ahead) continue; @@ -202,4 +207,17 @@ namespace Cryville.Crtr { void RegisterAnchor(int name); void PushAnchorEvent(double time, int name); } + public class SkinVariable { + float _value; + public PropOp Op { get; private set; } + public PropSrc Src { get; private set; } + public SkinVariable() { + Op = new PropOp.Float(Set); + Src = new PropSrc.Float(() => _value); + } + void Set(float value) { + _value = value; + Src.Invalidate(); + } + } } diff --git a/Assets/Cryville/Crtr/SkinPropertyKey.cs b/Assets/Cryville/Crtr/SkinPropertyKey.cs index 6727b43..d7b0338 100644 --- a/Assets/Cryville/Crtr/SkinPropertyKey.cs +++ b/Assets/Cryville/Crtr/SkinPropertyKey.cs @@ -21,6 +21,10 @@ namespace Cryville.Crtr { if (k.Count != 1) throw new FormatException("Invalid effect name"); return new EmitEffect(a, IdentifierManager.SharedInstance.Request(k[0])); } + else if (a.Remove("var")) { + if (k.Count != 1) throw new FormatException("Invalid variable name"); + return new SetVariable(a, IdentifierManager.SharedInstance.Request(k[0])); + } switch (k.Count) { case 1: if (compKeyFlag) return new CreateComponent(a, GetComponentByName(k[0])); @@ -42,8 +46,8 @@ namespace Cryville.Crtr { } public abstract override string ToString(); public abstract bool IsValueRequired { get; } - public abstract void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp); - public abstract void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl); + public abstract void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars); + public abstract void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl); public class CreateComponent : SkinPropertyKey { public Type Component { get; private set; } public CreateComponent(IEnumerable a, Type component) : base(a) { @@ -53,10 +57,10 @@ namespace Cryville.Crtr { return string.Format("*{0}", Component.Name); } public override bool IsValueRequired { get { return false; } } - public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) { + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { ctx.WriteTransform.gameObject.AddComponent(Component); } - public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) { + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { throw new InvalidOperationException("Component creation in dynamic context is not allowed"); } } @@ -71,10 +75,10 @@ namespace Cryville.Crtr { return string.Format("{0}.{1}", Component.Name, IdentifierManager.SharedInstance.Retrieve(Name)); } public override bool IsValueRequired { get { return true; } } - public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) { + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { Execute(ctx, GetPropOp(ctx.WriteTransform).Operator, exp); } - public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) { + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { var prop = GetPropOp(ctx.WriteTransform); if (dl > prop.UpdateDynamicLevel) return; Execute(ctx, prop.Operator, exp); @@ -110,10 +114,10 @@ namespace Cryville.Crtr { return string.Format("@has {0}", IdentifierManager.SharedInstance.Retrieve(Name)); } public override bool IsValueRequired { get { return false; } } - public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) { + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { group.RegisterAnchor(Name); } - public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) { + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { throw new InvalidOperationException("Anchor creation in dynamic context is not allowed"); } } @@ -127,12 +131,12 @@ namespace Cryville.Crtr { return string.Format("@at {0}", IdentifierManager.SharedInstance.Retrieve(Name)); } public override bool IsValueRequired { get { return true; } } - public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) { + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { throw new InvalidOperationException("Setting anchor in static context is not allowed"); } float _time; readonly PropOp _timeOp; - public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) { + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { if (dl > 0) return; var psrcs = ctx.ReadContext.PropSrcs; if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs); @@ -151,15 +155,37 @@ namespace Cryville.Crtr { return string.Format("@emit {0}", IdentifierManager.SharedInstance.Retrieve(Name)); } public override bool IsValueRequired { get { return true; } } - public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) { + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { throw new InvalidOperationException("Emitting effect in static context is not allowed"); } float _index; readonly PropOp _op; - public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) { + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { ChartPlayer.etor.Evaluate(_op, exp); ChartPlayer.effectManager.Emit(Name, _index); } } + public class SetVariable : SkinPropertyKey { + public int Name { get; private set; } + public SetVariable(IEnumerable a, int name) : base(a) { + Name = name; + } + public override string ToString() { + return string.Format("@var {0}", IdentifierManager.SharedInstance.Retrieve(Name)); + } + public override bool IsValueRequired { get { return true; } } + public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars) { + SkinVariable v; + if (!vars.TryGetValue(Name, out v)) + vars.Add(Name, v = new SkinVariable()); + ChartPlayer.etor.Evaluate(v.Op, exp); + } + public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary vars, int dl) { + SkinVariable v; + if (!vars.TryGetValue(Name, out v)) + throw new InvalidOperationException(string.Format("Variable \"{0}\" not defined", IdentifierManager.SharedInstance.Retrieve(Name))); + ChartPlayer.etor.Evaluate(v.Op, exp); + } + } } }