• Editor
  • Extending spine-c without using Atlas

Before the recent changes to spine-c, I had an extension working to use my own texture atlas system by deriving from the AnimationLoader and RegionAttachment, and everything worked fine. (I derived from RegionAttachment instead of Attachment because there is an important typecast to RegionAttachment* in SkeletonJson_readSkeletonData.)

After the update, the RegionAttachment_init and deinit function are gone from extensions.h, suggesting that I shouldn't try to extend that object any longer. However, with that necessary typecast in SkeletonJson_readSkeletonData, I'm not sure what else to do.

I went ahead and extended it anyway, being careful to manage the memory myself. Everything works fine, though I had to add a check for null to the code you added in RegionAttachment_updateOffset that deals with self->region. (Since I'm using my own texture atlas, that's always null.)

I'm guessing that I'm not extending this the way I should be, so I'd love if you could give me some pointers. Thanks!

Related Discussions
...

hi there!

like Chounard , I would like to write my own extension to support multi-texture in cocos2dx runtime for swap images (or will it support officially soon?), but I dont know where to start, any tips would be highly appreciated!

thank you!

My code seems to be working really well, so I'm gonna stick with this method for now, unless I learn of something better. If anybody wants to see how I did it, it's at the top of the file here:

https://github.com/ThirdPartyNinjas/NinjaParty/blob/master/Source/Graphics/SpineAnimationPlayer.cpp

You can safely ignore everything after the spine namespace. The rest of that is code to make it work with my animation system.

I had to make two modifications to the spine-c runtime for this to work.

1) In RegionAttachment_updateOffset, I check to make sure self->region isn't null.
2) In Animation_dispose, I added FREE(self->name); because it was leaking memory when I ran it through Instruments. (I'm not sure where it's supposed to be released.)

Philip escribió

like Chounard , I would like to write my own extension to support multi-texture in cocos2dx runtime for swap images (or will it support officially soon?)

As of the refactoring a few days ago, cocos2d-x supports atlases that have multiple backing images.

Thanks for being patient with the recent refactoring. I know it sucks when I break your code. :wonder:

I fixed freeing the animation name (good catch!).

Extending RegionAttachment as you did works even though it doesn't expose init/deinit functions because RegionAttachment doesn't allocate for any of its fields. If it had init/deinit, they would just call the Attachment_init/deinit functions. That said, you're right that since you don't see init/deinit it indicates RegionAttachment is not designed to be extended.

The recent refactoring removed the rendering from the data objects to reduce the inheritance required to extend spine-c. Previously RegionAttachment had to be extended because it knew how to draw itself. Now something external takes RegionAttachment and knows how to draw them.

RegionAttachment needs some knowledge of the region. This allows RegionAttachment_updateOffset to handle whitespace stripped and/or rotated regions. It also allows spine-c to have AtlasAttachmentLoader so it doesn't need to be implemented for each toolkit. I agree it would be better not to reference AtlasRegion. Instead we could copy the necessary data into RegionAttachment fields. If the data comes from a different atlas, then it will work just the same. RegionAttachment would also get a void* for the region's texture, which is a renderer specific pointer. I'll make these changes tomorrow.

Is there a reason you don't use AnimationState? I only glanced briefly, but I see you have some rather complex transitions, maybe AnimationState can handle that for you?

The only reason I don't use AnimationState is because I wrote all of this before you added AnimationState. (This was first built on the original spine-cpp runtime.)

I'll keep an eye out for the changes, thanks!

Nate escribió
Philip escribió

like Chounard , I would like to write my own extension to support multi-texture in cocos2dx runtime for swap images (or will it support officially soon?)

As of the refactoring a few days ago, cocos2d-x supports atlases that have multiple backing images.

Hi Nate,

I think I missed something. 😢 let me explain myself
so I took the goblins example, I removed the spear & dagger and generated a new goblins.atlas & goblins.png without them.
In Spine editor, the spear/dagger attachments are left there intentionally, so that I think I can attach the image
of the spear or dagger in runtime according to the calculate result from
"RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad)" in CCSkeleton class

But when I call "CCSkeleton::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale)"
it will fail to create because "SkeletonJson_readSkeletonDataFile(json, skeletonDataFile)" would fail, I assume
because of the spear&dagger are gone from .atlas

so how should I do this properly?
Thank you~

You explained what you did, but it isn't clear what your goal is.

SkeletonJson uses an AttachmentLoader to load attachments. It you are using AtlasAttachmentLoader then it considers not finding an image in the atlas an error. You can 1) put all the images in the same atlas (note an atlas can have multiple image pages), or 2) write your own AttachmentLoader that looks in different atlases, or 3) write your own AttachmentLoader that doesn't fail when a region could not be found and then assign the regions later.

If you are just trying to change the image attached to a slot at runtime, use Skeleton_setAttachment(skeleton, "slot name", "attachment name");.

sorry for my bad english. :tmi:
basically I would like to attach image (not in atlas at all, not stripped) to the place of target slot.
route 3 seems a way to go.
But in "SkeletonJson* SkeletonJson_create (Atlas* atlas)", "AtlasAttachmentLoader"
is called directly and i think i should not to modify the "AtlasAttachmentLoader" source code for easier update in the future.
can we provide a custom AttachmentLoader without modifying the runtime source code?

thank you~~

You can load the use the "skeletonWithData🙁SkeletonData*)skeletonData" constructor. Load the SkeletonData yourself using a SkeletonJson created via SkeletonJson_createWithLoader.

The refactoring I'm doing today will make it easier to do what you want. I'll post again explaining it when I'm done. In anticipation you can change your code to use the constructor mentioned.

Ok here the commit is done. RegionAttachment no longer has an AtlasRegion, instead it has:

void* texture;
float regionOffsetX, regionOffsetY; // Pixels stripped from the bottom left, unrotated.
float regionWidth, regionHeight; // Unrotated, stripped size.
float regionOriginalWidth, regionOriginalHeight; // Unrotated, unstripped size.

These are set by the AttachmentLoader. Eg, see AtlasAttachmentLoader. If you aren't using Atlas, set these values by whatever you are using. If you aren't whitespace stripping, set offset to 0 (or just don't set it) and set the region size and original size to the same values. The texture can be anything, as long as whatever is rendering your region attachments knows how to interpret it. Lastly, there is now a RegionAttachment_setUVs method that needs to be called with the region's UVs if your renderer will be using regionAttachment->uvs to render.

These changes also fix whitespace stripped and/or rotated regions for spine-c.

I will do a similar refactoring for C#.