EngineStore.LastCreatedEngine becoming empty

Hello everyone,

It’s been a long time since I last posted on this forum. Thank you all again for both this amazing library and community !

I’m running into an issue with EngineStore.LastCreatedEngine in the context of creating a simple GUI Element (directly copied from this playground

Explanations:

Even though the involved code is simple, the project structure is not:
I have 2 different projects, the first one (let’s call it ‘mainApp’) is importing the second one (call it ‘core’) as an npm package (through npm link if it helps). I am the maintainer of both projects.

Basically what happens is:

  • mainApp imports core as an npm package
  • mainApp imports and uses two classes from core:
    • one that performs the general setup of a baseScene (equivalent of the Playground, call it ‘SceneManager’ with a CreateScene method)
    • the other one that is abstract (‘SceneLayoutBuilder’) and extended in the mainApp project (as ‘MySceneLayoutBuilder’) and called by the CreateScene method through the ‘SceneLayoutBuilder’ type.

Here is a playground. in this context it is working but it is better to illustrate the structure of my code (that I cannot share unfortunately). The facts that it is working in Playground makes me think that it could be related to the way the packages are imported but I couldn’t go further on my own.

Although this complicated setup works fine when I am creating simple objects as spheres, planes etc… it is not working when I try to add some GUI elements.
Actually only those three lines are sufficient to make the error appear.

const advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI("myUI", true, scene);
var button1 = Button.CreateSimpleButton("but1", "Click Me");            advancedTexture.addControl(button1);

Here is the error I get :

babylon.gui.js:6730 
       Uncaught Error: Invalid engine. Unable to create a canvas.
    at Control._GetFontOffset (babylon.gui.js:6730:1)
    at TextBlock._processMeasures (babylon.gui.js:15921:1)
    at Control._layout (babylon.gui.js:6091:1)
    at Container._layout (babylon.gui.js:4245:1)
    at Container._layout (babylon.gui.js:4245:1)
    at AdvancedDynamicTexture._render (babylon.gui.js:1244:1)
    at AdvancedDynamicTexture._checkUpdate (babylon.gui.js:1219:1)
    at AdvancedDynamicTexture._render (babylon.gui.js:1237:1)
    at AdvancedDynamicTexture._checkUpdate (babylon.gui.js:1219:1)
    at c.callback (babylon.gui.js:620:94)

When looking into the line where the error is thrown, it seems that EngineStore.LastCreatedEngine becomes empty at some point in the code. I seems to happen just before the call to the ‘initScene’ method (through the abstract class).

I’ve looked into this forum post, talking about the same error, and tried several suggestions such as checking that the versions of babylonjs packages were the same in both projects but it seems to be the case (5.42.1 which must be the latest version at this time). I also tried to downgrade to an arbitrary version (5.20.0) but the error is still the same.

I hope this is understandable and I would appreciate any help that could preserve some of my nerves!
Thank you for your time !

Howdy!

We don’t clear EngineStore.LastCreatedEngine until an engine is disposed (or replaced), which leads me to believe there is a context issue here.
Is it possible you are using both UMD and es6 packages? would you be able to share part of the project? or at least your package.json?

2 Likes

Thank you for your answer. I didn’t mention it but I also tried to put a ‘console.log’ in the onDisposeObservable of the engine but it didn’t print anything.

As far as I know I am not using UMD modules, but this is still an obscure part of node that I currently don’t master enough so… maybe :person_shrugging: :smile:

Unfortunately I cannot share the code but here are relevant parts of both package.json (mainApp and core), with names adapted to my example:

mainApp:

{
  "name": "mainApp",
  "version": "0.0.0",
  "private": true,
  "type": "commonjs",
  "scripts": {
    /* ... */
  },
  "dependencies": {
    "@thescope/core": "file:../../core", //the other package
    "babylonjs": "^5.42.2",
    "babylonjs-gltf2interface": "^5.42.2",
    "babylonjs-gui": "^5.42.2",
    "babylonjs-loaders": "^5.42.2",
    /*...*/
  },
  "devDependencies": {
    /*...*/
    "@types/node": "^18.11.18",
    "file-loader": "^6.2.0",
    "nodemon": "^2.0.20",
    "ts-loader": "^9.4.2",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1"
  }
}

core:

{
    "name": "core",
    "scope": "thescope",
    "version": "0.3.0",
    "private": false,
    "main": "index.ts",
    "dependencies": {
        /*...*/
        "babylonjs": "^5.42.2",
        "babylonjs-gltf2interface": "^5.42.2",
        "babylonjs-gui": "^5.42.2",
        "babylonjs-loaders": "^5.42.2",
        "recast-detour": "^1.5.0",
    },
    "devDependencies": {
        "sass-loader": "^10",
        "ts-node": "^10.9.1",
        "typescript": "4.9.4"
    }
}

While answering I noticed the “type”: “commonjs”, in the first package.json which is a bit random, I don’t know if this could be the cause of the problem as it looks to be related to what you suggest.

These are the UMD packages :slight_smile:
Are these 2 different apps running in two different contexts? how are they connected?

The package ‘core’ is supposed to be “just” a library providing classes and utilities that can be imported and called by ‘mainApp’ (but also other projects, that is why it is separated).
Unless I missed something (and I will check that again) there should be only one context, as all the code from both packages is initially called from the mainApp package.

Could you advise me about what I am supposed to look for ? What kind of code could create another context ?

Well, if you have creqated an engine, it should be available in the BABYLON namespace (BABYLON.EngineStore.LastEngineCreated) this can be verified when creating the engine. A simple test to check your context would be to add some temp variable to the BABYLON namespace you are using after creating the engine. i.e. - BABYLON.TEMPTEST = 1234;. Afterwards, when creating the GUI (or using the GUI), make sure that this variable is available. if it is available but the engine isn’t, it is a different issue that we need to check. If it isn’t, you are running two different contexts.

From looking at your code, it does seem like you are importing certain parts of the framework. You don’t use the BABYLON namespace, even though you are using the UMD packages. I would suggest to try the ES6 packages instead and see if that helps (i.e. @babylonjs/??? instead of all of the babylonjs-??? packages).

And, if possible, a simple reproduction - like a project on github - would be very helpful to help you resolve this.

1 Like

Thank you for you suggestions, I managed to go a little further.

I replaced the UMD packages with the ES6 version (I wasn’t aware of the difference), even though it seems more appropriate, it doesn’t solve the problem.

I have done this test and the BABYLON.TEMPTEST property is indeed empty in the code section where I try to use the GUI. So there must be two contexts but I cannot determine why for now.

However, I tried to move the class ‘MySceneLayoutBuilder’ to the ‘core’ package and it does solve the problem. This is not ideal from an architectural point of view but I will settle for this solution for now. This makes me think that it is indeed more related to the way it is imported than to the code itself.

I will try to dig further into this problem when I have more time and let you know what I find.

Thank you for your help and availability ! :slight_smile:

1 Like