Macros.hx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package hide.tools;
  2. import haxe.macro.Expr;
  3. import haxe.macro.Context;
  4. import haxe.macro.Type;
  5. using haxe.macro.ExprTools;
  6. class Macros {
  7. public static macro function include( packages : Array<String> ) {
  8. includeShaderSources();
  9. for( p in packages )
  10. haxe.macro.Compiler.include(p);
  11. return macro null;
  12. }
  13. #if macro
  14. static function includeShaderSources() {
  15. var paths = [
  16. "h3d/shader/BaseMesh.hx",
  17. "hrt/shader/BaseEmitter.hx",
  18. ];
  19. for (pathStr in paths) {
  20. var path = Context.resolvePath(pathStr);
  21. var dir = new haxe.io.Path(path).dir;
  22. for( f in sys.FileSystem.readDirectory(dir) )
  23. if( StringTools.endsWith(f,".hx") )
  24. Context.addResource("shader/" + f.substr(0, -3), sys.io.File.getBytes(dir + "/" + f));
  25. }
  26. }
  27. public static function buildSaveLoad() {
  28. inline function isSerialized( field : haxe.macro.Field ) : Bool {
  29. return Lambda.find(field.meta, m -> m.name == ":s") != null;
  30. }
  31. inline function isOpt( field : haxe.macro.Field ) : Bool {
  32. return Lambda.find(field.meta, m -> m.name == ":opt") != null;
  33. }
  34. var fields = haxe.macro.Context.getBuildFields();
  35. // Add the call of _save and _load
  36. if( haxe.macro.Context.getLocalClass().get().name == "Prefab" ) {
  37. var loadField : Field = null;
  38. var saveField : Field = null;
  39. for( f in fields ) {
  40. if( f.name == "save" && f.kind.match(FFun(_)) )
  41. saveField = f;
  42. else if( f.name == "load" && f.kind.match(FFun(_)) )
  43. loadField = f;
  44. if( loadField != null && saveField != null )
  45. break;
  46. }
  47. var loadFunction = switch loadField.kind {
  48. case FFun(f): f;
  49. default: null;
  50. }
  51. loadFunction.expr = macro _load(v);
  52. var saveFunction = switch saveField.kind {
  53. case FFun(f): f;
  54. default: null;
  55. }
  56. saveFunction.expr = macro return _save();
  57. fields.push({
  58. name: "_load",
  59. access: [APrivate],
  60. pos: haxe.macro.Context.currentPos(),
  61. kind: FFun({
  62. args: [{ name : "obj", type : (macro:Dynamic) }],
  63. expr: macro return,
  64. params: [],
  65. ret: null
  66. })
  67. });
  68. fields.push({
  69. name: "_save",
  70. access: [APrivate],
  71. pos: haxe.macro.Context.currentPos(),
  72. kind: FFun({
  73. args: [],
  74. expr: macro return {},
  75. params: [],
  76. ret: (macro:Dynamic)
  77. })
  78. });
  79. return fields;
  80. }
  81. // Generate code for every field with :s metadata
  82. var saveExpr : Array<haxe.macro.Expr> = [];
  83. var loadExpr : Array<haxe.macro.Expr> = [];
  84. for( f in fields ) {
  85. if( !isSerialized(f) )
  86. continue;
  87. var name = f.name;
  88. switch f.kind {
  89. case FVar(t, e):
  90. // Don't save a field with his default value
  91. if( e != null )
  92. saveExpr.push(macro if( this.$name != $e ) obj.$name = this.$name);
  93. else {
  94. switch t {
  95. // Basic types default values : https://haxe.org/manual/types-nullability.html
  96. case TPath(p):
  97. if( p.name == "Bool" )
  98. saveExpr.push(macro if( this.$name != false) obj.$name = this.$name);
  99. else if( p.name == "Float" )
  100. saveExpr.push(macro if( this.$name != #if flash NaN #else 0.0 #end ) obj.$name = this.$name);
  101. else if( p.name == "Int" )
  102. saveExpr.push(macro if( this.$name != 0 ) obj.$name = this.$name);
  103. else
  104. saveExpr.push(macro if( this.$name != null ) obj.$name = this.$name);
  105. default:
  106. saveExpr.push(macro if( this.$name != null ) obj.$name = this.$name);
  107. }
  108. }
  109. case FFun(f): saveExpr.push(macro obj.$name = this.$name );
  110. case FProp(get, set, t, e): saveExpr.push(macro obj.$name = this.$name );
  111. }
  112. loadExpr.push(macro if( obj.$name != null ) this.$name = obj.$name );
  113. }
  114. // Generate the functions if not empty
  115. if( saveExpr.length > 0 ) {
  116. saveExpr.insert(0, macro var obj : Dynamic = super._save());
  117. saveExpr.push(macro return obj );
  118. fields.push({
  119. name: "_save",
  120. access: [AOverride, APrivate],
  121. pos: haxe.macro.Context.currentPos(),
  122. kind: FFun({
  123. args: [],
  124. expr: macro $b{saveExpr},
  125. params: [],
  126. ret: (macro:Dynamic)
  127. })
  128. });
  129. }
  130. if( loadExpr.length > 0 ) {
  131. loadExpr.insert(0, macro super._load(obj));
  132. fields.push({
  133. name: "_load",
  134. access: [AOverride, APrivate],
  135. pos: haxe.macro.Context.currentPos(),
  136. kind: FFun({
  137. args: [{ name : "obj", type : (macro:Dynamic) }],
  138. expr: macro $b{loadExpr},
  139. params: [],
  140. ret: null
  141. })
  142. });
  143. }
  144. return fields;
  145. }
  146. #end
  147. }