Loading assets dynamically from disk (not from a library)

I’m wondering how can i accomplish that with OpenFL 5.1.5 on desktop (Windows and Mac). Both Assets.getSound and Assets.loadSound expect a library id instead of a local path.

The use-case is:

  • I have some user-defined xml files which can have reference to audio files
  • These audio files are added by users to application folder (e.g. “exe_folder\assets\audio”)
  • Then when the program runs it should load the files declared in the xml
  • This fails with a null pointer error because Assets apparently only work with assets identified at compile time.

So, how can i dynamically load assets that aren’t part of the library? I know i can implement my own loader, but i thought openfl.Assets should have this functionality shouldn’t it?

Thanks

You have to create your own loader to load bunch of files.
I have the same situation when I build casino game (lobby) where from I should load different games with different assets (graphics, audio).
In my case I create custom loader where I just loop through list of the files names and then call

Assets.loadBitmapData(fullImagePath);
Assets.loadSound(soundToLoad).onComplete(onSoundLoaded);

Once it’s loaded I keep it in buffer (Assets class keep it I just take care to not delete it)
All files are defined in xml file. Example:

<graphics id="XHD">
		<image path="/BestOfBook/GameGraph/">xhd.xml</image>
		<image path="/BestOfBook/Symbols/">sxhd0.xml</image>
		<image path="/BestOfBook/Symbols/">sxhd1.xml</image>
		<image path="/BestOfBook/Symbols/">sxhd2.xml</image>
		<image path="/Gamble/">gxhd0.xml</image>
	</graphics>
<graphics id="MD">
	<image path="/BestOfBook/GameGraph/">md.xml</image>
	<image path="/BestOfBook/Symbols/">smd0.xml</image>
</graphics>

<sounds>
		<sound>adventurebook_bonus_game_loop</sound>
		<sound>adventurebook_button_bet</sound>
		<sound>adventurebook_button_click_new</sound>
</sounds>

As you can see I load TextureAtlas for graphics and I even choose what resolution I should load.

1 Like

We have some APIs that may help make it simpler to load files:

BitmapData.loadFromFile ("path/to/image.png").onComplete (function (bitmapData) {
    trace ("loaded");
}).onError (function (e) {
    trace ("error");
}).onProgress (function (loaded, total) {
    trace ("loaded " + loaded + "/" + total);
});

We don’t have an API to combine multiple requests into one progress queue at the moment, though.

1 Like

@gonzos Thanks for the reply, but unfortunately that’s not my problem. As i mentioned, Assets.loadSound simply returns null in onComplete because the asset itself is only added to the folder after compilation and thus is not recognized as an embedded / included asset. :slight_smile:

@singmajesty Thanks Josh, that looks like what i need! Is this asynchronous for all targets?

Yep, I think it’s asynchronous for all targets :slight_smile:

There are similar methods on other core objects like ByteArray and Sound

1 Like

Thanks!

It appears that Sound.fromFile is synchronous (there is no loadFromFile method and it returns a Sound object instead of a loader).

Not a problem though - looks like the correct way to load audio asynchronously is to use lime.media.AudioBuffer.fromFile which returns a Future object, then in the onComplete method you can use Sound.fromAudioBuffer.

Yeah, it looks like currently you can do:

AudioBuffer.loadFromFile ("sound.ogg").then (function (audioBuffer) {
    return Future.withValue (Sound.fromAudioBuffer (audioBuffer));
}).onComplete (function (sound) {
    trace ("loaded");
});

Not sure why Sound.loadFromFile doesn’t exist, seems like an oversight :slight_smile:

EDIT: Perhaps it is because there already is a sound.load that is asynchronous, but perhaps we should have both for consistency

EDIT 2: Added :smile:

1 Like