Problem creating AssetManifest using parse of json

There seems to be a problem with the parse function on AssetManifest.

var buttons=xml.node.pages.node.controls.nodes.button;
var jsonObject={
	name:"gloryManifest",
	libraryType:null,
	libraryArgs:{},
	basePath:"",
	assets:[],
	version:"2"
};
for(button in buttons){
	jsonObject.assets.push({path:button.att.src, id:button.att.id, type:"bitmap"});
}
var s=haxe.Json.stringify(jsonObject);
var am = AssetManifest.parse(s);

I’ve tried this on HTML5 and Flash, and both targets get an error on that last line. In HTML5 it says “this.buf.charCodeAt is not a function” and it references to Unserializer.hx:234 through AssetManifest.hx:92. It will do this even with an empty array for assets. Any suggestions?

You may notice, the AssetManifest system has gotten closer to maturity, but isn’t completely polished into a formal, stable API.

If you are not creating the asset manifest in the tools (you can add library="mycustomlibname" to any <assets /> tag to push the assets into a manifest other than the default) then I would recommend using new AssetManifest and setting the fields directly. This may still be fragile with changes in the future, but should be cleaner than generating JSON and serializing data, only to unserialize a moment later :wink:

Something like:

var buttons=xml.node.pages.node.controls.nodes.button;
var manifest = new AssetManifest ();
for(button in buttons){
    manifest.assets.push({path:button.att.src, id:button.att.id, type:"bitmap"});
}
var library = AssetLibrary.fromManifest(manifest);

That does it, thanks!

1 Like

Hm, in which “that does it” means I don’t get any errors. However I have this scenario now:

var al=AssetLibrary.fromManifest(am);  //works
Assets.registerLibrary("gloryAssets",al); //works
trace(al); //returns null

My end goal is simply to not have any asset paths hard-coded at compile time so I think I will just go simple and use the Assets class for all my loading.

Looks like it expects a size field for each asset in order to better predict loader progress

Perhaps now that Lime supports creating multiple asset manifests, it may make it simpler to bundle up your assets at compile-time into packs of assets you can load later at runtime using Assets.loadLibrary

However, I am interested ultimately in helping make improvements so that all of this is more transparent and easier to do. I guess we are missing an AssetData class, or something similar?

I can’t say what would be the best all-around solution. For my purposes I am wishing there was something akin to the BulkLoader library which was super-sweet in AS3.

I’ll take another look at runtime asset libraries. If you prefer, you should also be able to extend AssetLibrary and implement getBitmapData and exists yourself

1 Like

Back at this…

I have been able to successfully make an AssetLibrary now but it seems to not retain asset data after loading. I create the AssetManifest, then the AssetLibrary using fromManifest(). Then I register the library (Assets.registerLibrary), and tell it to load all the items using AssetLibrary.loadImage(), which it does—I can see them loading in the network pane of my browser.

Later on when I want to retrieve image data, I use Assets.getLibrary(libId), which works. Tracing the library shows the asset paths but their sizes are null. So doing getImage(id) on the library does not return any imageData.

Would it be better to simply save a persistent reference to the AssetLibrary I created, instead of retrieving it using Assets.getLibrary? Or am I missing a step which would make the AssetLibrary keep the loaded image in memory after loading?

It depends upon your design for the library. One approach would be for the library to preload everything, and retain references. Assets.loadLibrary will then load it all once. Or, you could preload nothing, but then allow Assets to cache the assets (by not setting cache to false) in your load calls. If you request the cache and it does not, that is a bug

My end goal is to build a website framework where the assets can be there at compile time (and so get included in the assets folder) but I don’t want the paths to the assets hard-coded into the compiled javascript. I am using an external xml config file so I can enable users to tweak the site without requiring a recompile.

Using the type=“template” attribute in the tag handles the asset bundling the way I want, i.e. the assets get moved but paths to them are not compiled.

I tried the following:

var am = new AssetManifest();

for(button in assetsList){
	// (here I populate the manifest)
}
var al = GloryAssetLibrary.fromManifest(am);
var libName:String = (pageId==null) ? "gloryControls" : pageId;
Assets.registerLibrary(libName,al);

//if I try Assets.loadlibrary(libName) here, there is no network activity. Is it because it's not "included"?

for (thisControl in assetsList){
// If I use al.loadImage here instead of the following, the files will load but they are not cached by Assets since there's no cache option

//this does not result in network activity:
	Assets.loadBitmapData(thisControl.att.src,true).onComplete(function(e){
		pendingLoads--;
		if(pendingLoads==0){
			commandComplete(); 
		}
	});
}

I believe if you begin loading a library, then it loads the library first, then it’s up to the library what additional resources it wants to load

I got to the point of using loadImage method in AssetLibrary but could not figure out how to retrieve them from cache later on. Seems like they aren’t cached, given that there’s no useCache parameter such as with loadImage method in the Assets class.

It appears that loadBitmapData does have cache enabled, but it calls loadImage internally with no cache set, in order to cache BitmapData on the OpenFL side, rather than the image on the Lime side.

Perhaps this is causing problems somewhere

https://github.com/openfl/openfl/blob/develop/openfl/utils/Assets.hx#L470

I was wondering if loadBitmapData is not working because there is no id or src hard-coded in the compiled Assets, so it doesn’t bother attempting to load it.

Edit: Just looking at Lime/Assets and it appears that I’m correct.

So it appears that right now, loading using loadImage via the AssetsLibrary will work but how can I ensure they get cached after loading?

You were showing AssetLibrary.loadFromManifest() examples at the summit and it looked like they were in the npm samples for OpenFL. I installed the npm version of OpenFL but I’m having trouble finding those samples. Any tips please?

Here’s a few samples that use a custom manifest:

I believe new AssetManifest should work on the Haxelib release, too :slight_smile:

If you want to try out our NPM project samples, you can clone the https://github.com/openfl/openfl-samples-ts, https://github.com/openfl/openfl-samples-es5, https://github.com/openfl/openfl-samples-es6 or https://github.com/openfl/openfl-samples repository. The “openfl-samples” repository has “haxelib” and “npm” folders which then break up into the difference samples.

All the samples should work with npm install then npm start to build and start a hot-reload server

(this is me writing a response then not hitting “submit” for a month!) Ha, I knew it was something easy, thank you! I was doing a text search in my local haxelib directory for openfl-samples and did not realise the npm variant was on Github.

1 Like

And what would be the easiest way to load copied assets from another server (for web targets)?

For example, I have images in assets/img and sounds in assets/snd on the main server, and the same images and sounds in the same folders on another server.
Can I somehow load libraries from the 2nd server at the runtime?

You should be able to load a library from a network location (or make a custom library that uses a different URL for the source asses). This can be done in the “rootPath” property for an asset manifest, I believe.

The big issue with loading from another server is cross-origin request security

What if loadLibrary() also had an optional 2nd parameter “rootPath”?
As far as I understand we need a separate manifest for each path atm.