badlogic написавI'm afraid there's no tutorial, but the Spine API is the same across programming languages! In your first code example, constructing the texture atlas is done via libGDX's API. What engine are you using? Cocos2d-x? In any case, our engine integrations offer simple APIs to load texture atlases through the engine itself. For Cocos2d-x you can find it here (since 3.7 we use spine-cpp not spine-c though!):
spine-runtimes/SkeletonRenderer.cpp at 3.8
Your second piece of Kotlin code should translate pretty much the same to spine-c or spine-cpp. Skin [url=http://esotericsoftware.com/spine-api-reference#Skin-getAttachment]
getAttachment[/url]()
becomes spSkin_getAttachment()
or spine::Skin::getAttachment()
, Attachment#copyAttachment()
becomes spAttachment_copyAttachment()
or spine::Attachment::copyAttachment()
etc.
Finally I managed to create a skin from another asset (.atlas and .png), but still have an issue.
The ideas are:
- Load the new atlas
- Create a skin object that already exist in the skeletonData, named
templateSkin
- Create a new skin object with skin name, called
newSkin
- Get the attachment from
templateSkin
- Paste it into the new one
newSkin
- Apply the
newSkin
into our skeleton
Here's our code in Objective-C
- (spSkin*)createItemSkinWithAtlas:(NSString[/i])skinAtlas withCategory:(NSString*)category andSkinName:(NSString*)newSkinName {
// Load the new atlas
spAtlas *newAtlas = spAtlas_createFromFile([skinAtlas UTF8String], 0);
// Create a skin object that already exist in the skeletonData, named `templateSkin`
spSkin *templateSkin = spSkeletonData_findSkin(_skeleton->data, "top_short_basic_m");
// Create a new skin object with skin name, called `newSkin`
spSkin *newSkin = spSkin_create([newSkinName UTF8String]);
// Get the attachment from `templateSkin`
for (int i=0; i<(self.skeleton->slotsCount - 1); i++) {
const char *slotName = self.skeleton->data->slots[i]->attachmentName;
spAttachment *templateAttachment = spSkin_getAttachment(templateSkin, i, slotName);
if (templateAttachment != NULL) {
NSString *newAttachmentName = [[NSString alloc] initWithFormat:@"%s_%@", slotName, newSkinName];
spAttachment *newAttachment = [self copyAttachmentFrom:templateAttachment withAtlas:newAtlas newAttachmentName:newAttachmentName];
// Paste it into the new one `newSkin`
if (!newAttachment) {
spSkin_setAttachment(newSkin, i, slotName, newAttachment);
}
}
}
return newSkin;
}
Here is my copyAttachmentFrom
function
// adding new function that copy attachment from existing atlas into the new one
- (spAttachment[i])copyAttachmentFrom:(spAttachment[/i])attachment withAtlas:(spAtlas*)atlas newAttachmentName:(NSString*)regionName {
spAtlasRegion *searchedRegion = spAtlas_findRegion(atlas, [regionName UTF8String]);
if (attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment *newAttachment = (spRegionAttachment*)attachment;
newAttachment->rendererObject = searchedRegion;
spRegionAttachment_updateOffset(newAttachment);
return (spAttachment*)newAttachment;
} else if (attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment *newAttachment = (spMeshAttachment*)attachment;
newAttachment->rendererObject = searchedRegion;
spMeshAttachment_updateUVs(newAttachment);
return (spAttachment*)newAttachment;
} else {
// just following android's code, only support 2 types
return attachment;
}
}
Then I create a skin with:
spSkin *theNewSkin = [self createItemSkinWithAtlas:@"animalbluetshirt12_m.atlas" withCategory:@"top_short_basic_m" andSkinName:@"animalbluetshirt12_m"];
spSkeleton_setSkin(_skeleton, theNewSkin);
spSkeleton_setSlotsToSetupPose(_skeleton);
But sadly, my theNewSkin
didnt' showed up in my character. I think, the copy attachment from existing skin into the new one was incomplete. Did I missing a step here?
Thank you in advance!