123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- package hrt.impl;
- import haxe.macro.Context;
- import haxe.macro.Expr;
- class Macros {
- #if macro
- public static function buildPrefab() {
- var fields = Context.getBuildFields();
- var toSerialize = [], toCopy = [];
- var isRoot = Context.getLocalClass().toString() == "hrt.prefab.Prefab";
- var localType = haxe.macro.Tools.TTypeTools.toComplexType(Context.getLocalType());
- var changed = false;
- for( f in fields ) {
- if( f.name == "copy" && !isRoot ) {
- // inject auto cast to copy parameter
- switch( f.kind ) {
- case FFun(f) if( f.args.length == 1 && f.expr != null ):
- var name = f.args[0].name;
- var expr = f.expr;
- f.expr = macro @:pos(f.expr.pos) { var $name : $localType = cast $i{name}; $expr; }
- changed = true;
- default:
- }
- }
- if( f.meta == null ) continue;
- for( m in f.meta ) {
- switch( m.name ) {
- case ":s":
- toSerialize.push(f);
- case ":c":
- toCopy.push(f.name);
- default:
- }
- }
- }
- if( toSerialize.length + toCopy.length == 0 )
- return changed ? fields : null;
- var ser = [], unser = [], copy = [];
- var pos = Context.currentPos();
- for( f in toSerialize ) {
- switch( f.kind ) {
- case FProp(_, _, t, e), FVar(t,e):
- var name = f.name;
- var serCond = null;
- if( e == null ) {
- var setDef = true;
- var c : Constant = switch( t ) {
- case null: Context.error("Invalid var decl", f.pos);
- case TPath({ pack : [], name : "Int"|"Float" }): CInt("0");
- case TPath({ pack : [], name : "Bool" }): CIdent("false");
- default: setDef = false; CIdent("null");
- }
- e = { expr : EConst(c), pos : f.pos };
- if( setDef ) {
- f.kind = switch( f.kind ) {
- case FVar(t,_): FVar(t,e);
- case FProp(get,set,t,_): FProp(get,set,t,e);
- default: throw "assert";
- }
- }
- } else {
- var echeck = e;
- if( e.expr.match(EArrayDecl([])) )
- serCond = macro @:pos(f.pos) this.$name.length != 0;
- }
- if( serCond == null ) {
- var defVal = e.expr.match(EConst(_) | EBinop(_) | EUnop(_)) ? e : macro @:pos(f.pos) null;
- serCond = macro @:pos(pos) this.$name != $defVal;
- }
- ser.push(macro @:pos(pos) if( $serCond ) obj.$name = this.$name);
- unser.push(macro @:pos(pos) this.$name = obj.$name == null ? $e : obj.$name);
- copy.push(macro @:pos(pos) this.$name = p.$name);
- default:
- Context.error("Invalid serialization field", f.pos);
- }
- }
- for( name in toCopy ) {
- copy.push(macro @:pos(pos) this.$name = p.$name);
- }
- if( !isRoot ) {
- ser.unshift(macro @:pos(pos) super.saveSerializedFields(obj));
- unser.unshift(macro @:pos(pos) super.loadSerializedFields(obj));
- copy.unshift(macro @:pos(pos) var p : $localType = cast p);
- copy.unshift(macro @:pos(pos) super.copySerializedFields(p));
- }
- function makeFun(name,block) : Field {
- return {
- name : name,
- kind : FFun({
- ret : null,
- expr : { expr : EBlock(block), pos : pos },
- args : [{ name : "obj", type : macro : Dynamic }],
- }),
- meta : [{ name : ":noCompletion", pos : pos }],
- access : isRoot ? [] : [AOverride],
- pos : pos,
- };
- }
- if( toSerialize.length > 0 ) {
- fields.push(makeFun("saveSerializedFields",ser));
- fields.push(makeFun("loadSerializedFields",unser));
- }
- fields.push({
- name : "copySerializedFields",
- kind : FFun({
- ret : null,
- expr : { expr : EBlock(copy), pos : pos },
- args : [{ name : "p", type : macro : hrt.prefab.Prefab }],
- }),
- meta : [{ name : ":noCompletion", pos : pos }],
- access : isRoot ? [] : [AOverride],
- pos : pos,
- });
- return fields;
- }
- #end
- }
|