Local images not loading in Babylon GUI (GUI Editor and code)

Hi!

I’m having trouble loading local images in Babylon GUI when using a Babylon.js Editor project with Vite.

I’ve tried both approaches:

  • Adding an image through the Babylon.js Editor GUI Editor.

  • Creating a BABYLON.GUI.Image directly from code.

For example:

const image = new BABYLON.GUI.Image(
    "myImage",
    "assets/2d/android.png"
);

advancedTexture.addControl(image);

The image does not appear. I also tried different relative paths and checked that the image file exists in the project.

Interestingly, I can see that the image is being requested/loaded in some cases, but it still doesn’t render correctly. At one point I only got a blue rectangle instead of the image.

I’m using a Babylon.js Editor project with Vite and Babylon.js 9.12.1.

My project structure is roughly:

public/
├── assets/
│   └── 2d/
│       └── android.png
└── scene/
    └── example.babylon

I have also tried using paths such as:

"assets/2d/android.png"
"./assets/2d/android.png"
"/assets/2d/android.png"

but I haven’t been able to get the local image to display correctly.

Is there a specific way that local GUI images should be referenced when using Babylon.js Editor + Vite?

Could this be related to Vite’s base: './' configuration or to how the Babylon Editor handles asset paths?

Thanks!

cc @julien-moreau, in case there’s some specific interactions between the editor and the GUI.

You don’t have a 404 in the console log?

I was able to solve this!

I realized that the asset path used by the Editor is different from the path used in the Vite build. With the following code:

const logo = texture.getControlByName("logo") as Image;

if (logo) {
    logo.source = "/scene/assets/amiga.jpg";
    logo.isPointerBlocker = false;
}

the image works perfectly when running with npm run dev.

In the Editor, I currently use a placeholder image by default.

Is there a way to set the same image in the Editor as well, so I can see the actual image while working in the GUI Editor?

Hey @Maxi !
You spotted a bug, the path should always be the one you have put first assets/2d/android.png. That means I have problem when running npm run dev where the rootUrl for assets is not properly set. I have created the issue here Images paths used in Babylon.js GUI files are not same between inline play and production · Issue #949 · BabylonJS/Editor · GitHub and it’ll be fixed in next release. I plan to release this week.

Thanks a lot for looking into this and for creating the issue! I really appreciate it.

One quick question: when the new release is available, will the Babylon.js Editor update automatically, or will I need to download/install the new version manually?

Thanks again!

It’s normal!
Nothing special, you’ll just need to launch the editor and a notification on your computer will saying you have to restart it to apply the update :slight_smile:
I’ll let you know once I deployed it

Hey @Maxi I just fixed it and it works perfectly!

Once deployed (you’ll get notified when running the Editor once I have deployed) you’ll be able to add in your scripts:

  @visibleAsAsset("gui", "My GUI Asset")
  private _gui!: AdvancedDynamicTexture;

And then drag’n’drop your GUI file inside your script (in case you wanted to manage GUI in a script).

And, if you do that, don’t forget to include somewhere in your app to register the GUI plugin when loading scenes:

import "babylonjs-editor-tools/loading/script/preload/plugins/gui";

Relative paths are now working relatively to your project’s absolute path so you could type assets/amiga.jpg in the field for the source of the image in the GUI Editor and it’ll be converted to an absolute path in the field. Don’t worry when saving the path still remains relative and everything will work as expected when you’ll deploy it on a server and nothing absolute is saved.

I’m deploying today or tomorrow (I’m adding a last fix for the release)

Thanks a lot for fixing this and for the detailed explanation! I really appreciate your help.

I’ll try it once the update is deployed.

Just deployed the fix for GUI too! v5.5.1

I’m having another issue after the latest update.

I now get the following error when running the project:

Error while playing the scene: 
Cannot read properties of null (reading 'getBoundingInfo') 
[ERROR] TypeError: Cannot read properties of null (reading 'getBoundingInfo')

I believe this error may be related to something else, since the object calling getBoundingInfo() is a Mesh and everything was working correctly before the update.

I’m also having an issue with a GUI Image:

  • The image is visible correctly in the GUI Editor.
  • However, when I click Play in the Editor, the image is not visible.

The image path is:

assets/amiga.jpg

I also noticed another error when running the project with npm run dev. In the browser console I get:

Failed to load resource: the server responded with a status of 400 (Bad Request)

and the request seems to point to main.ts.

Thanks!

I also noticed an issue with @nodeFromScene.

For example:

@nodeFromScene("playerHitbox")
private _playerHitbox: Mesh | null = null;

playerHitbox is in the same scene, but _playerHitbox is always null when I play the scene.

It almost seems like @nodeFromScene is behaving more like @nodeFromDescendants, or is otherwise unable to find nodes directly in the scene.

This was working correctly before the update.

Update: I found what seems to be the main issue.

I managed to get npm run dev working correctly again, and when running the game through the Vite dev server, @nodeFromScene correctly finds the node.

However, when I click Play directly in Babylon.js Editor, the same node is not found.

For example:

@nodeFromScene("playerHitbox")
private _playerHitbox: Mesh | null = null;

playerHitbox is in the same scene, but when playing inside the Editor:

this._playerHitbox === null

When running through npm run dev, the node is found correctly.

It seems that the problem is specifically related to how the Editor initializes/resolves @nodeFromScene when playing the scene.

This also appears to explain the other issues I was seeing, including:

  • Cannot read properties of null (reading 'getBoundingInfo')

  • GUI images visible in the GUI Editor but not in Play Mode

  • alpha and isHitTestVisible not behaving as expected

  • Other objects depending on nodes resolved with @nodeFromScene not being initialized correctly

Thanks!
Maxi

Thanks a lot for your help on this. This is so sad because I tried my game directly in Editor which uses almost ALL features and everything worked fine.
Do you have a Github repository? If you are ok, that would help me a lot to help you/me debugging :heart:

Thanks! I don’t have a Github repository for this project, and it would be difficult to share the whole game.

However, I can compress the project and send you a ZIP if that helps.

I also found a very simple way to reproduce the @nodeFromScene issue:

  1. Create a Mesh, for example a Box.

  2. Create another scene with another Box.

  3. Add a script to the second scene using @nodeFromScene.

  4. Put/instantiate that scene inside the first scene.

  5. Play the scene directly in the Editor.

When running it directly in the Editor, the log for the @nodeFromScene property is empty/null.

However, when I run the same project with npm run dev, @nodeFromScene correctly finds the Mesh and the log contains the Mesh object.

As a temporary workaround, I solved the issue in my game by storing the player’s hitbox reference directly in my GameManager instead of relying on @nodeFromScene.

There is also another issue with the GUI. I have a GUI asset with an Image called logo. The image is visible correctly in the GUI Editor, but when I play the scene directly in the Editor, it is not visible.

This is the code I use to load the GUI and set the image:

@visibleAsAsset("gui", "My GUI asset")
private _gui!: AdvancedDynamicTexture;

this._texture = AdvancedDynamicTexture.CreateFullscreenUI("hud");
this._texture.parseContent(this._gui.content, true);

const logo = this._texture.getControlByName("logo") as Image;

if (logo) {
    logo.isPointerBlocker = false;
}

The image is visible in the GUI Editor, but not when playing the scene.

I can send you a ZIP with the minimal reproduction case if that would be useful.

Thanks!

For the GUI part I just found the problem and it was here since the beginning, I added import "babylonjs-editor-tools/loading/script/preload/plugins/gui"; in my script file this is why it was working on my side :frowning:

I’m releasing the fix ASAP if you can send me in private a zip of your project that would help me a lot so I can fix all bugs and deploy right after (today or tomorrow) for a v5.5.2

Thanks again for helping improving the editor!

The playerHit issue was fixed in the new version 5.5.2 thanks to the new global option.

@nodeFromScene("playerHitText", { global: true })
private _playerHitTest!: Mesh;

As for the GUI, it also works in this new version and images can now be previewed. It’s also worth noting that now, to display a GUI created with the editor, all you need is

@visibleAsAsset("gui", "My GUI asset")
private _gui!: AdvancedDynamicTexture;

and drag the file into the properties.

Regarding the player hit issue, I want to add that I was confused — @nodeFromScene actually searched within the same scene before, which was my mistake for assuming it searched globally. But @julien-moreau added this very useful new feature.