Dynamically generated atlas for spine models

Hello,
I’d like to know if the following is possible in the current Defold version:

  • We have a Spine model, made with atlas A (imagine a character)
  • We’d like to propose to our user a very large set of combination of this character (think something like 500 differents hats). That won’t fit in a single atlas and we’d like to add new hats “on the go” once the app is live (think user-generated content).

Would it be possible to generate a new atlas on our server, and then the client downloads it and replaces the current spine atlas with the downloaded one?

Any pointer to do that would be appreciated, thanks.

1 Like

Currently, there’s no way to create or load a new atlas at runtime.

Perhaps you can attach a sprite to one of the bones instead?

Maybe I misnamed atlas for texture in my first post.
Let’s say the atlas stays the same (all the elements have the same size, and are placed the same way on the atlas file).
Is it possible to update the texture dynamically?

Yes, you can replace a texture resource with resource.set_texture()

OK, but how do you generate this new texture in the first place?
I mean let’s say I have a texture that has 10 elements (head, blue hat, etc). I want to creature a new texture where I change the hat to a red one.
Do I create a new PNG where all the elements have the same positions, and replace the blue hat in that PNG file, and then download the PNG and convert it to a texture?

Yes, this is crucial, as the atlas itself (the .texturesetc file) hasn’t changed.

Do I create a new PNG where all the elements have the same positions, and replace the bleu hat in that PNG file, and the download the PNG and convert it to a texture?

That would work yes

What do you put as a 1st parameter to update the texture of a spine?

I’m trying with
resource.set_texture( go.get("/go1#spinemodel", "texture0"), img_resource.header, img_resource.buffer )

but it doesn’t work. What’s the path to a spine texture?

The spine component doesn’t have a “texture0” property, so you cannot retrieve it (not yet anyways).
A workaround would be to set the same atlas on a sprite, and get it from there?

go.get("/go1#sprite, “texture0”)

1 Like

Good trick!

I’m having an issue here.

Here is the atlas I’m using in my game:

I’m trying to “update” it with another texture downloaded during runtime. Here is the one I’m trying to download and replace:
https://gateway.pinata.cloud/ipfs/QmXmiGfnCNix9T7Tz5MmMwXZQRnHPMit4CCThVLCyMGtYT

Here is the result I have:

Here is my code:

local function load_and_set_texture(url)
	http.request(url, "GET", function(self, id, res)
		if res.status ~= 200 and res.status ~= 304 then
			print("Unable to get image", res.response)
			return
		end
		print("Got the image")

		local img_resource = imageloader.load{data = res.response, format = resource.TEXTURE_FORMAT_RGBA}
		resource.set_texture( go.get("/sprite#sprite", "texture0"), img_resource.header, img_resource.buffer )
	end)
end

What am I doing wrong?

We use premultiplied alpha, so you most likely want to manipulate your loaded texture to do the same.

Thanks that solved the issue.

I still have a glitch regarding the position of the images in the spine animation. It feels like I’m not exactly building my new texture with the correct position.

Is there anything I should take into consideration when building my preloaded texture?

@Lex can you tell us a bit more about the games you are creating? Every screenshot or asset I’ve seen over the years look really great!