FXScript.hx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package hrt.prefab.fx;
  2. import hrt.prefab.fx.FX.FXAnimation;
  3. typedef Argument = { name : String, ?value : FxAst };
  4. enum FxAst {
  5. Block( a : Array<FxAst> );
  6. Var( get : Void -> Float );
  7. Const( v : Float );
  8. Set( set : Float -> Void, a : FxAst );
  9. Op( a : FxAst, b : FxAst, op : Float -> Float -> Float );
  10. Unop( a : FxAst, op : Float -> Float );
  11. If( cond : FxAst, eif : FxAst, eelse : FxAst );
  12. Function( args : Array<Argument>, a : FxAst, name : String );
  13. Call( name : String, args : Array<FxAst> );
  14. }
  15. enum FXVar {
  16. Float( value : Float );
  17. Int( value : Int );
  18. Bool( value : Bool );
  19. }
  20. // UI
  21. enum ParamOption {
  22. Range( min : Float, max : Float );
  23. }
  24. enum FXParam {
  25. Float( name : String, value : Float, options : Array<ParamOption> );
  26. Int( name : String, value : Int, options : Array<ParamOption> );
  27. Bool( name : String, value : Bool, options : Array<ParamOption> );
  28. }
  29. class FXScript {
  30. public var myVars : Map<String, FXVar> = [];
  31. public var params : Array<FXParam> = [];
  32. var fx : FXAnimation;
  33. var ast : FxAst;
  34. var initAst : FxAst;
  35. var updateAst : FxAst;
  36. public function new( fx : FXAnimation ){
  37. this.fx = fx;
  38. }
  39. public function getGetter( p : String ) : Void -> Float {
  40. var names = p.split('.');
  41. var i = 0;
  42. var root : h3d.scene.Object = fx;
  43. #if editor
  44. var fxRoot = fx.getObjectByName("FXRoot");
  45. if( fxRoot != null ) root = fxRoot;
  46. #end
  47. var curObj : h3d.scene.Object = root.getObjectByName(names[i++]);
  48. while(curObj != null && i < p.length) {
  49. var next = curObj.getObjectByName(names[i++]);
  50. next != null ? curObj = next : break;
  51. }
  52. if( curObj == null )
  53. return () -> 0.0;
  54. var field : String = "";
  55. for( index in i - 1 ... i )
  56. field += names[index];
  57. return switch( field ) {
  58. case "x": function() { return curObj.x; };
  59. case "y": function() { return curObj.y; };
  60. case "z": function() { return curObj.z; };
  61. case "scaleX": function() { return curObj.scaleX; };
  62. case "scaleY": function() { return curObj.scaleY; };
  63. case "scaleZ": function() { return curObj.scaleZ; };
  64. case "visible": function() { return curObj.visible ? 1.0 : 0.0; };
  65. case "rotationX": function() {
  66. return curObj.getRotationQuat().toEuler().x; }
  67. case "rotationY": function() {
  68. return curObj.getRotationQuat().toEuler().y; }
  69. case "rotationZ": function() {
  70. return curObj.getRotationQuat().toEuler().z; }
  71. default: return function() {
  72. if(Reflect.hasField(curObj, field)) {
  73. var p = Reflect.getProperty(curObj, field);
  74. return cast(p, Float);
  75. }
  76. else return 0.0;};
  77. }
  78. }
  79. public function getSetter( p : String ) : Float -> Void {
  80. var names = p.split('.');
  81. var i = 0;
  82. var root : h3d.scene.Object = fx;
  83. #if editor
  84. var fxRoot = fx.getObjectByName("FXRoot");
  85. if( fxRoot != null ) root = fxRoot;
  86. #end
  87. var curObj : h3d.scene.Object = root.getObjectByName(names[i++]);
  88. while(curObj != null && i < p.length) {
  89. var next = curObj.getObjectByName(names[i++]);
  90. next != null ? curObj = next : break;
  91. }
  92. if( curObj == null )
  93. return (v) -> {};
  94. var field : String = "";
  95. for( index in i - 1 ... i )
  96. field += names[index];
  97. return switch( field ) {
  98. case "x": function(v) { curObj.x = v; };
  99. case "y": function(v) { curObj.y = v; };
  100. case "z": function(v) { curObj.z = v; };
  101. case "scaleX": function(v) { curObj.scaleX = v; };
  102. case "scaleY": function(v) { curObj.scaleY = v; };
  103. case "scaleZ": function(v) { curObj.scaleZ = v; };
  104. case "visible": function(v) { curObj.visible = v > 0; };
  105. case "rotationX": function(v) {
  106. var euler = curObj.getRotationQuat().toEuler();
  107. curObj.setRotation(v, euler.y, euler.z); };
  108. case "rotationY": function(v) {
  109. var euler = curObj.getRotationQuat().toEuler();
  110. curObj.setRotation(euler.x, v, euler.z); };
  111. case "rotationZ": function(v) {
  112. var euler = curObj.getRotationQuat().toEuler();
  113. curObj.setRotation(euler.x, euler.y, v); };
  114. default: {
  115. if(Reflect.hasField(curObj, field)) {
  116. var cur = Reflect.field(curObj, field);
  117. if(Std.is(cur, Value))
  118. (v) -> Reflect.setProperty(curObj, field, Value.VConst(v));
  119. else
  120. (v) -> Reflect.setProperty(curObj, field, v);
  121. }
  122. else (v) -> {};
  123. };
  124. }
  125. }
  126. public function getVar( n : String ) : Float {
  127. if( n == "time" ) // TODO: support @global like hxsl
  128. return fx.localTime;
  129. if( !myVars.exists(n))
  130. return 0.0;
  131. if( myVars[n] == null )
  132. return 0.0;
  133. return switch myVars[n] {
  134. case Float(value): value;
  135. case Int(value): value;
  136. case Bool(value): value ? 1.0 : 0.0;
  137. default : 0.0;
  138. }
  139. }
  140. public function setVar( n : String, v : Float ) : Float {
  141. if( !myVars.exists(n) )
  142. return 0.0;
  143. switch myVars[n]{
  144. case Float(value): myVars.set(n, FXVar.Float(v));
  145. case Int(value): myVars.set(n, FXVar.Int(Std.int(v)));
  146. case Bool(value): myVars.set(n, FXVar.Bool( v > 0 ));
  147. }
  148. return switch myVars[n]{
  149. case Float(value): value;
  150. case Int(value): value;
  151. case Bool(value): value ? 1.0 : 0.0;
  152. }
  153. }
  154. function call( f : String, args : Array<FxAst>) : Float {
  155. switch( f ) {
  156. case "rand": return hxd.Math.random();
  157. case "mix": return hxd.Math.lerp(eval(args[0]), eval(args[1]), eval(args[2]));
  158. case "clamp": return hxd.Math.clamp(eval(args[0]), eval(args[1]), eval(args[2]));
  159. default: return 0.0;
  160. }
  161. }
  162. function eval(ast : FxAst) : Float {
  163. if(ast == null) return 0.0;
  164. switch (ast) {
  165. case Block(a):
  166. for(ast in a)
  167. eval(ast);
  168. return 0.0;
  169. case Call(a, args):
  170. return call(a, args);
  171. case Function(args, a, name):
  172. return 0.0; // TO DO
  173. case Var(get):
  174. return get();
  175. case Const(v):
  176. return v;
  177. case Set(set, a):
  178. var v = eval(a);
  179. set(v);
  180. return v;
  181. case Op(a, b, op):
  182. var va = eval(a);
  183. var vb = eval(b);
  184. return op(va,vb);
  185. case Unop(a, op):
  186. return op(eval(a));
  187. case If(cond, eif, eelse):
  188. return eval(cond) != 0 ? eval(eif) : eval(eelse);
  189. }
  190. }
  191. public function init() {
  192. eval(initAst);
  193. }
  194. public function update() {
  195. eval(updateAst);
  196. }
  197. }