Preloader , now that NMEPreloader is depreciated

hi pozirk,

Iā€™ve been wasting my morning trying to restore the same functionality as NMEPreloader, without NMEPreloader, and have so far only managed to get some of the functionality back for flash targets. (not html).

in my project.xml i have ā€¦

<app preloader="MyPreloader" />

and iā€™ve added unique listeners to MyPreloader, as follows

Lib.current.loaderInfo.addEventListener (openfl.events.Event.COMPLETE, loaderInfo_onComplete);
Lib.current.loaderInfo.addEventListener (openfl.events.Event.INIT, loaderInfo_onInit);
Lib.current.loaderInfo.addEventListener (ProgressEvent.PROGRESS, loaderInfo_onProgress);

you can then check Lib.current.loaderInfo.bytesLoaded , and Lib.current.loaderInfo.bytesTotal to find out load progress (in flash, these come back as null in html weirdly, havenā€™t figure out how to restore any preloading within html yet).

Unfortunatly using this method youā€™ll also have no control over when your Main entry point is launched, unlike the NMEpreloader method which waited until you dispatched an Event.COMPLETE .

If anyone else has a working preloader for flash and html which can show simply load progress and give the developer control over when the Main entry point is launched, please do share !

Hey guys,

I just tried to create a custom preloader, itā€™s not fancy, but this worked:

package;


import openfl.display.Sprite;
import openfl.events.Event;


@:keep class Preloader extends Sprite {
	
	
	private var progress:Sprite;
	
	
	public function new () {
		
		super ();
		
		progress = new Sprite ();
		progress.graphics.beginFill (0xFF0000);
		progress.graphics.drawRect (0, 0, 100, 100);
		addChild (progress);
		
		progress.scaleX = 0;
		
		
	}
	
	
	public function onInit ():Void {
		
		trace ("init");
		
	}
	
	
	public function onLoaded ():Void {
		
		trace ("loaded");
		
		var delay = 60;
		
		addEventListener (Event.ENTER_FRAME, function (_) {
			
			delay--;
			
			if (delay == 0) {
				
				trace ("delayed start");
				dispatchEvent (new Event (Event.COMPLETE));
				
			}
			
		});
		
	}
	
	
	public function onUpdate (bytesLoaded:Int, bytesTotal:Int):Void {
		
		trace ("update: " + bytesLoaded + "/" + bytesTotal);
		
		if (bytesTotal == 0) {
			
			progress.scaleX = 0;
			
		} else {
			
			progress.scaleX = bytesLoaded / bytesTotal;
			
		}
		
	}
	
	
}

FYI, currently OpenFL will skip the preloader on native builds, and will skip on Flash or HTML5 if it is already before it would initialize a preloader. We could possibly change this if thereā€™s important logic in the custom preloaders, let me know.

I used <app preloader="Preloader" /> and tested on HTML5 to see the above work

Iā€™m also open to ideas if you think the system can be improved, perhaps it should be something related to LoaderInfo? For example:

class Preloader extends Sprite {
	
	
	public function new (loaderInfo:LoaderInfo) {
		
		super ();
		
		loaderInfo.addEventListener (Event.COMPLETE, loaderInfo_onComplete);
		loaderInfo.addEventListener (ProgressEvent.PROGRESS, loaderInfo_onProgress);
		
	}
	
	
	...
	
	
	private function loaderInfo_onComplete (event:Event):Void {
		
		dispatchEvent (event);
		
	}
	
	
}

Or perhaps (even better) have the loaderInfo set already, and donā€™t pass it in

class Preloader extends Sprite {
	
	
	public function new () {
		
		super ();
		
		loaderInfo.addEventListener (Event.COMPLETE, loaderInfo_onComplete);
		loaderInfo.addEventListener (ProgressEvent.PROGRESS, loaderInfo_onProgress);
		
	}
	
	
	...
	
	
	private function loaderInfo_onComplete (event:Event):Void {
		
		dispatchEvent (event);
		
	}
	
	
}

What do you think?

Hi Joshua, thanks for your reply on this.

Iā€™ve grasped parts of your preloader, and see that the functions onInit(), onLoaded, and onUpdate(bl:int, bt:Int) , are indeed triggered under html. (and work in a similar way to overriding NMEpreloader which is also still working there). I have a quick question regarding this, how would someone like me, be able to discover what the function names should be in a custom preloader if you werenā€™t here to write them on a forum for me ?

