123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- package hrt.prefab.fx;
- import hrt.prefab.fx.FXScript;
- @:access(hide.view.FXEditor)
- @:access(hrt.prefab.fx.FXScript)
- class FXScriptParser {
- public var firstParse = false;
- public function new(){
- }
- #if !hscript
- public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
- throw "FX Scripts requires -lib hscript";
- }
- #else
- inline function getExpr( e : hscript.Expr ) {
- #if hscriptPos
- return e.e;
- #else
- return e;
- #end
- }
- public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
- var parser = new hscript.Parser();
- parser.allowMetadata = true;
- parser.allowTypes = true;
- parser.allowJSON = true;
- var expr : hscript.Expr = null;
- var script = new hrt.prefab.fx.FXScript(fx);
- function parse( expr : hscript.Expr ) {
- if( expr == null ) return;
- switch(getExpr(expr)){
- case EMeta(name, args, e):
- parse(e);
- switch(name){
- case "param" :
- script.params.push(createFXParam(e));
- }
- case EBlock(e):
- for(expr in e)
- parse(expr);
- case EVar(n, t, e):
- script.myVars.set(n, createFXVar(expr));
- default:
- }
- }
- try {
- expr = parser.parseString(s, "");
- } catch( e : hscript.Expr.Error ) { }
- parse(expr);
- function convert( expr : hscript.Expr ) : FxAst {
- if( expr == null ) return null;
- function getPath( expr : hscript.Expr ) : String {
- return switch(getExpr(expr)){
- case EField(e,f): getPath(e) + "." + f;
- case EIdent(v): v;
- default: null;
- }
- }
- function getSetField( expr : hscript.Expr ){
- return script.getSetter(getPath(expr));
- }
- function getGetField( expr : hscript.Expr ){
- return script.getGetter(getPath(expr));
- }
- switch(getExpr(expr)){
- case EBlock(e):
- return Block( [for(expr in e) convert(expr)] );
- case ECall( e, params ):
- var name = switch(getExpr(e)) {
- case EIdent(v): v;
- default: null;
- }
- return Call( name, [for(a in params) convert(a)]);
- case EFunction(args, e, name, ret):
- switch(name){
- case "update": script.updateAst = convert(e);
- case "init": script.initAst = convert(e);
- }
- return null;
- case EVar(n, t, e):
- if(e != null ) return Set(function(v){ script.setVar(n, v); }, convert(e));
- else return Var( function(){ return script.getVar(n); });
- case EField(e, f):
- return Var( getGetField(expr) );
- case EIf( cond, e1, e2):
- return If(convert(cond), convert(e1), convert(e2));
- case EIdent(v):
- return switch(v) {
- case "true": Const(1);
- case "false": Const(0);
- default: Var( function(){ return script.getVar(v); });
- }
- case EConst( c ):
- return switch(c) {
- case CInt(v): Const(v);
- case CFloat(f): Const(f);
- default: null;
- }
- case EBinop(op, e1, e2):
- switch(op) {
- case "%": return Op( convert(e1), convert(e2), function(a,b) { return a % b; });
- case "*": return Op( convert(e1), convert(e2), function(a,b) { return a * b; });
- case "/": return Op( convert(e1), convert(e2), function(a,b) { return a / b; });
- case "+": return Op( convert(e1), convert(e2), function(a,b) { return a + b; });
- case "-": return Op( convert(e1), convert(e2), function(a,b) { return a - b; });
- case "=": switch(getExpr(e1)){
- case EIdent(v): return Set(function(val){ script.setVar(v, val); }, convert(e2));
- case EField(e,f): return Set( getSetField(e1), convert(e2));
- default: return null;
- }
- case "+=": switch(getExpr(e1)){
- case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
- case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
- default: return null;
- }
- case "-=": switch(getExpr(e1)){
- case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
- case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
- default: return null;
- }
- case "==": return Op( convert(e1), convert(e2), function(a,b) { return a == b ? 1.0 : 0.0; });
- case "!=": return Op( convert(e1), convert(e2), function(a,b) { return a != b ? 1.0 : 0.0; });
- case ">": return Op( convert(e1), convert(e2), function(a,b) { return a > b ? 1.0 : 0.0; });
- case "<": return Op( convert(e1), convert(e2), function(a,b) { return a < b ? 1.0 : 0.0; });
- case ">=": return Op( convert(e1), convert(e2), function(a,b) { return a >= b ? 1.0 : 0.0; });
- case "<=": return Op( convert(e1), convert(e2), function(a,b) { return a <= b ? 1.0 : 0.0; });
- default: return null;
- }
- case EUnop(op, prefix, e):
- var expr = e;
- switch(getExpr(e)){
- case EIdent(v):
- return switch(op){
- case "++": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
- case "--": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? --a : a--; }));
- case "-": Unop( convert(e), function(a){ return -a;});
- default: null;
- }
- case EField(e,f):
- return switch(op){
- case "++": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
- case "--": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? --a : a--; }));
- case "-": Unop( convert(e), function(a){ return -a;});
- default : null;
- }
- case ECall( e, params ):
- return switch(op){
- case "-": Unop( convert(e), function(a){ return -a;});
- default : null;
- }
- default: return null;
- }
- case EParent(e):
- return convert(e);
- case EObject(fl):
- for(elem in fl) trace(elem.name);
- return Block( [for(elem in fl) convert(elem.e)] );
- default:
- return null;
- }
- }
- script.ast = convert(expr);
- return script;
- }
- function createFXVar( expr : hscript.Expr ) {
- function parse(expr : hscript.Expr) : FXVar {
- return switch(getExpr(expr)){
- case EFunction(args, e, name, ret):
- return parse(e);
- case EMeta(name, args, e):
- return parse(e);
- case EVar(n, t, e):
- var r : FXVar = null;
- if(t != null){
- switch(t){
- case CTPath(path, params):
- switch(path){
- case ["Int"]: r = FXVar.Int(0);
- case ["Float"]: r = FXVar.Float(0.0);
- case ["Bool"]: r = FXVar.Bool(false);
- default:
- }
- default: null;
- }
- }
- if(e != null){
- switch(getExpr(e)){
- case EIdent(v):
- if(r != null){
- switch(r){
- case Float(value):
- switch(v) {
- case "true": r = FXVar.Float(1.0);
- case "false": r = FXVar.Float(0.0);
- default:
- }
- case Int(value):
- switch(v) {
- case "true": r = FXVar.Int(1);
- case "false": r = FXVar.Int(0);
- default:
- }
- case Bool(value):
- switch(v) {
- case "true": r = FXVar.Bool(true);
- case "false": r = FXVar.Bool(false);
- default:
- }
- }
- }else{
- switch(v) {
- case "true": r = FXVar.Bool(true);
- case "false": r = FXVar.Bool(false);
- default:
- }
- }
- case EConst(c):
- if(r != null){
- switch(r){
- case Float(value):
- switch(c){
- case CInt(v): r = FXVar.Float(v);
- case CFloat(f): r = FXVar.Float(f);
- default:
- }
- case Int(value):
- switch(c){
- case CInt(v): r = FXVar.Int(v);
- case CFloat(f): r = FXVar.Int(Std.int(f));
- default:
- }
- case Bool(value):
- switch(c){
- case CInt(v): r = FXVar.Bool(v > 0);
- case CFloat(f): r = FXVar.Bool(f > 0);
- default:
- }
- }
- }
- else{
- switch(c){
- case CInt(v): r = FXVar.Int(v);
- case CFloat(f): r = FXVar.Float(f);
- default:
- }
- }
- default: null;
- }
- }
- return r;
- default: null;
- }
- }
- return parse(expr);
- }
- function createFXParam( expr : hscript.Expr ) : FXParam {
- var options : Array<ParamOption> = [];
- function parse(expr : hscript.Expr) : FXParam {
- if( expr == null ) return null;
- switch(getExpr(expr)){
- case EFunction(args, e, name, ret):
- return parse(e);
- case EMeta(name, args, e):
- switch(name){
- case "range":
- var min = switch(getExpr(args[0])){
- case EConst(c):
- switch(c){
- case CInt(v): v;
- case CFloat(f): f;
- default: null;
- }
- default: null;
- }
- var max = switch(getExpr(args[1])){
- case EConst(c):
- switch(c){
- case CInt(v): v;
- case CFloat(f): f;
- default: null;
- }
- default: null;
- }
- options.push(Range(min, max));
- default:
- }
- return parse(e);
- case EVar(n, t, e):
- var r : FXParam = null;
- if(t != null){
- switch(t){
- case CTPath(path, params):
- switch(path){
- case ["Int"]: r = FXParam.Int(n, 0, options);
- case ["Float"]: r = FXParam.Float(n, 0.0, options);
- case ["Bool"]: r = FXParam.Bool(n, false, options);
- default:
- }
- default: null;
- }
- }
- if(e != null){
- switch(getExpr(e)){
- case EIdent(v):
- if(r != null){
- switch(r){
- case Float(name, value, options):
- switch(v) {
- case "true": r = FXParam.Float(n, 1.0, options);
- case "false": r = FXParam.Float(n, 0.0, options);
- default:
- }
- case Int(name, value, options):
- switch(v) {
- case "true": r = FXParam.Int(n, 1, options);
- case "false": r = FXParam.Int(n, 0, options);
- default:
- }
- case Bool(name, value, options):
- switch(v) {
- case "true": r = FXParam.Bool(n, true, options);
- case "false": r = FXParam.Bool(n, false, options);
- default:
- }
- }
- }else{
- switch(v) {
- case "true": r = FXParam.Bool(n, true, options);
- case "false": r = FXParam.Bool(n, false, options);
- default:
- }
- }
- case EConst(c):
- if(r != null){
- switch(r){
- case Float(name, value, options):
- switch(c){
- case CInt(v): r = FXParam.Float(n, v, options);
- case CFloat(f): r = FXParam.Float(n, f, options);
- default:
- }
- case Int(name, value, options):
- switch(c){
- case CInt(v): r = FXParam.Int(n, v, options);
- case CFloat(f): r = FXParam.Int(n, Std.int(f), options);
- default:
- }
- case Bool(name, value, options):
- switch(c){
- case CInt(v): r = FXParam.Bool(n, v > 0, options);
- case CFloat(f): r = FXParam.Bool(n, f > 0, options);
- default:
- }
- }
- }
- else{
- switch(c){
- case CInt(v): r = FXParam.Int(n, v, options);
- case CFloat(f): r = FXParam.Float(n, f, options);
- default:
- }
- }
- default: null;
- }
- }
- return r;
- default:
- return null;
- }
- return null;
- }
- return parse(expr);
- }
- #end
- #if editor
- public function generateUI( s : FXScript, editor : hide.view.FXEditor ){
- var elem = editor.element.find(".fx-scriptParams");
- elem.empty();
- if(s == null) return;
- var root = new Element('<div class="group" name="Params"></div>');
- for(p in s.params){
- if(p == null) continue;
- switch(p){
- case Float(name, value, options):
- var sliderMin = 0.0;
- var sliderMax = 1.0;
- for(o in options){
- switch(o){
- case Range(min, max):
- sliderMin = min;
- sliderMax = max;
- default:
- }
- }
- root.append(createSlider(s, name, sliderMin, sliderMax, 0.1, value));
- case Int(name, value, options):
- var sliderMin = 0.0;
- var sliderMax = 1.0;
- for(o in options){
- switch(o){
- case Range(min, max):
- sliderMin = min;
- sliderMax = max;
- default:
- }
- }
- root.append(createSlider(s, name, sliderMin, sliderMax, 1.0, value));
- case Bool(name, value, options):
- root.append(createChekbox(s, name, value));
- }
- }
- elem.append(root);
- }
- function createSlider( s : FXScript, name : String, min : Float, max : Float, step : Float, defaultVal : Float ) : Element {
- var root = new Element('<div class="slider"/>');
- var label = new Element('<label> $name : </label>');
- var slider = new Element('<input type="range" min="$min" max="$max" step="$step" value="$defaultVal"/>');
- root.append(label);
- var range = new hide.comp.Range(root, slider);
- range.onChange = function(b){
- s.setVar(name, range.value);
- }
- return root;
- }
- function createChekbox( s : FXScript, name : String, defaultVal : Bool ) : Element {
- var root = new Element('<div class="checkbox"/>');
- var label = new Element('<label> $name : </label>');
- var checkbox = new Element('<input type="checkbox" />');
- checkbox.prop("checked", defaultVal);
- checkbox.on("change", function(_) {
- var checked : Bool = checkbox.prop("checked");
- s.setVar(name, checked ? 1.0 : 0.0);
- });
- root.append(label);
- root.append(checkbox);
- return root;
- }
- #end
- }
|