We are a Spine licensee and doing our first Spine deployment. It works great, but we'd like to optimize it into our workflow/toolchain a bit neater.
To reduce image duplication, I'm trying to load the images used by Spine animations from the Cocos2d-X SpriteFrameCache instead of from Spine's own atlases. I can get the code below to work and animations to play. However, the attachments are either rotated or scaled incorrectly.
for spRegionAttachment and spMeshAttachment, should the regionWidth and regionHeight be scaled based on the value used to create the skeleton? E.g. regionSize.width * json->scale?
Also for rotation, should we set this to 1 if the cocos2d-x image is rotated in its sprite sheet and 0 if it's not?
Any help would be greatly appreciated.
static unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0};
spAttachment* _SpriteSheetAttachmentLoader_createAttachment (spAttachmentLoader* loader, spSkin* skin, spAttachmentType type,
const char* name, const char* path) {
switch (type) {
case SP_ATTACHMENT_REGION: {
std::string spritePath = std::string(path) + ".png";
Sprite *region = Sprite::createWithSpriteFrameName(spritePath);
if(!region) {
_spAttachmentLoader_setError(loader, "SpriteFrame not found with path: ", path);
CC_SAFE_DELETE(region);
return 0;
}
spRegionAttachment* attachment;
const cocos2d::Size& regionSize = region->getContentSize();
const V3F_C4B_T2F_Quad spriteQuad = region->getQuad();
attachment = spRegionAttachment_create(name);
attachment->rendererObject = region;
region->retain();
spRegionAttachment_setUVs(attachment,
spriteQuad.bl.texCoords.u,
spriteQuad.bl.texCoords.v,
spriteQuad.tr.texCoords.u,
spriteQuad.tr.texCoords.v,
0);
attachment->regionOffsetX = 0;
attachment->regionOffsetY = 0;
attachment->regionWidth = regionSize.width;
attachment->regionHeight = regionSize.height;
attachment->regionOriginalWidth = regionSize.width;
attachment->regionOriginalHeight = regionSize.height;
return SUPER(attachment);
}
case SP_ATTACHMENT_MESH:
case SP_ATTACHMENT_LINKED_MESH: {
std::string spritePath = std::string(path) + ".png";
Sprite *region = Sprite::createWithSpriteFrameName(spritePath);
if(!region) {
_spAttachmentLoader_setError(loader, "SpriteFrame not found with path: ", path);
CC_SAFE_DELETE(region);
return 0;
}
spMeshAttachment* attachment;
const cocos2d::Size& regionSize = region->getContentSize();
const V3F_C4B_T2F_Quad spriteQuad = region->getQuad();
attachment = spMeshAttachment_create(name);
attachment->rendererObject = region;
region->retain();
attachment->regionU = spriteQuad.bl.texCoords.u;
attachment->regionV = spriteQuad.bl.texCoords.v;
attachment->regionU2 = spriteQuad.tr.texCoords.u;
attachment->regionV2 = spriteQuad.tr.texCoords.v;
attachment->regionOffsetX = region->getOffsetPosition().x;
attachment->regionOffsetY = region->getOffsetPosition().y;
attachment->regionRotate = 1;
attachment->regionWidth = regionSize.width;
attachment->regionHeight = regionSize.height;
attachment->regionOriginalWidth = regionSize.width;
attachment->regionOriginalHeight = regionSize.height;
return SUPER(SUPER(attachment));
}
case SP_ATTACHMENT_BOUNDING_BOX:
return SUPER(SUPER(spBoundingBoxAttachment_create(name)));
case SP_ATTACHMENT_PATH:
return SUPER(SUPER(spPathAttachment_create(name)));
default:
_spAttachmentLoader_setUnknownTypeError(loader, type);
return 0;
}
}
void _SpriteSheetAttachmentLoader_configureAttachment (spAttachmentLoader* loader, spAttachment* attachment) {
attachment->attachmentLoader = loader;
switch (attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* regionAttachment = SUB_CAST(spRegionAttachment, attachment);
//Getting region from sprite
Sprite* region = (Sprite*)regionAttachment->rendererObject;
// Create vertex aatachment from sprite texture
AttachmentVertices* attachmentVertices = new AttachmentVertices(region->getTexture(), 4, quadTriangles, 6);
V3F_C4B_T2F* vertices = attachmentVertices->_triangles->verts;
// Create uv's from sprite quad
const V3F_C4B_T2F_Quad& spriteQuad = region->getQuad();
vertices[1].texCoords = spriteQuad.tl.texCoords;
vertices[2].texCoords = spriteQuad.tr.texCoords;
vertices[3].texCoords = spriteQuad.br.texCoords;
vertices[0].texCoords = spriteQuad.bl.texCoords;
//Sefty delete sprite
region->release();
regionAttachment->rendererObject = attachmentVertices;
break;
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* meshAttachment = SUB_CAST(spMeshAttachment, attachment);
//Getting region from sprite
Sprite* region = (Sprite*)meshAttachment->rendererObject;
AttachmentVertices* attachmentVertices = new AttachmentVertices(region->getTexture(),
meshAttachment->super.worldVerticesLength >> 1, meshAttachment->triangles, meshAttachment->trianglesCount);
V3F_C4B_T2F* vertices = attachmentVertices->_triangles->verts;
for (int i = 0, ii = 0, nn = meshAttachment->super.worldVerticesLength; ii < nn; ++i, ii += 2) {
vertices[i].texCoords.u = meshAttachment->uvs[ii];
vertices[i].texCoords.v = meshAttachment->uvs[ii + 1];
}
region->release();
meshAttachment->rendererObject = attachmentVertices;
break;
}
default: ;
}
}
void _SpriteSheetAttachmentLoader_disposeAttachment (spAttachmentLoader* loader, spAttachment* attachment) {
switch (attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* regionAttachment = SUB_CAST(spRegionAttachment, attachment);
delete (AttachmentVertices*)regionAttachment->rendererObject;
break;
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* meshAttachment = SUB_CAST(spMeshAttachment, attachment);
delete (AttachmentVertices*)meshAttachment->rendererObject;
break;
}
default: ;
}
}
void _SpriteSheetAttachmentLoader_dispose (spAttachmentLoader* loader) {
SpriteSheetAttachmentLoader* self = SUB_CAST(SpriteSheetAttachmentLoader, loader);
spAttachmentLoader_dispose(SUPER_CAST(spAttachmentLoader, self->atlasAttachmentLoader));
_spAttachmentLoader_deinit(loader);
}
SpriteSheetAttachmentLoader* SpriteSheetAttachmentLoader_create (spAtlas* atlas) {
SpriteSheetAttachmentLoader* self = NEW(SpriteSheetAttachmentLoader);
_spAttachmentLoader_init(SUPER(self), _SpriteSheetAttachmentLoader_dispose, _SpriteSheetAttachmentLoader_createAttachment,
_SpriteSheetAttachmentLoader_configureAttachment, _SpriteSheetAttachmentLoader_disposeAttachment);
self->atlasAttachmentLoader = spAtlasAttachmentLoader_create(atlas);
return self;
}
No help?