Your example does work for html, and it goes bring back the ability to trigger Event.COMPLETE when a developer is ready. It doesnā€™t however currently skip on native builds, the new() function of a custom preloader excecute on flash, neko, windows and mobile(android), just as a preloader created previously overriding NMEPreloader would do on all of those targets - however onInit(), onLoaded(), and onUpdate(bl:int, bt:Int) arenā€™t being triggered on any of those targets any more. and Event.COMPLETE is being dispatched without any developer control. Am i just describing a Bug ? and is this simple not working as Intended ?

My personal preference would be to go back to how things were. keep the entry in the project.xml, and have a single class to override if the developer wishes to update progress, or perform any further tasks before the main entry point is launched.

passing LoadeInfo to any preloader would be beneficial ! - in your html example above i cannot fathom where to query bytesloaded directly, and couldnā€™t find it other than within your onUpdate function - whereas for flash it can be queried at Lib.current.loaderInfo.bytesLoaded. (but always 0 on html)

Ah, youā€™re right ā€“ I didnā€™t realize that new was called even on native.

Iā€™m leaning strongly toward a Sprite and an Event.COMPLETE dispatch when complete, then to handle progress, you can listen to itā€™s loaderInfo object. I think that would be even more Flash-like than the current system

Having LoaderInfo on hand would be nice, but I simply need it to work, preferably on all the targets :slight_smile:
Because now, with latest OpenFL/Lime. Preloader stopped working even in Legacy mode.

OpenFL 4 has no legacy :wink:

Does this work? :slight_smile:

Not on Flash. :confused: onInit, onLoad and onUpdate are not being called.
I should do the following to start it working:

Lib.current.loaderInfo.addEventListener(Event.COMPLETE, onLoaded);
Lib.current.loaderInfo.addEventListener(Event.INIT, onInit);
Lib.current.loaderInfo.addEventListener(ProgressEvent.PROGRESS, onUpdate);

But even with this I canā€™t control when to launch Main entry. Pretty much the same as @Penry wrote.
Or is it a new way of doing preloader now?

1 Like

OpenFL is designed to skip the preloader if things are already loaded

itā€™s just broken for flash at the moment it seems @pozirk. If we can get the functionality which @singmajesty has shown still works in html, back into flash, all would be good i think !!?

for neko and windows .exe files, thereā€™s a single file to load, so thereā€™s obviously no ā€œpreloadingā€ going on once the first code has executed - once loaded it jumped through any preloader and proceeds to the main entry point - unfortunatly this is happening for flash at the moment, but iā€™m pretty sure now that is just a bug awaiting remedy ! - Should neko, windows and android completely omit a preloader ? even if it is set for those targets in the project.xml ? Iā€™m undecided personally. - there seems little point in running code within a preloader, if it can be run within main once everythingā€™s loaded !? but would removing the running of code within a defined preloader just cuase inconsistencies between targets for some projects ?

for android .apk , it would be fantastic if a preloader could exist!, iā€™ve never investigated how that is done, but if it were possible to create an android preloader, and have it defined as simply as overriding NMEPreloader was, that was be a huge benefit !

I am leaning strongly toward a change in OpenFL preloading

We use Sprite as base type, dispatch the progress events through the loaderInfo property, then wait for your preloader to dispatch Event.COMPLETE before we continue

It would be done on all platforms, and it would be up to you to decide when you dispatch COMPLETE, either immediately, or later.

The only thing is how to handle assets, if preloaders are easy to do, it raises questions of how to embed an image while preloading, before openfl.Assets is available

1 Like

In my preloader I was embedding images like this, it worked even on native platforms, although I am implementing preloader for native platforms differently.:

@:bitmap("assets/preload.jpg") class Back extends BitmapData {}
...
public function new()
{
 back = new Bitmap(new Back(Std.int(w), Std.int(h)), PixelSnapping.AUTO, true);
 addChild(back);
}

similarly iā€™ve been using @:bitmap , (i add preloader assets to a /pre/ folder, which isnā€™t included within an assets path in the project.xml, so the graphics i use in the preloader dont also get added as Assets to the project as well !)

@:bitmap("assets/pre/preloadbar.png") class Pbar extends BitmapData { }

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