Macros.hx 4.4 KB

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