• Runtimes
  • WebGL Runtime attach PNG to bone slot

I have a Spine animation to use as a template, and playing with Spine Web Player. I do not have the ability to embed the required png data from within the editor as I depend heavily on server-side data.

I need a clean cut way of injecting PNG's into my model, I assume calling a findSlot method but have not found how to attach or process a png url, or if needed, download and draw the PNG onto a canvas object.

looking for someone with in depth knowledge of the web player and the best way to find assets and swap them out dynamically by using "lite" spine animations that does not contain image data until the user uploads it to our servers.

Related Discussions
...

I've written a little example. Note that you need to use the latest spine-ts release (4.1.27, or 4.2.13 if you use the beta). You can find the example here:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.1/spine-ts/spine-webgl/example/custom-attachment.html#L49

It's the basic WebGL example extended to load a .png file and replace the existing attachment for Spineboy's head. I assume you know what slots and attachments are.

Loading the image is done via AssetManager as usual in loadAssets(), in addition to the .skel and .atlas files:

assetManager.loadTexture("head.png");

Once everything is loaded, we parse the loaded data into a TextureAtlas and SkeletonData instance, from which we create a Skeleton and AnimationState.

The final trick is to replace the head image, which comes from the atlas, with the head.png image. Here's the code for that from the example:

let texture = assetManager.require("head.png");
let textureRegion = {
	texture: texture,
	u: 0, v: 0, u2: 1, v2: 1,
	width: texture.getImage().width, height: texture.getImage().height,
	degrees: 0,
	offsetX: 0, offsetY: 0,
	originalWidth: texture.getImage().width, originalHeight: texture.getImage().height
};				
let headSlot = this.skeleton.findSlot("head");
let newHeadAttachment = headSlot.getAttachment().copy();				
newHeadAttachment.region = textureRegion;
newHeadAttachment.updateRegion();
headSlot.setAttachment(newHeadAttachment);	

We first fetch the loaded image from the AssetManager, also called a texture. Next, we create a new TextureRegion. A texture regions specifies which parts of an image should be used when rendering an attachment. In this case, we want to use the entire image, so we set the texture region fields accordingly.

Next, we fetch the slot called head from the skeleton, and copy the attachment that's currently set on the slot. We replace the region of the attachment with the region we just created. A call to newHeadAttachment.updateRegion() ensures that the attachment knows how to work with the new region in terms of texture coordinates and so on.

Finally, we set the new attachment with our custom texture region sourced from the .png on the slot. And that's it!

This will only work if the image you used in the Spine Editor for that region has the same size as the image you load from the .png.

If you want to go back to the original attachment and its original region from the texture atlas, you can call skeleton.setToSetupPose(). If you do not need the loaded .png anymore, make sure to dispose the corresponding texture with texture.dispose(), otherwise you'll leak GPU side memory.

    10 jours plus tard

    Mario
    Thank you! this is a blessing!

    19 jours plus tard

    Mario
    I am encountering an error with transparency, seems there are issues with PNG bleeding, perhaps the alpha isn't taken into account?


    asset example:

    6 jours plus tard

    That's not something that can be fixed in the runtime. It's also hard to tell from the info you gave what's going on. My guess is that the chest_open_glow image has an incorrect alpha mask.