FXScriptParser.hx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. package hrt.prefab.fx;
  2. import hrt.prefab.fx.FXScript;
  3. @:access(hide.view.FXEditor)
  4. @:access(hrt.prefab.fx.FXScript)
  5. class FXScriptParser {
  6. public var firstParse = false;
  7. public function new(){
  8. }
  9. #if !hscript
  10. public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
  11. throw "FX Scripts requires -lib hscript";
  12. }
  13. #else
  14. inline function getExpr( e : hscript.Expr ) {
  15. #if hscriptPos
  16. return e.e;
  17. #else
  18. return e;
  19. #end
  20. }
  21. public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
  22. var parser = new hscript.Parser();
  23. parser.allowMetadata = true;
  24. parser.allowTypes = true;
  25. parser.allowJSON = true;
  26. var expr : hscript.Expr = null;
  27. var script = new hrt.prefab.fx.FXScript(fx);
  28. function parse( expr : hscript.Expr ) {
  29. if( expr == null ) return;
  30. switch(getExpr(expr)){
  31. case EMeta(name, args, e):
  32. parse(e);
  33. switch(name){
  34. case "param" :
  35. script.params.push(createFXParam(e));
  36. }
  37. case EBlock(e):
  38. for(expr in e)
  39. parse(expr);
  40. case EVar(n, t, e):
  41. script.myVars.set(n, createFXVar(expr));
  42. default:
  43. }
  44. }
  45. try {
  46. expr = parser.parseString(s, "");
  47. } catch( e : hscript.Expr.Error ) { }
  48. parse(expr);
  49. function convert( expr : hscript.Expr ) : FxAst {
  50. if( expr == null ) return null;
  51. function getPath( expr : hscript.Expr ) : String {
  52. return switch(getExpr(expr)){
  53. case EField(e,f): getPath(e) + "." + f;
  54. case EIdent(v): v;
  55. default: null;
  56. }
  57. }
  58. function getSetField( expr : hscript.Expr ){
  59. return script.getSetter(getPath(expr));
  60. }
  61. function getGetField( expr : hscript.Expr ){
  62. return script.getGetter(getPath(expr));
  63. }
  64. switch(getExpr(expr)){
  65. case EBlock(e):
  66. return Block( [for(expr in e) convert(expr)] );
  67. case ECall( e, params ):
  68. var name = switch(getExpr(e)) {
  69. case EIdent(v): v;
  70. default: null;
  71. }
  72. return Call( name, [for(a in params) convert(a)]);
  73. case EFunction(args, e, name, ret):
  74. switch(name){
  75. case "update": script.updateAst = convert(e);
  76. case "init": script.initAst = convert(e);
  77. }
  78. return null;
  79. case EVar(n, t, e):
  80. if(e != null ) return Set(function(v){ script.setVar(n, v); }, convert(e));
  81. else return Var( function(){ return script.getVar(n); });
  82. case EField(e, f):
  83. return Var( getGetField(expr) );
  84. case EIf( cond, e1, e2):
  85. return If(convert(cond), convert(e1), convert(e2));
  86. case EIdent(v):
  87. return switch(v) {
  88. case "true": Const(1);
  89. case "false": Const(0);
  90. default: Var( function(){ return script.getVar(v); });
  91. }
  92. case EConst( c ):
  93. return switch(c) {
  94. case CInt(v): Const(v);
  95. case CFloat(f): Const(f);
  96. default: null;
  97. }
  98. case EBinop(op, e1, e2):
  99. switch(op) {
  100. case "%": return Op( convert(e1), convert(e2), function(a,b) { return a % b; });
  101. case "*": return Op( convert(e1), convert(e2), function(a,b) { return a * b; });
  102. case "/": return Op( convert(e1), convert(e2), function(a,b) { return a / b; });
  103. case "+": return Op( convert(e1), convert(e2), function(a,b) { return a + b; });
  104. case "-": return Op( convert(e1), convert(e2), function(a,b) { return a - b; });
  105. case "=": switch(getExpr(e1)){
  106. case EIdent(v): return Set(function(val){ script.setVar(v, val); }, convert(e2));
  107. case EField(e,f): return Set( getSetField(e1), convert(e2));
  108. default: return null;
  109. }
  110. case "+=": switch(getExpr(e1)){
  111. case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
  112. case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
  113. default: return null;
  114. }
  115. case "-=": switch(getExpr(e1)){
  116. case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
  117. case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
  118. default: return null;
  119. }
  120. case "==": return Op( convert(e1), convert(e2), function(a,b) { return a == b ? 1.0 : 0.0; });
  121. case "!=": return Op( convert(e1), convert(e2), function(a,b) { return a != b ? 1.0 : 0.0; });
  122. case ">": return Op( convert(e1), convert(e2), function(a,b) { return a > b ? 1.0 : 0.0; });
  123. case "<": return Op( convert(e1), convert(e2), function(a,b) { return a < b ? 1.0 : 0.0; });
  124. case ">=": return Op( convert(e1), convert(e2), function(a,b) { return a >= b ? 1.0 : 0.0; });
  125. case "<=": return Op( convert(e1), convert(e2), function(a,b) { return a <= b ? 1.0 : 0.0; });
  126. default: return null;
  127. }
  128. case EUnop(op, prefix, e):
  129. var expr = e;
  130. switch(getExpr(e)){
  131. case EIdent(v):
  132. return switch(op){
  133. case "++": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
  134. case "--": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? --a : a--; }));
  135. case "-": Unop( convert(e), function(a){ return -a;});
  136. default: null;
  137. }
  138. case EField(e,f):
  139. return switch(op){
  140. case "++": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
  141. case "--": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? --a : a--; }));
  142. case "-": Unop( convert(e), function(a){ return -a;});
  143. default : null;
  144. }
  145. case ECall( e, params ):
  146. return switch(op){
  147. case "-": Unop( convert(e), function(a){ return -a;});
  148. default : null;
  149. }
  150. default: return null;
  151. }
  152. case EParent(e):
  153. return convert(e);
  154. case EObject(fl):
  155. for(elem in fl) trace(elem.name);
  156. return Block( [for(elem in fl) convert(elem.e)] );
  157. default:
  158. return null;
  159. }
  160. }
  161. script.ast = convert(expr);
  162. return script;
  163. }
  164. function createFXVar( expr : hscript.Expr ) {
  165. function parse(expr : hscript.Expr) : FXVar {
  166. return switch(getExpr(expr)){
  167. case EFunction(args, e, name, ret):
  168. return parse(e);
  169. case EMeta(name, args, e):
  170. return parse(e);
  171. case EVar(n, t, e):
  172. var r : FXVar = null;
  173. if(t != null){
  174. switch(t){
  175. case CTPath(path, params):
  176. switch(path){
  177. case ["Int"]: r = FXVar.Int(0);
  178. case ["Float"]: r = FXVar.Float(0.0);
  179. case ["Bool"]: r = FXVar.Bool(false);
  180. default:
  181. }
  182. default: null;
  183. }
  184. }
  185. if(e != null){
  186. switch(getExpr(e)){
  187. case EIdent(v):
  188. if(r != null){
  189. switch(r){
  190. case Float(value):
  191. switch(v) {
  192. case "true": r = FXVar.Float(1.0);
  193. case "false": r = FXVar.Float(0.0);
  194. default:
  195. }
  196. case Int(value):
  197. switch(v) {
  198. case "true": r = FXVar.Int(1);
  199. case "false": r = FXVar.Int(0);
  200. default:
  201. }
  202. case Bool(value):
  203. switch(v) {
  204. case "true": r = FXVar.Bool(true);
  205. case "false": r = FXVar.Bool(false);
  206. default:
  207. }
  208. }
  209. }else{
  210. switch(v) {
  211. case "true": r = FXVar.Bool(true);
  212. case "false": r = FXVar.Bool(false);
  213. default:
  214. }
  215. }
  216. case EConst(c):
  217. if(r != null){
  218. switch(r){
  219. case Float(value):
  220. switch(c){
  221. case CInt(v): r = FXVar.Float(v);
  222. case CFloat(f): r = FXVar.Float(f);
  223. default:
  224. }
  225. case Int(value):
  226. switch(c){
  227. case CInt(v): r = FXVar.Int(v);
  228. case CFloat(f): r = FXVar.Int(Std.int(f));
  229. default:
  230. }
  231. case Bool(value):
  232. switch(c){
  233. case CInt(v): r = FXVar.Bool(v > 0);
  234. case CFloat(f): r = FXVar.Bool(f > 0);
  235. default:
  236. }
  237. }
  238. }
  239. else{
  240. switch(c){
  241. case CInt(v): r = FXVar.Int(v);
  242. case CFloat(f): r = FXVar.Float(f);
  243. default:
  244. }
  245. }
  246. default: null;
  247. }
  248. }
  249. return r;
  250. default: null;
  251. }
  252. }
  253. return parse(expr);
  254. }
  255. function createFXParam( expr : hscript.Expr ) : FXParam {
  256. var options : Array<ParamOption> = [];
  257. function parse(expr : hscript.Expr) : FXParam {
  258. if( expr == null ) return null;
  259. switch(getExpr(expr)){
  260. case EFunction(args, e, name, ret):
  261. return parse(e);
  262. case EMeta(name, args, e):
  263. switch(name){
  264. case "range":
  265. var min = switch(getExpr(args[0])){
  266. case EConst(c):
  267. switch(c){
  268. case CInt(v): v;
  269. case CFloat(f): f;
  270. default: null;
  271. }
  272. default: null;
  273. }
  274. var max = switch(getExpr(args[1])){
  275. case EConst(c):
  276. switch(c){
  277. case CInt(v): v;
  278. case CFloat(f): f;
  279. default: null;
  280. }
  281. default: null;
  282. }
  283. options.push(Range(min, max));
  284. default:
  285. }
  286. return parse(e);
  287. case EVar(n, t, e):
  288. var r : FXParam = null;
  289. if(t != null){
  290. switch(t){
  291. case CTPath(path, params):
  292. switch(path){
  293. case ["Int"]: r = FXParam.Int(n, 0, options);
  294. case ["Float"]: r = FXParam.Float(n, 0.0, options);
  295. case ["Bool"]: r = FXParam.Bool(n, false, options);
  296. default:
  297. }
  298. default: null;
  299. }
  300. }
  301. if(e != null){
  302. switch(getExpr(e)){
  303. case EIdent(v):
  304. if(r != null){
  305. switch(r){
  306. case Float(name, value, options):
  307. switch(v) {
  308. case "true": r = FXParam.Float(n, 1.0, options);
  309. case "false": r = FXParam.Float(n, 0.0, options);
  310. default:
  311. }
  312. case Int(name, value, options):
  313. switch(v) {
  314. case "true": r = FXParam.Int(n, 1, options);
  315. case "false": r = FXParam.Int(n, 0, options);
  316. default:
  317. }
  318. case Bool(name, value, options):
  319. switch(v) {
  320. case "true": r = FXParam.Bool(n, true, options);
  321. case "false": r = FXParam.Bool(n, false, options);
  322. default:
  323. }
  324. }
  325. }else{
  326. switch(v) {
  327. case "true": r = FXParam.Bool(n, true, options);
  328. case "false": r = FXParam.Bool(n, false, options);
  329. default:
  330. }
  331. }
  332. case EConst(c):
  333. if(r != null){
  334. switch(r){
  335. case Float(name, value, options):
  336. switch(c){
  337. case CInt(v): r = FXParam.Float(n, v, options);
  338. case CFloat(f): r = FXParam.Float(n, f, options);
  339. default:
  340. }
  341. case Int(name, value, options):
  342. switch(c){
  343. case CInt(v): r = FXParam.Int(n, v, options);
  344. case CFloat(f): r = FXParam.Int(n, Std.int(f), options);
  345. default:
  346. }
  347. case Bool(name, value, options):
  348. switch(c){
  349. case CInt(v): r = FXParam.Bool(n, v > 0, options);
  350. case CFloat(f): r = FXParam.Bool(n, f > 0, options);
  351. default:
  352. }
  353. }
  354. }
  355. else{
  356. switch(c){
  357. case CInt(v): r = FXParam.Int(n, v, options);
  358. case CFloat(f): r = FXParam.Float(n, f, options);
  359. default:
  360. }
  361. }
  362. default: null;
  363. }
  364. }
  365. return r;
  366. default:
  367. return null;
  368. }
  369. return null;
  370. }
  371. return parse(expr);
  372. }
  373. #end
  374. #if editor
  375. public function generateUI( s : FXScript, editor : hide.view.FXEditor ){
  376. var elem = editor.element.find(".fx-scriptParams");
  377. elem.empty();
  378. if(s == null) return;
  379. var root = new Element('<div class="group" name="Params"></div>');
  380. for(p in s.params){
  381. if(p == null) continue;
  382. switch(p){
  383. case Float(name, value, options):
  384. var sliderMin = 0.0;
  385. var sliderMax = 1.0;
  386. for(o in options){
  387. switch(o){
  388. case Range(min, max):
  389. sliderMin = min;
  390. sliderMax = max;
  391. default:
  392. }
  393. }
  394. root.append(createSlider(s, name, sliderMin, sliderMax, 0.1, value));
  395. case Int(name, value, options):
  396. var sliderMin = 0.0;
  397. var sliderMax = 1.0;
  398. for(o in options){
  399. switch(o){
  400. case Range(min, max):
  401. sliderMin = min;
  402. sliderMax = max;
  403. default:
  404. }
  405. }
  406. root.append(createSlider(s, name, sliderMin, sliderMax, 1.0, value));
  407. case Bool(name, value, options):
  408. root.append(createChekbox(s, name, value));
  409. }
  410. }
  411. elem.append(root);
  412. }
  413. function createSlider( s : FXScript, name : String, min : Float, max : Float, step : Float, defaultVal : Float ) : Element {
  414. var root = new Element('<div class="slider"/>');
  415. var label = new Element('<label> $name : </label>');
  416. var slider = new Element('<input type="range" min="$min" max="$max" step="$step" value="$defaultVal"/>');
  417. root.append(label);
  418. var range = new hide.comp.Range(root, slider);
  419. range.onChange = function(b){
  420. s.setVar(name, range.value);
  421. }
  422. return root;
  423. }
  424. function createChekbox( s : FXScript, name : String, defaultVal : Bool ) : Element {
  425. var root = new Element('<div class="checkbox"/>');
  426. var label = new Element('<label> $name : </label>');
  427. var checkbox = new Element('<input type="checkbox" />');
  428. checkbox.prop("checked", defaultVal);
  429. checkbox.on("change", function(_) {
  430. var checked : Bool = checkbox.prop("checked");
  431. s.setVar(name, checked ? 1.0 : 0.0);
  432. });
  433. root.append(label);
  434. root.append(checkbox);
  435. return root;
  436. }
  437. #end
  438. }