engine.displayLoadingUI(); run order

Hello,
Here is some pseudo code
engine.displayLoadingUI();
– DIspose of 1000 meshes … Rebuild 1000 meshes from data
engine.hideLoadingUI();

I want to use the loading screen to let the user know the computer is working while it is rebuilding the scene but even though I call displayLoadingUI before I dispose and rebuild the scene the Loading Screen only displays after the rebuild, so the user experience is that the computer seems to hang and they actually don’t see the loading screen because hideLoadingUI is called right after.

In practice it runs more like this:
– DIspose of 1000 meshes … Rebuild 1000 meshes from data
engine.displayLoadingUI();
engine.hideLoadingUI();

Is there a way to prioritize the loading screen…maybe in the render loop?

Hi gamedev44,

Can you post a Playground? Off the top of my head, this sounds like an issue with all these calls being synchronous; if that’s the case, even though you told the Engine to show a loading UI, execution will block on the mesh disposal and the frame containing the loading UI won’t even get generated until after the disposal and recreation have finished. If that’s the problem, you might be able to work around it by spreading your scene recreation across many frames, “coroutine-style.” But again, this’ll be much easier to think clearly about with a Playground to look at. :slight_smile:

https://www.babylonjs-playground.com/#M13SAY#3

Here is one, if you jack up the variable max, it will stall but you won’t see the loading screen… Thanks

Yep, definitely looks like an issue with synchronous calls. This is a rather hack-ish way to go about this; but does this more along the lines of the behavior you were going for?

https://www.babylonjs-playground.com/#M13SAY#4

Yes thats the behaviour, but I’m leary of using timeouts as a fix…not know how consistent that will work across all systems.

Okay. I’m not sure there’s going to be a way to get it really smooth without using a timeout to limit the number of meshes being processed on a single frame. That said, the less hack-ish way you probably would want to go about it, at least at the top level, would be with a Promise.

Bottom line, if you want the loading UI to display, you need to call displayLoadingUI() and hideLoadingUI() on separate frames; calling them on the same frame, one right after the other, will just be a no-op. My understanding (sorry, still a little new to JavaScript) is that setTimeout() can be a little imprecise, but it should be at least good enough to let you set things to happen on different frames.

Good news, though: Babylon actually has a tool for this! Check out BABYLON.Tools.SetImmediate; it actually looks at the browser’s capabilities and chooses the best option to make your function execute on the next frame.

Cool, Is there a way we could use BABYLON.Tools.SetImmediate to fix the playground?

https://www.babylonjs-playground.com/#M13SAY#7

I refactored a bit and added some Promise usage. That do what you were hoping?

I started on that but, I think it relies on breaking up the meshes into groups of 100 to slow it down…

I found a solution which doesn’t make sense to me based on the words meaning:
https://www.babylonjs-playground.com/#M13SAY#8

  engine.displayLoadingUI();
    BABYLON.Tools.SetImmediate(function () {
	process_data();
});

SetImmediate, essentially delays the process_data function so that displayLoadingUI can run first, similarly to your setimeout example but I would think that “immediate” would be better applied to “displayLoadingUI” but this seems to work.

There are also a few engine observables and methods in the documentation with begin and end frame in them but they didn’t seem to allow me to separate frames and make “displayLoadingUI” run first.

Bottom line: the solution you’ve found should work just fine for your use case. :smiley:

You don’t have to break the loading into groups (100 was an arbitrarily chosen number :slight_smile: ), that was just to demonstrate a way you could do it in case you wanted to break the processing across many frames; that’s the “coroutine-style” pattern I mentioned earlier, reminiscent of one way to reduce the impact of long-running processes on the frame rate. Here’s an example of similar code that does each bulk load all within a single frame, blocking that frame for as long as the process needs.

https://www.babylonjs-playground.com/#M13SAY#9

You’re right, SetImmediate is a little bit of a confusing name because it actually causes execution to be delayed. The function was named that way to match the non-standard feature setImmediate(), which does the same thing but isn’t available on all browsers. Essentially what this means is that JavaScript won’t run the enclosed function until the next “tick,” which will allow the Babylon Engine to go ahead and take rendering actions before executing. You can dive pretty deep on JavaScript’s asynchronous features, if you want to; but for your use case here, I think SetImmediate is a perfectly viable way to tell JavaScript to execute something “next frame.”

Thanks for your help. In my app I still had issues with the loading screen not showing. I used settimeout to 5000 miliseconds and if I was loading lots of meshes it wouldn’t show, Which is weird that the program should have no knowledge that something processor intensive is coming in 5 seconds but would still delay showing the loading screen. setimmediate seemed to introduce other bugs where I was relying on linear execution.

I’m going to live with the delay for now and figure that users will have to figure that if the create a 1000 meshes things will delay if their machine can’t handle it.

I’m wondering if there is a way to request a feature? Add a parameter to force engine.displayLoadingUI() to run in a linear order, so that it would happen where it is called in the code.

If you feel there’s something that needs to be added to Babylon, you can file an issue and label it as an enhancement. However, from what you’ve described, it still sounds like there’s something else going on.

The behavior you’re describing in your app sounds pretty surprising, as whether or not the loading UI displays should have nothing to do with whether or not there’s something processor intensive to do: Babylon.js Playground. Can you reproduce the behavior your were describing in the Playground?

The feature I think you’re looking for when you say “run in linear order,” unless I’m misunderstanding, is a kind of asynchronous model: you want the execution of a command to be delayed until the prior command has finished executing. You can achieve this in JavaScript with Promises and Promise chaining, which I still think may be a direction worth exploring. I’ve refactored the Playground we’ve been working on again to illustrate this syntax and hopefully clarify what’s happening under the hood.

https://www.babylonjs-playground.com/#M13SAY#10