• Runtimes
  • Using the same assets in Pixi and Spine

Davide The easiest approach in your case is to export the skeleton three times, enabling the export flag only for the skin you want to export each time. This way, at runtime, your skeleton will require only the regions for the selected skin.

Thanks this seems to work!

Davide Next, use the texture packer separately, providing as input a folder containing only the attachments of that skin. For example, to create the atlas for skin1, if your image folder is structured as follows:...

I'm not sure why I need this? Doesn't the first part cover all my needs? Is this a different approach or an extension?

  • Davide님이 이에 답장했습니다.
    Related Discussions
    ...

    Glad it worked!

    michalvadak I'm not sure why I need this. Doesn't the first part cover all my needs? Is this a different approach or an extension?

    If your skin has no dependencies, the first step should be enough.
    If there are dependencies, as explained below, you also need to export the skin you depend on. In that case, its images will be included in your atlas. To avoid that you need to export the skeleton and the atlas separately.

    Okay, thanks!

    • Davide 님이 이 게시물을 좋아합니다..
    5일 후

    Davide // load the atlas and automatically the textures
    const atlas = await PIXI.Assets.load("https://esotericsoftware.com/files/examples/latest/spineboy/export/spineboy-pma.atlas");

    // util to get a new sprite, given an attachment name
    const getSprite = attachmentName => {
    // find the region with the given attachment name
    const region = atlas.regions.find(element => element.name === attachmentName);

    // get the respective page texture
    const originalTexture = region.texture.texture;
    
    // determine the position of the desired attachment, considering rotation
    const frame = {
        x: region.x,
        y: region.y,
        width: region.rotate === undefined ? region.width : region.height,
        height: region.rotate === undefined ? region.height : region.width,
    };
    
    // creating the new sub texture
        const texture = new PIXI.Texture({
        source: originalTexture.baseTexture,
        crop: new PIXI.Rectangle(frame.x, frame.y, frame.width, frame.height),
        frame,
    });
    
    // creating a new sprite
    return new PIXI.Sprite(texture);

    }

    const miniSpineBoy = new PIXI.Container();

    const footR = getSprite("front-foot");
    footR.x = 85;
    footR.y = 135;
    footR.scale.set(.70)
    miniSpineBoy.addChild(footR);

    const head = getSprite("head");
    miniSpineBoy.addChild(head);

    const eyeL = getSprite("eye-surprised");
    eyeL.x = 45;
    eyeL.y = 75;
    eyeL.scale.set(.75)
    miniSpineBoy.addChild(eyeL);

    const eyeR = getSprite("eye-indifferent");
    eyeR.x = 70;
    eyeR.y = 80;
    eyeR.scale.set(.75)
    miniSpineBoy.addChild(eyeR);

    const mouth = getSprite("mouth-oooo");
    mouth.x = 50;
    mouth.y = 120;
    miniSpineBoy.addChild(mouth);

    const footL = getSprite("front-foot");
    footL.x = 25;
    footL.y = 135;
    footL.scale.set(.70)
    miniSpineBoy.addChild(footL);

    miniSpineBoy.x = window.innerWidth / 2 - miniSpineBoy.width / 2;
    miniSpineBoy.y = window.innerHeight / 2 - miniSpineBoy.height / 2;;
    app.stage.addChild(miniSpineBoy);

    The only thing is I can't get the script to work correctly in Spine 7 with rotated assets and white strip on :/

    • Davide님이 이에 답장했습니다.

      michalvadak The only thing is I can't get the script to work correctly in Spine 7 with rotated assets and white strip on :/

      The script above was just a quick experiment. I did not test any special use cases.

      But what's the problem? In my example, I also had rotated textures and white strips.
      Just knowing that it doesn't work for you won't help me in helping you 🙂
      Could you describe your issue better?

      Got it! We made it to work now... but we have calculate the offsets and rotate the Texture at the end which I'm not sure is the correct approach.

      export const createTexturesFromSpineAtlas = (
        atlas: string,
        assets: string[]
      ) => {
        const regions = Assets.get(atlas)['regions'];
      
        regions
          .filter((region: TextureAtlasRegion) => assets.includes(region.name))
          .forEach((region: TextureAtlasRegion) => {
            const frame = new Rectangle(
              region.x,
              region.y,
              region.degrees !== 0 ? region.height : region.width,
              region.degrees !== 0 ? region.width : region.height
            );
      
            const orig = new Rectangle(
              0,
              0,
              region.originalWidth,
              region.originalHeight
            );
      
            const offsetY = region.originalHeight - region.height - region.offsetY; // spine stores data from the bottom-left corner, and we need to adjust for that
      
            const trim = new Rectangle(
              region.offsetX,
              offsetY,
              region.width,
              region.height
            );
      
            const texture = new Texture(
              region.texture.texture,
              frame,
              orig,
              trim,
              Pixi.groupD8.N
            );
      
            Texture.addToCache(texture, region.name);
          });
      };
      • Davide님이 이에 답장했습니다.

        michalvadak

        Here you can find all the properties parsed from the texture atlas file. If something doesn't work in the future, you can double-check there.

        You may also want to check the API documentation for the AtlasRegion where all relevant properties are documented.

        4달 후

        Hey! I have a question related to the topic discussed here. You said that addSlotObjects should be avoided where possible. But what if I want to create an animation that requires a dynamic number value? Would it be OK to use addSlotObjects in that case, or should I change the whole idea and create the animation in Pixi directly?

        • Davide님이 이에 답장했습니다.

          michalvadak

          Hello, you should avoid it if you can do that in Spine, otherwise it's perfectly fine 🙂

          You meant Pixi, right? But thanks! 😊

          Is there any good guide for batching and best practices to learn why and when it is a problem? I would like to figure out which assets should be packed together and if one large spritesheet is better or couple of smaller ones, etc.

          • Davide님이 이에 답장했습니다.
            • 수정됨

            michalvadak

            You meant Pixi, right?

            I meant that is better if you can embed what you do with addSlotObjects directly into the skeleton, so in the Spine Editor.
            For example, I remember that some users were able to create dynamic numbers within the editor with a combinations of skins. The developer just activated the respective skins and animations.

            Is there any good guide for batching and best practices to learn why and when it is a problem? I would like to figure out which assets should be packed together and if one large spritesheet is better or couple of smaller ones, etc.

            It's a so common topic that you can find valuable information everywhere. Even just asking it to ChatGPT would answer your questions.
            In general, there isn't a golden rule, it all depends on the use case.

            A good starting point is the doc page about performance. Start from there and explore what you find more interesting on the web.