Macros.hx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. package hrt.shgraph;
  2. import haxe.macro.Context;
  3. import haxe.macro.Expr;
  4. import hxsl.Ast;
  5. using hxsl.Ast;
  6. using haxe.macro.Tools;
  7. class Macros {
  8. #if macro
  9. static function buildNode() {
  10. var fields = Context.getBuildFields();
  11. for (f in fields) {
  12. if (f.name == "SRC") {
  13. switch (f.kind) {
  14. case FVar(_, expr) if (expr != null):
  15. var pos = expr.pos;
  16. if( !Lambda.has(f.access, AStatic) ) f.access.push(AStatic);
  17. Context.getLocalClass().get().meta.add(":src", [expr], pos);
  18. try {
  19. var c = Context.getLocalClass();
  20. // function map(e: haxe.macro.Expr) {
  21. // switch(e) {
  22. // case EMeta("sginput", args, e):
  23. // trace("sginput");
  24. // }
  25. // }
  26. // expr.map()
  27. var varmap : Map<String, hrt.shgraph.SgHxslVar> = [];
  28. function iter(e: haxe.macro.Expr) : Void {
  29. switch(e.expr) {
  30. case EMeta(meta, subexpr):
  31. switch (meta.name) {
  32. case "sginput":
  33. var defValue : hrt.shgraph.SgHxslVar.ShaderDefInput = null;
  34. if (meta.params != null && meta.params.length > 0) {
  35. switch (meta.params[0].expr) {
  36. case EConst(v):
  37. switch(v) {
  38. case CIdent(name):
  39. defValue = Var(name);
  40. case CString(val):
  41. defValue = Var(val);
  42. case CFloat(val), CInt(val):
  43. defValue = Const(Std.parseFloat(val));
  44. default:
  45. throw "sginput default param must be an identifier or a integer";
  46. }
  47. default:
  48. trace(meta.params[0].expr);
  49. throw "sginput default param must be a constant value";
  50. }
  51. }
  52. switch(subexpr.expr) {
  53. case EVars(vars):
  54. for (v in vars) {
  55. var isDynamic = false;
  56. switch (v.type) {
  57. case TPath(p) if (p.name == "Dynamic"):
  58. isDynamic = true;
  59. p.name = "Vec4"; // Convert dynamic value back to vec4 as a hack
  60. default:
  61. }
  62. varmap.set(v.name, SgInput(isDynamic, defValue));
  63. }
  64. e.expr = subexpr.expr;
  65. default:
  66. throw "sginput must be used with variables only";
  67. }
  68. case "sgoutput":
  69. switch(subexpr.expr) {
  70. case EVars(vars):
  71. for (v in vars) {
  72. var isDynamic = false;
  73. switch (v.type) {
  74. case TPath(p) if (p.name == "Dynamic"):
  75. isDynamic = true;
  76. p.name = "Vec4"; // Convert dynamic value back to vec4 as a hack
  77. default:
  78. }
  79. varmap.set(v.name, SgOutput(isDynamic));
  80. }
  81. e.expr = subexpr.expr;
  82. default:
  83. throw "sgoutput must be used with variables only";
  84. }
  85. case "sgconst":
  86. switch(subexpr.expr) {
  87. case EVars(vars):
  88. for (v in vars) {
  89. varmap.set(v.name, SgConst);
  90. }
  91. e.expr = subexpr.expr;
  92. default:
  93. throw "sgconst must be used with variables only";
  94. }
  95. default:
  96. }
  97. default:
  98. }
  99. }
  100. expr.iter(iter);
  101. var shader = new hxsl.MacroParser().parseExpr(expr);
  102. f.kind = FVar(null, macro @:pos(pos) $v{shader});
  103. var name = Std.string(c);
  104. var check = new hxsl.Checker();
  105. check.warning = function(msg,pos) {
  106. haxe.macro.Context.warning(msg, pos);
  107. };
  108. check.loadShader = loadShader;
  109. var shader = check.check(name, shader);
  110. //trace(shader);
  111. //Printer.check(shader);
  112. var serializer = new hxsl.Serializer();
  113. var str = Context.defined("display") ? "" : serializer.serialize(shader);
  114. f.kind = FVar(null, { expr : EConst(CString(str)), pos : pos } );
  115. f.meta.push({
  116. name : ":keep",
  117. pos : pos,
  118. });
  119. function makeField(name: String, arr: Array<String>) : Field
  120. {
  121. return {
  122. name: name,
  123. access: [APublic, AStatic],
  124. kind: FVar(macro : Array<String>, macro $v{arr}),
  125. pos: f.pos,
  126. meta: [{
  127. name : ":keep",
  128. pos : pos,}
  129. ],
  130. };
  131. }
  132. var finalMap : Map<Int, hrt.shgraph.SgHxslVar> = [];
  133. for (v in shader.vars) {
  134. var info = varmap.get(v.name);
  135. if (info != null) {
  136. var serId = @:privateAccess serializer.idMap.get(v.id);
  137. finalMap.set(serId, info);
  138. }
  139. }
  140. fields.push(
  141. {
  142. name: "_variablesInfos",
  143. access: [APublic, AStatic],
  144. kind: FVar(macro : Map<Int, hrt.shgraph.SgHxslVar>, macro $v{finalMap}),
  145. pos: f.pos,
  146. meta: [{
  147. name : ":keep",
  148. pos : pos,}
  149. ],
  150. }
  151. );
  152. } catch( e : hxsl.Ast.Error ) {
  153. fields.remove(f);
  154. Context.error(e.msg, e.pos);
  155. }
  156. default:
  157. }
  158. }
  159. }
  160. return fields;
  161. }
  162. static function loadShader( path : String ) {
  163. var m = Context.follow(Context.getType(path));
  164. switch( m ) {
  165. case TInst(c, _):
  166. var c = c.get();
  167. for( m in c.meta.get() )
  168. if( m.name == ":src" )
  169. return new hxsl.MacroParser().parseExpr(m.params[0]);
  170. default:
  171. }
  172. throw path + " is not a shader";
  173. return null;
  174. }
  175. static function autoRegisterNode() {
  176. var fields = Context.getBuildFields();
  177. var thisClass = Context.getLocalClass();
  178. var cl = thisClass.get();
  179. var clPath = cl.pack.copy();
  180. clPath.push(cl.name);
  181. #if editor
  182. fields.push({
  183. name: "_",
  184. access: [Access.AStatic],
  185. kind: FieldType.FVar(macro:Bool, macro ShaderNode.register($v{cl.name}, ${clPath.toFieldExpr()})),
  186. pos: Context.currentPos(),
  187. });
  188. #end
  189. return fields;
  190. }
  191. #end
  192. }