EsotericSoftware / spine-runtimes

2D skeletal animation runtimes for Spine.
http://esotericsoftware.com/
Other
4.42k stars 2.92k forks source link

[ts][pixi] Fix atlas src cannot be resolved for preferred texture #2619

Closed furic closed 2 months ago

furic commented 2 months ago

Description

Pixi provides a way to load the assets from a bundle, given a preferred resolution and format, it can pick the best source asset for smaller game-size.

The assets must follow the format, e.g. spritesheet@0.5x.png.json // 0.5x resolution, png spritesheet.

That works well with Sprite and Spritesheet, but it's currently broken for Spine Atlas where it always picks the first one in the src list.

Steps to Reproduce

I have a manifest.json, which contains only one bundle named spineboy, with spineboy assets:

{
    "bundles": [
        {
            "name": "spineboy",
            "assets": [
                {
                    "alias": [
                        "spineboyAtlas"
                    ],
                    "src": [
                        "spineboy.png.atlas",
                        "spineboy@2x.png.atlas",
                        "spineboy@3x.png.atlas",
                        "spineboy.webp.atlas",
                        "spineboy@2x.webp.atlas",
                        "spineboy@3x.webp.atlas"
                    ]
                },
                {
                    "alias": [
                        "spineboyData"
                    ],
                    "src": [
                        "spineboy-pro.json"
                    ]
                }
            ]
        }
    ]
}

The manifest and the assets can be created manually, or auto-generated by Pixi's Asset Pack.

Then, I can initialize PIXI.Assets and load the bundle by:

// Initialize Assets with given manifest and preference
await PIXI.Assets.init({
  basePath: './assets/spineboy-bundle',
  manifest: './manifest.json',
  texturePreference: {
    resolution: Math.min(PIXI.utils.isMobile.any ? window.devicePixelRatio : 3, 3), // Set the preferred resolution to 3 for desktop, or devicePixelRatio for mobile; Pixi.Assets will load the corresponding asset if found
    format: ['webp', 'png'], // Prefer WEBP, then fallback to PNG if the device doesn't support it
  },
});
// Load the bundle that includes the skeleton data and atlas
await PIXI.Assets.loadBundle("spineboy");
// Create the spine display object
const spineboy = spine.Spine.from("spineboyData", "spineboyAtlas");

Expected Behaviour

Pixi picks the right resolution and format, e.g. spineboy@3x.webp.atlas on desktops and corresponding ones in mobile:

iPad Pro iPad Pro uses 2x resolution WEBP

iPhone 14 Pro iPhone 14 Pro uses 3x resolution WEBP

Actual Behaviour

Pixi always picks the first one, spineboy.png.atlas no matter what.

Code Explanation

Currently the atlasLoader is missing the resolver parameter. resolver:parse is used to determine the asset properties, so PIXI.Assets knows which one to use. For example, spineboy@2x.png.atlas should result {resolution: 2, format: 'png', src: '...'}. The added code is referenced from Pixi's SpritesheetAsset and a similar issue with JSON.

davidetan commented 2 months ago

Thanks for this! I've removed the example since it brought in too many assets, but I will update the documentation accordingly 👍

davidetan commented 2 months ago

Released in 4.2.59. Thanks again :)