Preloader , now that NMEPreloader is depreciated

Hi guys,

I just finished writing the new logic for preloading in the OpenFL Github version. Let me explain how it works:

Every project has two entry points, the first is the preloader (optional), and the second is the document class, or main class.

The document class will be built if preloading is complete, which finishes instantly (currently) on native, but may take time, even locally, on Flash or HTML5. Instead of a custom architecture, I’ve relied upon the existing Flash paradigm of LoaderInfo to get our events.

There is one rule to a custom preloader – you must dispatch Event.COMPLETE to continue to your document class. If you do not, your application will stay on the preloader.

In order to display progress, listening to Event.ADDED_TO_STAGE (similar to the old onInit) and then responding to ProgressEvent.PROGRESS and Event.COMPLETE from the loaderInfo object will provide progress information.

This is much more like how an ordinary preloader would work, with the exception that we build everything into one file, instead of two, which is more convenient :smile:

Amazing!
Looking forward to try it.

What am I supposed to upgrade for using the new preloading method ? OpenFL only ?
A bit of off topic, but is their any way, by which my projects while building, somehow get automatically labelled with what versions of libraries openfl,hxcpp,actuate,lime,nme etc is using ?

Yes, you could use something like

import haxe.macro.Compiler;

..

trace (Compiler.getDefine ("openfl"));
trace (Compiler.getDefine ("lime"));

You can also use that value elsewhere, all up to what you prefer :slight_smile:

1 Like

I downloaded the github version to try out the new preloading.I get this error:

…/openfl/Assets.hx:9: characters 7-30 : Type not found : lime.utils.AssetLibrary
Build halted with errors.

Also, a new problem I am noticing is that all the bitmaps that were break apart in the flash ide, are now showing as whole original bitmap. This is not any serious though. But it used to work good earlier.

I’ve just updated to openfl 4.5.1 , lime 3.5.1 , and tested the CustomPreloader included in the notes.

Everything seems alot tidier than before. The use of event.preventDefault(), works well (once i’d figured out i have to removeEventListener (Event.COMPLETE, this_onComplete); , before i trigger dispatchEvent (new Event (Event.COMPLETE)); to exit the preloader. working for me for flash, html5, neko, windows and android.

The problem i have now, is embedding assets, as using @:bitmap fails with the following error on html5, neko, windows, and android since updating, (only working now on flash)

D:/dev/HaxeToolkit/haxe/lib/openfl/4,5,1/openfl/display/BitmapData.hx:72: characters 2-11 : Method embedBitmap not found on class openfl.Assets
bin/windows/cpp/debug/haxe/ApplicationMain.hx:94: characters 14-29 : Called from macro here
bin/windows/cpp/debug/haxe/ApplicationMain.hx:94: characters 2-29 : Void should be openfl.display.Preloader
Build halted with errors.

has @:bitmap embedding been removed from everything but flash ? or is this just a bug with the latest version

I’m kind of having the same problem with @bitmap, something is messed up.
This works for Flash:

@:bitmap("assets/preload.jpg") class Back extends BitmapData {}

And this works for Windows and Android, but I see white screen instead of my image:

@:bitmap("assets/preload.jpg") class Back extends Bitmap {}

This is a bug, we don’t test this in our unit tests, or most of the projects I touch during development, I guess! :frowning:

Does changing it to lime.utils.Assets.embedBitmap at the head of the file work differently? I’ll try and take a look at it tomorrow if that does not help

If we wanted, we could think of using a different event type, such as ProgressEvent.PROGRESS, then Event.COMPLETE, then Event.UNLOAD, Event.CLOSE or some other combination.

The nice thing about Event.COMPLETE is that it bubbles, so unhandled, it triggers the same “okay, preloader is done” behavior, but having to removeEventListener sounds slightly confusing

a similar error when trying lime.utils.assets.embedBitmap() - “Method embedBitmap not found on class lime.utils.Assets”

Yes, listening to Event.COMPLETE, preventing it from bubbling and then stop listening in order to fire it yourself is a little bit confusing. :slight_smile:

I think all the confusion because of 2 entry points, while it should be only one.
It’s better to listen for Event.ADDED_TO_STAGE, Event.COMPLETE and ProgressEvent.PROGRESS in my Main class, do preloading animation, etc., and avoid this confusion.
I’m sure, it’s much easier to code, if there is only 1 entry point.

Btw, I get a different error message for native:

Error: Preloader.cpp
./src/com/pozirk/tools/Preloader.cpp(84) : error C2660: 'com::pozirk::tools::Back_obj::__alloc' : function does not take 5 arguments

Where com.pozirk.tools.Back is

@:bitmap("assets/preload.jpg") class Back extends BitmapData {}

Here is line 84 of Preloader.cpp

HXDLIN(  48)		HX_VARI_NAME(  ::openfl::display::BitmapData,bmpd1,"bmpd") =  ::com::pozirk::tools::Back_obj::__alloc( HX_CTX ,bmpd,::Std_obj::_hx_int(h),null(),null());

Does this patch help with the embed?

Here’s another idea on the events, what do you think?

addEventListener (Event.COMPLETE, this_onComplete);
addEventListener (ProgressEvent.PROGRESS, this_onProgress);

...

private function this_onComplete (event:Event):Void {
    
    // optionally
    event.preventDefault ();
    
    Timer.delay (function () {
        parent.removeChild (this); // application waits for REMOVED_FROM_STAGE to continue, default removes the preloader from the stage automatically, preventing default means you must remove the preloader yourself
    }, 1000);
    
}

EDIT: The other alternative I’m considering is

dispatchEvent (new Event (Event.CLOSE));

or

dispatchEvent (new Event (Event.UNLOAD));

Thanks for the feedback

It seems that new preloader receives only 2 progress events, one for 0 or 1, seconds for 1 of 1, so visually it looks like “0%”… some time ago “100%” and game loaded.

I prepare PR to fix it:

P. S. Not related to topic, but also this PR fixes font preloading in Safari (it is not related to font preloading bug that fixed in 3.5.2).

Does a newer version work any differently?

Anyone have feedback on we remove / unload the preloader? Thank you :slight_smile:

with previous version bitmap wasn’t shown in html5. In newer version it is, but still weird numbers on loading info. This is my trace:

update: 0
update: 1
update: 0.8440901070310789
update: 0.8440901070310789
update: 1
update: 1
update: 1

public function onUpdate (e:ProgressEvent):Void 
	{
		
		trace ("update: "+(e.bytesLoaded / e.bytesTotal) );
		
		if (e.bytesTotal == 0) {
			
			progress.scaleX = 0;
			
		} else {
			
			progress.scaleX = e.bytesLoaded / e.bytesTotal;
			
		}
		
	}

There is some similar bug on Flash target, but it’s still acceptable.

var percentLoaded = pe.bytesLoaded / pe.bytesTotal;
trace("update "+percentLoaded+" / "+pe.bytesLoaded+" / "+pe.bytesTotal);

gives the following results:

update 0 / 0 / 1
update 1 / 1 / 1
update 0.06629267788390245 / 327680 / 4942929
update 0.06629267788390245 / 327680 / 4942929
update 0.07955121346068293 / 393216 / 4942929
update 0.09280974903746342 / 458752 / 4942929

update 1 / 4942929 / 4942929
update 1 / 1 / 1

Also I would go with one entry point at Main class where all the preloading things/events can be easily done and no confusion/extra coding.
If you are willing to stay with current Two entry points, I would go with an extra even, something like

dispatchEvent (new Event (Event.READY));

or

dispatchEvent (new Event (Event.START));

would be more obvious for me.

1 Like

thanks for update, @:Bitmap working for me within preloader now (where it wasn’t) on html5, windows, neko targets (will test android when i can);
@restorer posted that ProgressEvent.PROGRESS is only firing twice during loading for html target. I’m experience that also.
any event syntax to dismiss the preloader which doesn’t cause confusion would be sufficient i think !.

Oh, forgot those weren’t standard events. Will have to keep thinking

I have just updated the custom preloader behavior

Now the preloader dispatches ProgressEvent.PROGRESS then Event.COMPLETE while loading. The default will dispatch an Event.UNLOAD on COMPLETE to signal the ApplicationMain class to unload the preloader and execute the document (or “main”) class.

If you choose, you can event.preventDefault on Event.COMPLETE, and dispatch Event.UNLOAD at a time of your own choosing. This method allows us to use Event without adding new values to the class, and I think is consistent with the idea that the preloader will be unloaded, and the main application will be run. I agree that dispatching Event.COMPLETE a second time (and therefore having to remove your listener first) is more confusing.

I hope that this will be a better architecture with less special rules. Preloaders on mobile/desktop has been a long-requested feature, and I think the custom preloader extending a generated NMEPreloader class is not as friendly.

2 Likes

In fact, we might even use a separate SWF, JS file or executable to enforce a strict boundary between the preloader and the main application in the future. That would remove some restrictions we currently have (such as maximum SWF size), and perhaps make the preloading even more reliable. This is unimportant right now, but might support the Event.UNLOAD event more