Joost

I'm trying to combine skins using the C runtime. What I want to do is take a base skin that has the entire body and then replace specific parts with whatever is present in several other skins. So maybe I have an armor skin with arm and torso armor, and a helmet skin with an alternative head. In code I don't know which skin overwrites what, that's up to the artists. All I need to know in code is that a skin overwrites whatever it contains. I found the explanation on Runtime Skins (http://esotericsoftware.com/spine-runtime-skins) and this forum topic (http://esotericsoftware.com/forum/Generating-a-skin-at-runtime-libGDX-9092?p=41209).

However, I can't seem to find several of the functions I need in the C runtime. I might be looking in the wrong place, I don't know. I got it to work, but only by casting to an internal Spine struct and by leaking memory. I suspect that's not as intended. :p

My current approach is this:
void update()
{
combinedSkin = spSkin_create("combined");

// Add elements from base skin
overwriteCombinedSkinAttachments("Normal", combinedSkin);

// Add elements from skins that contain only specific parts
overwriteCombinedSkinAttachments("Mohawk", combinedSkin);
overwriteCombinedSkinAttachments("Moustache01", combinedSkin);

spSkeleton_setSkin(skeleton, combinedSkin);
}


void SpineRenderable::overwriteCombinedSkinAttachments(const char* overwritingSkinName, spSkin* combinedSkin)
{
_spSkin* overwritingSkin = (_spSkin*)(spSkeletonData_findSkin(skeletonData, overwritingSkinName));
_Entry* iter = overwritingSkin->entries;
while (iter != nullptr && iter->attachment != nullptr)
{
spSkin_addAttachment(combinedSkin, iter->slotIndex, iter->name, iter->attachment);
iter = iter->next;
}
}
If I try to delete the skin before creating a new one through spSkin_dispose(combinedSkin) I get a crash. Maybe this also deletes the attachments or something like that? What's the right way to delete a skin I made myself, and is there some way to clear a skin (instead of deleting it every time)?

Also, I'm using the internal struct _spSkin here which works, but I don't think it's as intended. What's the correct way to do this? I couldn't find any other way to iterate over the attachments in a skin.
Joost
Сообщения: 2

badlogic

Welcome to the wonderful world of skins! As you identified, there's currently no way to iterate over the attachments inside an spSkin apart from casting to the internal _spSkin structure. I just opened an issue for adding the method from this forum post by Nate (Generating a skin at runtime (libGDX)) to all other runtimes: [runtimes] API to add all attachments of a skin to another (empty/new) skin · #990 Until that is implemented, you can continue casting to _spSkin.

spSkin_dispose currently assumes that the skin being disposed owns the attachments it contains. The function will thus not only delete the _Entry structs in the skin, but also call spAttachment_dispose. Any attachments you've added from another skin will thus be disposed and point to invalid memory. I've created an issue to add a function that won't dispose the attachments here: [c] Add spSkin_dipose that does not dispose attachments · #991. You can temporarily use this code:
void spSkin_shallowDispose (spSkin* self) {
_Entry* entry = SUB_CAST(_spSkin, self)->entries;
while (entry) {
_Entry* nextEntry = entry->next;
FREE(entry->name);
FREE(entry);
entry = nextEntry;
}

FREE(self->name);
FREE(self);
}
Аватара пользователя
badlogic

Mario
Сообщения: 979

Joost

Thanks for the explanation!

At first your shallowDispose still crashed the game, but it turns out this was because I deleted the old skin before assigning a new one. I saw in the source now that spSkeleton_setSkin starts by doing things with the old skin, which crashes if the old skin has already been deleted. So the solution was to delete the old skin only after the new skin had been created and set.
Joost
Сообщения: 2

badlogic

Glad it works for you! Follow the issues i linked to on updates to the official API. Thanks for the feedback!
Аватара пользователя
badlogic

Mario
Сообщения: 979


Вернуться в Runtimes