Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the proper way to handle atlas image loading failures? #538

Open
vovaslotmill opened this issue Dec 22, 2023 · 1 comment
Open

Comments

@vovaslotmill
Copy link

vovaslotmill commented Dec 22, 2023

Hi!

Problem

It is not possible to catch spine loading error if an image, defined in .atlas file, has failed to load (network error, absence of asset itself, etc.).

Dependencies:

spine: 4.1.24
pixi-spine: 4.0.4
pixi.js: 7.3.2

Example

Few assumptions first:
assets folder is available and serve files correctly.
faultySpine consists of 3 files: faultySpine.json, faultySpine.atlas and faultySpine.png.
To prevent faultySpine.png file from being loaded - it has been blocked, through Chrome Dev Tools.

Here is the code example, itself:

import { Application, Assets, Sprite } from "pixi.js";
import { Spine } from "pixi-spine";

const worldWidth = 1920;
const worldHeight = 1080;

(async () => {
  const app = new Application({
    backgroundColor: 0x000000,
    width: worldWidth,
    height: worldHeight,
  });

  document.body.appendChild(app.view as HTMLCanvasElement);

  // setup faulty spine
  try {
    Assets.add({
      alias: "faultySpine",
      src: "./assets/faultySpine.json",
      data: {
        metadata: {
          spineAtlasFile: `./assets/faultySpine.atlas`,
        },
      },
    });
    const spineAsset = await Assets.load("faultySpine");
    const spine = new Spine(spineAsset.spineData);
    spine.x = app.renderer.width / 2;
    spine.y = app.renderer.height / 2;
    spine.state.setAnimation(0, "some_animation", true);
    app.stage.addChild(spine);
  } catch (e) {
    console.error(e); // (1) will not be triggered if `faultySpine.png` failed to load
  }

  // setup bunny sprite
  try {
    const texture = await Assets.load("./assets/bunny.png");
    const bunny = new Sprite(texture);

    bunny.x = app.renderer.width / 2;
    bunny.y = app.renderer.height / 2;

    bunny.anchor.x = 0.5;
    bunny.anchor.y = 0.5;

    app.stage.addChild(bunny);
    app.ticker.add(() => {
      bunny.rotation += 0.01;
    });
  } catch (e) {
    console.error(e); // (2) will be triggered if `bunny.png` failed to load
  }
})();

Trying to figure out why an error for Assets.load('faultySpine.json') has not been trigged, brought up the following part to attention:

export const makeSpineTextureAtlasLoaderFunctionFromPixiLoaderObject = (loader: Loader, atlasBasePath: string, imageMetadata: any) => {
    return async (pageName: string, textureLoadedCallback: (tex: BaseTexture) => any): Promise<void> => {
        // const url = utils.path.join(...atlasBasePath.split(utils.path.sep), pageName); // Broken in upstream

        const url = utils.path.normalize([...atlasBasePath.split(utils.path.sep), pageName].join(utils.path.sep));

        const texture = await loader.load<Texture>({ src: url, data: imageMetadata });

        textureLoadedCallback(texture.baseTexture);
    };
};

https://github.com/pixijs/spine/blob/master/packages/loader-base/src/atlasLoader.ts#L98-L108

If const texture = await loader.load<Texture>({ src: url, data: imageMetadata }); will throw an error -textureLoadedCallback will never be called, therefore the following rejection will never happen in this case, thus error will never be captured and will be an instance of Uncaught error:

if (!newAtlas) {
    reject('Something went terribly wrong loading a spine .atlas file\nMost likely your texture failed to load.');
}

https://github.com/pixijs/spine/blob/master/packages/loader-base/src/atlasLoader.ts#L59-L61
uncaught-error-example

Solution (?)

Call textureLoadedCallback with null, if texture loading has failed, to prevent TextureAtlas setup and trigger an error that will be captured in (1)

@vovaslotmill
Copy link
Author

i've prepared PR to address this issue: #544

if texture loading has failed for any reason - an appropriate error will be populated by loader as expected.

@miltoncandelero if an assumption that there IS a problem is wrong - please, leave comment here, so PR and issue can be closed 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant