package;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
class AssetServiceBuilder
{
public static macro function build() : Array<Field>
{
// The build fields of the class being built
var fields = Context.getBuildFields();
// The asset data we want to store into a map
var assetData : AssetData = haxe.Json.parse(sys.io.File.getContent("res/assets.json"));
// The array of expressions representing the final map of assets
var assets = [];
// We use reflection to iterate through fields of the anonymous object that is assetData
for (locale in Reflect.fields(assetData))
{
// This is akin to assetData[locale] or assetData.locale
var l : AssetData.AssetLocaleData = Reflect.field(assetData, locale);
// The array of expressions representing the internal map of assets per platform
var localAssets = [];
for (platform in Reflect.fields(l))
{
var p : AssetData.AssetPlatformData = Reflect.field(l, platform);
// I'm only looking at the assets for a single platform to avoid duplicate keys
if (platform == "ios")
{
for (entry in p)
{
// Note the use of `macro` and expression reification (`$v{}`)
localAssets.push(macro $v{
entry.name} => new Asset($v{locale}, $v{
entry.name}, $v{entry.resource}, $v{entry.type}));
}
}
}
// Note the use of `macro` and expression reification (`$a{}`)
assets.push(macro $v{locale} => $a{localAssets});
}
// We "push" (add) a new field to the class
fields.push({
// Think of this as the line position that will be referenced on error
pos: Context.currentPos(),
// Field name
name: "_assets",
// We won't be adding any metadata
meta: null,
// The field will be a variable of the Map<String, Map<String, Asset>> type, and will contain the array of expressions making up a map
kind: FieldType.FVar(macro : Map<String, Map<String, Asset>>, macro $a{assets}),
// We won't be adding any documentation
doc: null,
// We'll give it private visibility
access: [Access.APrivate]
});
// Once the build macro is done it needs to return the context's build fields
return fields;
}
}