diff --git a/.bin/music/test-60bpm.sj b/.bin/music/test-60bpm.sj index d076722..ed55e79 100644 --- a/.bin/music/test-60bpm.sj +++ b/.bin/music/test-60bpm.sj @@ -18,14 +18,17 @@ posteffect [0..1] { clip_left := 0.1; clip_right := 0.1; } +variable [0..3.5] { + hoge = 1-time; +} -$repeat i 1 { +$repeat i 2 { $repeat j 20 { - circle [$i..$i+2] { + circle [$i+1..$i+3] { color_r := 0.8; color_g := 0.1; color_b := 0.1; - color_a := 1; + color_a = hoge; damage := 0.1; nearness_coe := 0.01; diff --git a/sjplayer/src/sjplayer/AbstractScheduledController.d b/sjplayer/src/sjplayer/AbstractScheduledController.d index 369beb5..d3f4f66 100644 --- a/sjplayer/src/sjplayer/AbstractScheduledController.d +++ b/sjplayer/src/sjplayer/AbstractScheduledController.d @@ -74,8 +74,7 @@ abstract class AbstractScheduledController : ScheduledControllerInterface { } auto temp = varstore_[name]; if (!temp.isNull) return temp; - // TODO: std constants - return Nullable!float.init; + return StandardVarStore.GetByName(name); } void SetParameter(ref in Parameter param, ref in VarStore vars) { if (param.name.length < 2 || param.name[0..2] != "__") { diff --git a/sjplayer/src/sjplayer/Context.d b/sjplayer/src/sjplayer/Context.d index 28387f0..3a39a92 100644 --- a/sjplayer/src/sjplayer/Context.d +++ b/sjplayer/src/sjplayer/Context.d @@ -21,7 +21,8 @@ import sjplayer.Actor, sjplayer.PostEffectControllerInterface, sjplayer.ProgramSet, sjplayer.ScheduledControllerInterface, - sjplayer.VarStore; + sjplayer.VarStore, + sjplayer.VarStoreScheduledController; /// class Context { @@ -55,6 +56,10 @@ class Context { "circle", CircleElementScheduledControllerFactory(programs, varstore), ), + tuple( + "variable", + VarStoreScheduledControllerFactory(varstore), + ), ); foreach (ref factory; factories) { factory[1]. diff --git a/sjplayer/src/sjplayer/VarStore.d b/sjplayer/src/sjplayer/VarStore.d index 24d69b6..2408681 100644 --- a/sjplayer/src/sjplayer/VarStore.d +++ b/sjplayer/src/sjplayer/VarStore.d @@ -21,10 +21,19 @@ class VarStore : VarStoreInterface { case "actor_x": return Nullable!float(actor_.pos.x); case "actor_y": return Nullable!float(actor_.pos.y); - default: return Nullable!float.init; + default: } + return name in user_vars_? + Nullable!float(user_vars_[name]): Nullable!float.init; + } + + /// + void opIndexAssign(float value, string name) { + user_vars_[name] = value; } private: const Actor actor_; + + float[string] user_vars_; } diff --git a/sjplayer/src/sjplayer/VarStoreScheduledController.d b/sjplayer/src/sjplayer/VarStoreScheduledController.d new file mode 100644 index 0000000..fe0dcc5 --- /dev/null +++ b/sjplayer/src/sjplayer/VarStoreScheduledController.d @@ -0,0 +1,56 @@ +/// License: MIT +module sjplayer.VarStoreScheduledController; + +import std.range.primitives; + +import sjscript; + +import sjplayer.AbstractScheduledController, + sjplayer.ContextBuilderInterface, + sjplayer.VarStore, + sjplayer.util.Parameter; + +/// +class VarStoreScheduledController : AbstractScheduledController { + public: + /// + alias VarStore = sjplayer.VarStore.VarStore; + + /// + this(VarStore varstore, in ParametersBlock[] operations) { + super(varstore, operations); + varstore_ = varstore; + } + + override void SetParameter( + ref in Parameter param, + ref in AbstractScheduledController.VarStore vars) { + const x_nullable = varstore_[param.name]; + auto x = x_nullable.isNull? 0f: x_nullable.get; + param.CalculateParameter(x, vars); + varstore_[param.name] = x; + } + + private: + VarStore varstore_; +} + +/// +struct VarStoreScheduledControllerFactory { + public: + /// + this(VarStore varstore) { + varstore_ = varstore; + } + + /// + void Create(R)(R params, ContextBuilderInterface builder) + if (isInputRange!R && is(ElementType!R == ParametersBlock)) { + auto product = new VarStoreScheduledController( + varstore_, SortParametersBlock(params)); + builder.AddScheduledController(product); + } + + private: + VarStore varstore_; +} diff --git a/sjscript/src/sjscript/calculate.d b/sjscript/src/sjscript/calculate.d index 327187c..04b3693 100644 --- a/sjscript/src/sjscript/calculate.d +++ b/sjscript/src/sjscript/calculate.d @@ -7,6 +7,7 @@ import std.algorithm, std.format, std.math, std.traits, + std.typecons, std.variant; import sjscript.Expression, @@ -22,12 +23,17 @@ static assert(IsVarStore!(float[string])); struct StandardVarStore { public: static float opIndex(string name) { + const v = GetByName(name); + enforce(!v.isNull); + return v.get; + } + static Nullable!float GetByName(string name) { switch (name) { - case "PI": return PI; - case "PI_2": return PI_2; - case "PI_4": return PI_4; - case "E": return E; - default: throw new Exception("undefined variable %s".format(name)); + case "PI": return Nullable!float(PI); + case "PI_2": return Nullable!float(PI_2); + case "PI_4": return Nullable!float(PI_4); + case "E": return Nullable!float(E); + default: return Nullable!float.init; } } static assert(IsVarStore!StandardVarStore);