ParseFieldsMacro.hx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package hrt.shgraph;
  2. import haxe.macro.Context;
  3. import haxe.macro.Expr;
  4. using haxe.macro.Tools;
  5. class ParseFieldsMacro {
  6. #if macro
  7. public static function build() : Array<Field> {
  8. var fields = Context.getBuildFields();
  9. var mapInputs = new Array<Expr>();
  10. var inputsList = new Array<String>();
  11. var hasInputs = false;
  12. var mapOutputs = new Array<Expr>();
  13. var outputsList = new Array<String>();
  14. var hasOutputs = false;
  15. for ( f in fields ) {
  16. if( f.meta == null ) continue;
  17. switch (f.kind) {
  18. case FVar(t, e):
  19. var saveMeta = f.meta;
  20. for (m in saveMeta) {
  21. if (m.name == "input") {
  22. hasInputs = true;
  23. var sel = f.name;
  24. var get_sel = "get_" + sel;
  25. var propSel = "prop_" + sel;
  26. var hasProperty = false;
  27. var isRequired = true;
  28. var nameInput = "input";
  29. if (m.params.length >= 1) {
  30. switch(m.params[0].expr) {
  31. case EConst(CString(s)):
  32. if (s.length > 0)
  33. nameInput = s;
  34. default:
  35. }
  36. }
  37. if (m.params.length >= 2) {
  38. switch(m.params[1].expr) {
  39. case EConst(CIdent(b)):
  40. if (b == "true") {
  41. hasProperty = true;
  42. fields.push({
  43. name: propSel,
  44. access: [Access.APrivate],
  45. kind: FieldType.FVar(macro:Float),
  46. pos: Context.currentPos(),
  47. meta: [{name: "prop", params: [{expr: EConst(CString("macro")), pos: Context.currentPos() }], pos: Context.currentPos()}]
  48. });
  49. }
  50. default:
  51. }
  52. }
  53. if (m.params.length >= 3) {
  54. switch(m.params[2].expr) {
  55. case EConst(CIdent(b)):
  56. if (b == "false") {
  57. isRequired = false;
  58. }
  59. default:
  60. }
  61. }
  62. if (hasProperty) {
  63. var sfields = macro class {
  64. inline function $get_sel() : NodeVar {
  65. var input = getInput($v{sel});
  66. if (input == null)
  67. return new NodeVar(new hrt.shgraph.nodes.FloatConst($i{propSel}), "output");
  68. else
  69. return getInput($v{sel});
  70. }
  71. };
  72. for( field in sfields.fields )
  73. fields.push(field);
  74. } else {
  75. var sfields = macro class {
  76. inline function $get_sel() : NodeVar return getInput($v{sel});
  77. };
  78. for( field in sfields.fields )
  79. fields.push(field);
  80. }
  81. if (e == null)
  82. Context.error('Input ${sel} has not affectation', f.pos);
  83. var enumValue = ["ShaderType", "SType", e.toString().split(".").pop()];
  84. mapInputs.push(macro $v{sel} => { name : $v{nameInput}, type : ${enumValue.toFieldExpr()}, hasProperty: $v{hasProperty}, isRequired : $v{isRequired} });
  85. f.kind = FProp("get", "null", TPath({ pack: ["hrt", "shgraph"], name: "NodeVar" }));
  86. f.meta = saveMeta;
  87. inputsList.push(f.name);
  88. break;
  89. } else if (m.name == "output") {
  90. hasOutputs = true;
  91. var sel = f.name;
  92. var get_sel = "get_" + sel;
  93. var sfields = macro class {
  94. inline function $get_sel() : TVar return getOutput($v{sel});
  95. };
  96. for( field in sfields.fields )
  97. fields.push(field);
  98. if (e == null)
  99. Context.error('Output ${sel} has not affectation', f.pos);
  100. var nameOutput = "";
  101. if (m.params.length > 0) {
  102. switch(m.params[0].expr) {
  103. case EConst(CString(s)):
  104. if (s.length > 0)
  105. nameOutput = s;
  106. default:
  107. }
  108. }
  109. var enumValue = ["ShaderType", "SType", e.toString().split(".").pop()];
  110. mapOutputs.push(macro $v{sel} => { name : $v{nameOutput}, type : ${enumValue.toFieldExpr()} });
  111. f.kind = FProp("get", "null", TPath({ pack: [], name: "TVar" }));
  112. f.meta = saveMeta;
  113. outputsList.push(f.name);
  114. break;
  115. }
  116. }
  117. default:
  118. }
  119. }
  120. if (hasInputs) {
  121. fields.push({
  122. name: "inputsInfo",
  123. access: [Access.APrivate],
  124. kind: FieldType.FVar(macro:Map<String, ShaderNode.InputInfo>, macro $a{mapInputs}),
  125. pos: Context.currentPos(),
  126. });
  127. var sfields = macro class {
  128. override public function getInputInfo(key : String) : ShaderNode.InputInfo return inputsInfo.get(key);
  129. override public function getInputInfoKeys() : Array<String> return $v{inputsList};
  130. };
  131. for( field in sfields.fields )
  132. fields.push(field);
  133. }
  134. if (hasOutputs) {
  135. fields.push({
  136. name: "outputsInfo",
  137. access: [Access.APrivate],
  138. kind: FieldType.FVar(macro:Map<String, ShaderNode.OutputInfo>, macro $a{mapOutputs}),
  139. pos: Context.currentPos(),
  140. });
  141. var sfields = macro class {
  142. override public function getOutputInfo(key : String) : ShaderNode.OutputInfo return outputsInfo.get(key);
  143. override public function getOutputInfoKeys() : Array<String> return $v{outputsList};
  144. };
  145. for( field in sfields.fields )
  146. fields.push(field);
  147. }
  148. var thisClass = Context.getLocalClass();
  149. var cl = thisClass.get();
  150. var clPath = cl.pack.copy();
  151. clPath.push(cl.name);
  152. #if editor
  153. fields.push({
  154. name: "_",
  155. access: [Access.AStatic],
  156. kind: FieldType.FVar(macro:Bool, macro ShaderNode.register($v{cl.name}, ${clPath.toFieldExpr()})),
  157. pos: Context.currentPos(),
  158. });
  159. #end
  160. return fields;
  161. }
  162. #end
  163. }