How to have an "alternate" assets library

So I’m making a surprise for someone, who sometimes comes into the room while I’m working. This person will not notice text mentioning them but they would sure notice the graphics I have prepared, so I can only work on that set when they’re not around.

I thought it would be fairly easy to make a quick compile flag that switched to a placeholder library that I could use when they’re around, but it’s trickier than I thought for some reason.

Flash target at the moment, BTW, but I plan to target windows, it’s just faster during development to compile flash.

In my Project.xml (it’s a HaxeFlixel game, but I think it applies to OpenFL since that’s where that xml is processed) I have:

    <assets path="assets" unless="SECRET" />
    <assets path="secretassets" if="SECRET" />

And then AssetPaths.hx I modify like this:

package;

@:build(flixel.system.FlxAssets.buildFileReferences(#if SECRET "secretassets" #else "assets" #end, true))
class AssetPaths {}

What this does correctly is autocompletion in FlashDevelop: I type “AssetPaths.” and the secret ones come up instead of the regular ones, if and only if I have <haxedef name="SECRET"/> in my Project.xml. If I don’t have it, I get the regular assets directory’s assets. (I know they should be the same normally, but I made them each have a unique file in them just to test this.)

And the paths returned by AssetPaths are correct, e.g. if I trace AssetPaths.seaweed1__png with the secret enabled I get secretassets/images/seaweed1.png.

The problem is, they don’t seem to be included in the compiler output, because then I get runtime errors in the haxeflixel debug console saying things like [ERROR] Could not find a BitmapData asset with ID 'secretassets/images/seaweed1.png'. and the image gets replaced with a generic haxeflixel logo placeholder.

Is there a ‘right way’ to get this to work, or am I once again trying something a little too fancy? :slight_smile:

Oh wait, now I see it. They are included…yet for some reason (at least on windows output, which I just tried) they’re included in a folder “assets” and the program is looking for “secretassets”.

Yet, if I put rename="assets" in the xml, I get the same errors, this time because AssetPaths is returning stuff from secretassets because of my modification to it. But if I then undo that, so that AssetPaths looks in “assets” no matter what, then autocompletion is broken, and also my project won’t compile if I’ve added something to secretassets that I haven’t yet made a placeholder for in “assets”, because Class<AssetPaths> has no field seaweed1__png. Is there no way to have it both ways?

Looks like buildFileReferences() is your problem. It doesn’t support a rename parameter. The solution is to implement your own:

macro public static function buildFileReferences(directory:String = "assets/", rename:String = null, subDirectories:Bool = false, ?filterExtensions:Array<String>):Array<Field>
{
    if (!directory.endsWith("/"))
        directory += "/";
    if (rename != null && !rename.endsWith("/"))
        rename += "/"
    
    @:privateAccess
    var fileReferences:Array<FileReference> = FlxAssets.getFileReferences(directory, subDirectories, filterExtensions);
    
    var fields:Array<Field> = Context.getBuildFields();
    for (fileRef in fileReferences)
    {
        // apply the replacement
        if (rename != null)
            fileRef.value = fileRef.replace(directory, rename);
        
        // create new field based on file references!
        fields.push({
            name: fileRef.name,
            doc: fileRef.documentation,
            access: [Access.APublic, Access.AStatic, Access.AInline],
            kind: FieldType.FVar(macro:String, macro $v{fileRef.value}),
            pos: Context.currentPos()
        });
    }
    return fields;
}

Make a new class, copy the imports from FlxAssets.hx, and add this function. Then use this function instead of FlxAssets.buildFileReferences to build AssetPaths.

Wow, thanks very much! I’m kind of surprised it doesn’t support rename out of the box, since HF documents how to use it in Project.xml. Maybe we can send this in… now that I think of it I think maybe HF has two different asset loaders going on, or something like that.

Looks like they copied OpenFL’s documentation. And it’s true: you can use OpenFL’s Assets class in Flixel. Skip buildFileReferences() entirely, and call Assets.getBitmapData("assets/images/seeweed1.png") instead.