前言:

cocos2dx 中spine 的换皮功能是一种静态的方法,也就是在创建 spine 动画的时候就必须将所有的皮肤全部加载,然后在代码中直接换皮,并且这种换皮是整体的切换,对于我们实际开发中这种方式是相当的不理想的。

注意:

本代码本人还只是简单的测试,如果还存在其它问题可以留言。

原理介绍:

对于spine动画而言动画的构成由  1、bone(骨骼)2、slot (槽)3、attachment(附件)组成,而动画中的图片资源都是通过附件来存储的。在spine的源文件由一个 xxx.atlas 文件  xxx.json 文件构成, xxx.atlas 文件其实就相当于我们的 plist 合图。 xxx.json 就是我们的动画描述文件,里面包含了。 bone、IK、slot、skin、animation、event 的描述。在解析后,所有图片附件都是元始于  skin 的,然后会挂载在 slot 下,也就是如果要换皮就需要替换 skin 和 slot 下对应的 attachment。

更新(2016/07/07):

今天又研究了下,其实还可以再简化一些,原先是创建新的attachment 替换旧的,其实我们可以基于旧的attachment修改显示的纹理就行了,简化后代码见最后修改代码。

更新(2016/07/08):

基于前面两个版本,因为换装一般都需要换来换去,那么如果能够保留原先的皮肤方便换回去还是很有必要的。因此本版本主要增加此类功能。

exmaple:

void* region = skeletonNode->replaceAttachmentImage("head", "head", Sprite::create("Images/head.png")->getSpriteFrame());
region = skeletonNode->replaceAttachmentByRegion("head", "head", region);

版本一实现代码:

1、接口声明:

bool replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 = nullptr);

2、接口实现:

static spAtlasPage* createNewPage(cocos2d::SpriteFrame* frame, spAttachment* oldAttachment)
{spAtlasPage *page = nullptr;spAtlasRegion* region = nullptr;switch (oldAttachment->type){case SP_ATTACHMENT_REGION:{spRegionAttachment* attachment = SUB_CAST(spRegionAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}case SP_ATTACHMENT_MESH:{spMeshAttachment* attachment = SUB_CAST(spMeshAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}case SP_ATTACHMENT_SKINNED_MESH: {spSkinnedMeshAttachment* attachment = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}}if (region == nullptr || region->page == nullptr) return page;Texture2D* texture = frame->getTexture();char pageName[20];itoa((int)texture, pageName, 16);spAtlasPage *searchPage = region->page->atlas->pages;spAtlasPage* lastPage = searchPage;while (searchPage != nullptr){if (strcmp(searchPage->name, pageName) == 0){page = searchPage;break;}searchPage = searchPage->next;if (searchPage != nullptr)lastPage = searchPage;}if (page != nullptr) return page;page = spAtlasPage_create(CONST_CAST(spAtlas*, region->page->atlas), pageName);texture->retain();page->rendererObject = texture;page->width = texture->getPixelsWide();page->height = texture->getPixelsHigh();lastPage->next = page;page->format = region->page->format;page->minFilter = region->page->minFilter;page->magFilter = region->page->magFilter;page->uWrap = region->page->uWrap;page->vWrap = region->page->vWrap;return page;
}static spAtlasRegion* createRegion(spAtlasPage *page, cocos2d::SpriteFrame* frame, spAttachment* oldAttachment)
{const char* name = oldAttachment->name;Texture2D* texture = frame->getTexture();spAtlasRegion *region = spAtlasRegion_create();region->page = page;MALLOC_STR(region->name, name);region->rotate = frame->isRotated();cocos2d::Rect rect = frame->getRectInPixels();region->x = rect.getMinX();region->y = rect.getMinY();region->width = rect.size.width;region->height = rect.size.height;cocos2d::Size originSize = frame->getOriginalSizeInPixels();region->originalWidth = originSize.width;region->originalHeight = originSize.height;region->u = region->x / (float)page->width;region->v = region->y / (float)page->height;if (region->rotate) {region->u2 = (region->x + region->height) / (float)page->width;region->v2 = (region->y + region->width) / (float)page->height;}else {region->u2 = (region->x + region->width) / (float)page->width;region->v2 = (region->y + region->height) / (float)page->height;}cocos2d::Vec2 offset = frame->getOffsetInPixels();region->offsetX = offset.x;region->offsetY = offset.y;region->index = -1;spAtlasRegion* lastRegion, *nextRegion; lastRegion = page->atlas->regions;nextRegion = region->next;while (nextRegion != nullptr){lastRegion = nextRegion;nextRegion = nextRegion->next;}lastRegion->next = region;return region;
}bool SkeletonRenderer::replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 /* = nullptr*/)
{spAttachment* oldAttachment = getAttachment(slotName, attachmentName);if (oldAttachment == nullptr) return false;spAttachment* newAttchment = nullptr;const char* name = oldAttachment->name;spAtlasPage *page = createNewPage(frame, oldAttachment);if (page == nullptr) return false;spAtlasRegion *region = createRegion(page, frame, oldAttachment);switch (oldAttachment->type) {case SP_ATTACHMENT_REGION: {spRegionAttachment* attachment;attachment = spRegionAttachment_create(name);attachment->rendererObject = region;spRegionAttachment_setUVs(attachment, region->u, region->v, region->u2, region->v2, region->rotate);attachment->regionOffsetX = region->offsetX;attachment->regionOffsetY = region->offsetY;attachment->regionWidth = region->width;attachment->regionHeight = region->height;attachment->regionOriginalWidth = region->originalWidth;attachment->regionOriginalHeight = region->originalHeight;newAttchment = SUPER(attachment);spRegionAttachment* oldRegion = SUB_CAST(spRegionAttachment, oldAttachment);attachment->x = oldRegion->x;attachment->y = oldRegion->y;attachment->scaleX = oldRegion->scaleX;attachment->scaleY = oldRegion->scaleY;attachment->rotation = oldRegion->rotation;attachment->width = oldRegion->width;attachment->height = oldRegion->height;attachment->r = oldRegion->r;attachment->g = oldRegion->g;attachment->b = oldRegion->b;attachment->a = oldRegion->a;spRegionAttachment_updateOffset(attachment);break;}case SP_ATTACHMENT_MESH: {spMeshAttachment* attachment;attachment = spMeshAttachment_create(name);attachment->rendererObject = region;attachment->regionU = region->u;attachment->regionV = region->v;attachment->regionU2 = region->u2;attachment->regionV2 = region->v2;attachment->regionRotate = region->rotate;attachment->regionOffsetX = region->offsetX;attachment->regionOffsetY = region->offsetY;attachment->regionWidth = region->width;attachment->regionHeight = region->height;attachment->regionOriginalWidth = region->originalWidth;attachment->regionOriginalHeight = region->originalHeight;newAttchment = SUPER(attachment);spMeshAttachment* oldMesh = SUB_CAST(spMeshAttachment, oldAttachment);attachment->verticesCount = oldMesh->verticesCount;attachment->vertices = oldMesh->vertices;oldMesh->vertices = 0;attachment->trianglesCount = oldMesh->trianglesCount;attachment->triangles = oldMesh->triangles;oldMesh->triangles = 0;attachment->regionUVs = oldMesh->regionUVs;oldMesh->regionUVs = 0;spMeshAttachment_updateUVs(attachment);attachment->r = oldMesh->r;attachment->g = oldMesh->g;attachment->b = oldMesh->b;attachment->a = oldMesh->a;attachment->hullLength = oldMesh->hullLength;attachment->edgesCount = oldMesh->edgesCount;attachment->edges = oldMesh->edges;oldMesh->edges = 0;attachment->width = oldMesh->width;attachment->height = oldMesh->height;break;}case SP_ATTACHMENT_SKINNED_MESH: {spSkinnedMeshAttachment* attachment;attachment = spSkinnedMeshAttachment_create(name);attachment->rendererObject = region;attachment->regionU = region->u;attachment->regionV = region->v;attachment->regionU2 = region->u2;attachment->regionV2 = region->v2;attachment->regionRotate = region->rotate;attachment->regionOffsetX = region->offsetX;attachment->regionOffsetY = region->offsetY;attachment->regionWidth = region->width;attachment->regionHeight = region->height;attachment->regionOriginalWidth = region->originalWidth;attachment->regionOriginalHeight = region->originalHeight;newAttchment = SUPER(attachment);spSkinnedMeshAttachment* oldMesh = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);int verticesCount, b, w, nn;float* vertices;attachment->uvsCount = oldMesh->uvsCount;attachment->regionUVs = oldMesh->regionUVs;oldMesh->regionUVs = 0;attachment->bonesCount = oldMesh->bonesCount;attachment->weightsCount = oldMesh->weightsCount;attachment->bones = oldMesh->bones;oldMesh->bones = 0;attachment->weights = oldMesh->weights;oldMesh->weights = 0;attachment->trianglesCount = oldMesh->trianglesCount;attachment->triangles = oldMesh->triangles;oldMesh->triangles = 0;spSkinnedMeshAttachment_updateUVs(attachment);attachment->r = oldMesh->r;attachment->g = oldMesh->g;attachment->b = oldMesh->b;attachment->a = oldMesh->a;attachment->hullLength = oldMesh->hullLength;attachment->edges = oldMesh->edges;oldMesh->edges = 0;attachment->edgesCount = oldMesh->edgesCount;attachment->width = oldMesh->width;attachment->height = oldMesh->height;break;}}if (newAttchment == nullptr)return false;spSkin* skin = _skeleton->skin == nullptr ? _skeleton->data->defaultSkin : _skeleton->skin;for (int i = 0; i < _skeleton->slotsCount; ++i) {spSlot* slot = _skeleton->slots[i];if (slot->data->attachmentName != nullptr && strcmp(slot->data->attachmentName, attachmentName) == 0){if (attachment2 == nullptr) CONST_CAST(spAttachment*, slot->attachment) = newAttchment;return spSkin_setAttachment(skin, i, attachment2 == nullptr ? attachmentName : attachment2, newAttchment);}}return false;
}
int spSkin_setAttachment(const spSkin* self, int slotIndex, const char* name, spAttachment* attachment) // 在 skin.c 文件中添加
{_Entry* entry = SUB_CAST(_spSkin, self)->entries;while (entry) {if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0){spAttachment* odlAttachment = entry->attachment;entry->attachment = attachment;spAttachment_dispose(odlAttachment);return 1;}entry = entry->next;}return 0;
}

2016/07/07 更新,基于版本一修改:

bool SkeletonRenderer::replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 /* = nullptr*/)
{spAttachment* oldAttachment = nullptr;spSkin* skin = _skeleton->skin == nullptr ? _skeleton->data->defaultSkin : _skeleton->skin;for (int i = 0; i < _skeleton->slotsCount; ++i){spSlot* slot = _skeleton->slots[i];if (slot->data->attachmentName != nullptr && strcmp(slot->data->attachmentName, attachmentName) == 0){oldAttachment = spSkin_getAttachment(skin, i, attachment2 == nullptr ? attachmentName : attachment2);}}if (oldAttachment == nullptr) return false;spAttachment* newAttchment = nullptr;const char* name = oldAttachment->name;spAtlasPage *page = createNewPage(frame, oldAttachment);if (page == nullptr) return false;spAtlasRegion *region = createRegion(page, frame, oldAttachment);switch (oldAttachment->type) {case SP_ATTACHMENT_REGION: {spRegionAttachment* oldRegion = SUB_CAST(spRegionAttachment, oldAttachment);oldRegion->rendererObject = region;spRegionAttachment_setUVs(oldRegion, region->u, region->v, region->u2, region->v2, region->rotate);oldRegion->regionOffsetX = region->offsetX;oldRegion->regionOffsetY = region->offsetY;oldRegion->regionWidth = region->width;oldRegion->regionHeight = region->height;oldRegion->regionOriginalWidth = region->originalWidth;oldRegion->regionOriginalHeight = region->originalHeight;spRegionAttachment_updateOffset(oldRegion);break;}case SP_ATTACHMENT_MESH: {spMeshAttachment* oldMesh = SUB_CAST(spMeshAttachment, oldAttachment);oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spMeshAttachment_updateUVs(oldMesh);break;}case SP_ATTACHMENT_SKINNED_MESH: {spSkinnedMeshAttachment* oldMesh = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spSkinnedMeshAttachment_updateUVs(oldMesh);break;}}return false;
}

接口使用说明:

slotName: 要替换皮肤附件所在slot名字

attachmentName: 要替换皮肤在 slot 上的 附件名字

frame: 要替换皮肤图片的 SpriteFrame,为了能够像spine一样利用合图的优势,这里使用的是SpriteFrame,同一个合图上的 SpriteFrame 会复用一个 spAtlasPage。

attachmentName2: 如果存在那种 slot 下有多个 切换用的 皮肤图片,而在slot下的名字都是同一个,那么就需要 传递这个名字默认为 nullptr

example:

skeletonNode = SkeletonAnimation::createWithFile("spine/alien.json", "spine/alien.atlas", 0.5f);  // 此spine动画为spine 自带的 example 那个爆头动画
skeletonNode->replaceAttachmentImage("head", "head", Sprite::create("Images/r1.png")->getSpriteFrame(), "burst01");
skeletonNode->replaceAttachmentImage("head", "head", Sprite::create("Images/r1.png")->getSpriteFrame(), "burst02");
skeletonNode->replaceAttachmentImage("head", "head", Sprite::create("Images/r1.png")->getSpriteFrame());

2016/07/07 更新

bool SkeletonRenderer::replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 /* = nullptr*/)
{spAttachment* oldAttachment = nullptr;spSkin* skin = _skeleton->skin == nullptr ? _skeleton->data->defaultSkin : _skeleton->skin;for (int i = 0; i < _skeleton->slotsCount; ++i){spSlot* slot = _skeleton->slots[i];if (slot->data->attachmentName != nullptr && strcmp(slot->data->attachmentName, attachmentName) == 0){oldAttachment = spSkin_getAttachment(skin, i, attachment2 == nullptr ? attachmentName : attachment2);}}if (oldAttachment == nullptr) return false;spAttachment* newAttchment = nullptr;const char* name = oldAttachment->name;spAtlasPage *page = createNewPage(frame, oldAttachment);if (page == nullptr) return false;spAtlasRegion *region = createRegion(page, frame, oldAttachment);switch (oldAttachment->type) {case SP_ATTACHMENT_REGION: {spRegionAttachment* oldRegion = SUB_CAST(spRegionAttachment, oldAttachment);oldRegion->rendererObject = region;spRegionAttachment_setUVs(oldRegion, region->u, region->v, region->u2, region->v2, region->rotate);oldRegion->regionOffsetX = region->offsetX;oldRegion->regionOffsetY = region->offsetY;oldRegion->regionWidth = region->width;oldRegion->regionHeight = region->height;oldRegion->regionOriginalWidth = region->originalWidth;oldRegion->regionOriginalHeight = region->originalHeight;spRegionAttachment_updateOffset(oldRegion);break;}case SP_ATTACHMENT_MESH: {spMeshAttachment* oldMesh = SUB_CAST(spMeshAttachment, oldAttachment);oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spMeshAttachment_updateUVs(oldMesh);break;}case SP_ATTACHMENT_SKINNED_MESH: {spSkinnedMeshAttachment* oldMesh = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spSkinnedMeshAttachment_updateUVs(oldMesh);break;}}return false;
}

2016/07/08 版本三:

    spAtlasRegion*  replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 = nullptr);spAtlasRegion*    replaceAttachmentByRegion(const char* slotName, const char* attachmentName, void* region, const char* attachment2 = nullptr);
private:spAttachment*   getAttachmentFromSlot(const char* slotName, const char* attachmentName, const char* attachment2 = nullptr);spAtlasRegion*  changeAttachment(spAttachment* attachment, spAtlasRegion* region);
static spAtlasPage* createNewPage(cocos2d::SpriteFrame* frame, spAttachment* oldAttachment)
{spAtlasPage *page = nullptr;spAtlasRegion* region = nullptr;switch (oldAttachment->type){case SP_ATTACHMENT_REGION:{spRegionAttachment* attachment = SUB_CAST(spRegionAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}case SP_ATTACHMENT_MESH:{spMeshAttachment* attachment = SUB_CAST(spMeshAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}case SP_ATTACHMENT_SKINNED_MESH: {spSkinnedMeshAttachment* attachment = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);region = SUB_CAST(spAtlasRegion, attachment->rendererObject);break;}}if (region == nullptr || region->page == nullptr) return page;Texture2D* texture = frame->getTexture();char pageName[20];itoa((int)texture, pageName, 16);spAtlasPage *searchPage = region->page->atlas->pages;spAtlasPage* lastPage = searchPage;while (searchPage != nullptr){if (strcmp(searchPage->name, pageName) == 0){page = searchPage;break;}searchPage = searchPage->next;if (searchPage != nullptr)lastPage = searchPage;}if (page != nullptr) return page;page = spAtlasPage_create(CONST_CAST(spAtlas*, region->page->atlas), pageName);texture->retain();page->rendererObject = texture;page->width = texture->getPixelsWide();page->height = texture->getPixelsHigh();lastPage->next = page;page->format = region->page->format;page->minFilter = region->page->minFilter;page->magFilter = region->page->magFilter;page->uWrap = region->page->uWrap;page->vWrap = region->page->vWrap;return page;
}static spAtlasRegion* createRegion(spAtlasPage *page, cocos2d::SpriteFrame* frame, spAttachment* oldAttachment)
{const char* name = oldAttachment->name;Texture2D* texture = frame->getTexture();spAtlasRegion *region = spAtlasRegion_create();region->page = page;MALLOC_STR(region->name, name);region->rotate = frame->isRotated();cocos2d::Rect rect = frame->getRectInPixels();region->x = rect.getMinX();region->y = rect.getMinY();region->width = rect.size.width;region->height = rect.size.height;cocos2d::Size originSize = frame->getOriginalSizeInPixels();region->originalWidth = originSize.width;region->originalHeight = originSize.height;region->u = region->x / (float)page->width;region->v = region->y / (float)page->height;if (region->rotate) {region->u2 = (region->x + region->height) / (float)page->width;region->v2 = (region->y + region->width) / (float)page->height;}else {region->u2 = (region->x + region->width) / (float)page->width;region->v2 = (region->y + region->height) / (float)page->height;}cocos2d::Vec2 offset = frame->getOffsetInPixels();region->offsetX = offset.x;region->offsetY = offset.y;region->index = -1;spAtlasRegion* lastRegion, *nextRegion; lastRegion = page->atlas->regions;nextRegion = region->next;while (nextRegion != nullptr){lastRegion = nextRegion;nextRegion = nextRegion->next;}lastRegion->next = region;return region;
}spAttachment*  SkeletonRenderer::getAttachmentFromSlot(const char* slotName, const char* attachmentName, const char* attachment2 /*= nullptr*/)
{spAttachment* attachment = nullptr;spSkin* skin = _skeleton->skin == nullptr ? _skeleton->data->defaultSkin : _skeleton->skin;for (int i = 0; i < _skeleton->slotsCount; ++i){spSlot* slot = _skeleton->slots[i];if (slot->data->attachmentName != nullptr && strcmp(slot->data->attachmentName, attachmentName) == 0){attachment = spSkin_getAttachment(skin, i, attachment2 == nullptr ? attachmentName : attachment2);}}return attachment;
}spAtlasRegion* SkeletonRenderer::changeAttachment(spAttachment* oldAttachment, spAtlasRegion* region)
{spAtlasRegion* oldRegion = nullptr;if (oldAttachment == nullptr || region == nullptr) return oldRegion;switch (oldAttachment->type){case SP_ATTACHMENT_REGION:{spRegionAttachment* oldRegionAttachment = SUB_CAST(spRegionAttachment, oldAttachment);oldRegion = (spAtlasRegion*)oldRegionAttachment->rendererObject;oldRegionAttachment->rendererObject = region;spRegionAttachment_setUVs(oldRegionAttachment, region->u, region->v, region->u2, region->v2, region->rotate);oldRegionAttachment->regionOffsetX = region->offsetX;oldRegionAttachment->regionOffsetY = region->offsetY;oldRegionAttachment->regionWidth = region->width;oldRegionAttachment->regionHeight = region->height;oldRegionAttachment->regionOriginalWidth = region->originalWidth;oldRegionAttachment->regionOriginalHeight = region->originalHeight;spRegionAttachment_updateOffset(oldRegionAttachment);break;}case SP_ATTACHMENT_MESH:{spMeshAttachment* oldMesh = SUB_CAST(spMeshAttachment, oldAttachment);oldRegion = (spAtlasRegion*)oldMesh->rendererObject;oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spMeshAttachment_updateUVs(oldMesh);break;}case SP_ATTACHMENT_SKINNED_MESH:{spSkinnedMeshAttachment* oldMesh = SUB_CAST(spSkinnedMeshAttachment, oldAttachment);oldRegion = (spAtlasRegion*)oldMesh->rendererObject;oldMesh->rendererObject = region;oldMesh->regionU = region->u;oldMesh->regionV = region->v;oldMesh->regionU2 = region->u2;oldMesh->regionV2 = region->v2;oldMesh->regionRotate = region->rotate;oldMesh->regionOffsetX = region->offsetX;oldMesh->regionOffsetY = region->offsetY;oldMesh->regionWidth = region->width;oldMesh->regionHeight = region->height;oldMesh->regionOriginalWidth = region->originalWidth;oldMesh->regionOriginalHeight = region->originalHeight;spSkinnedMeshAttachment_updateUVs(oldMesh);break;}}return oldRegion;
}spAtlasRegion*  SkeletonRenderer::replaceAttachmentImage(const char* slotName, const char* attachmentName, cocos2d::SpriteFrame* frame, const char* attachment2 /* = nullptr*/)
{spAttachment* oldAttachment = getAttachmentFromSlot(slotName, attachmentName, attachment2);if (oldAttachment == nullptr) return false;spAttachment* newAttchment = nullptr;const char* name = oldAttachment->name;spAtlasPage *page = createNewPage(frame, oldAttachment);if (page == nullptr) return false;spAtlasRegion *region = createRegion(page, frame, oldAttachment);return replaceAttachmentByRegion(slotName, attachmentName, region, attachment2);
}spAtlasRegion* SkeletonRenderer::replaceAttachmentByRegion(const char* slotName, const char* attachmentName, void* region, const char* attachment2 /* = nullptr */)
{return changeAttachment(getAttachmentFromSlot(slotName, attachmentName, attachment2), (spAtlasRegion*)region);
}

spine 动态换皮功能相关推荐

  1. Unity Spine 局部换皮

    1.Spine元素主要包含皮肤(Skin).骨骼(Bone).插槽(Slot).附件(Attachment).及附件下的图片. 2.而皮肤(Skin)包含了插槽信息.附件信息,如果我们有两套相同构成的 ...

  2. cocoscreator 中 spine局部换皮

    1 多attachment切换 let goblingirl = this.spine2.findSlot("left-arm");let attachment = gobling ...

  3. cocoscreator中spine局部换皮的探索

    1.需求情况 书之国中需要一个人物捏脸系统,要求可以让用户自由选择身体不同部位的形象,比如头发.眼睛.眉毛.上衣.裤子等.已经支持RegionAttacment和MeshAttachment,而且在r ...

  4. 动态改变标题_小米相册更新,新增动态换天/赛博朋克/MIUI12界面等等!

    嗨咯,各位小伙伴们大家晚上好呀,今天为大家介绍一款灰度测试应用"MIUI相册"也就是大家小米手机里面的相册app,为方便解说,以下统称为"相册"更新后打开相册第 ...

  5. 使用ant-design-vue实现换肤功能

    1.安装ant-design-vue npm i ant-design-vue --save 2.在main.js中引入 `import Antd from 'ant-design-vue'``imp ...

  6. vue动态换肤(自定义主题)

    前言 有时候一个项目的主题并不能满足所有人的审美, 所以这个时候就需要换肤功能登场了. 下面是一个换肤demo, 思路很简单,定义一个全局css变量,然后在页面根元素获取变量并动态修改这个变量值即可完 ...

  7. 使用 css/less 动态更换主题色(换肤功能)

    前言 说起换肤功能,前端应该是非常熟悉了? 一般来说换肤的需求分为几种: 1. 纯前端,直接在页面前端通过点击自由切换限定的几种主题色,切换之后主题色变量存到本地浏览器 2. 在后台配置好色值,传到前 ...

  8. 动态更换主题色(换肤功能)

    文章目录 对于可供选择的颜色/主题样式换肤的实现 一个全局class控制样式切换 JS改变href属性值切换样式表,例如 HTML 的 rel 属性下的 alternate 实现: 对于制定动态色值换 ...

  9. android工程换背景图片,android换肤功能 如何动态获取控件中背景图片的资源id?

    这个是在在做一个换肤功能时遇到的问题. 对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像R.drawable.background(喂,这不是废话 ...

最新文章

  1. 记 fastjson泛型转对象 第一次可以正常转,第二次就变成JSONArray 问题
  2. 计算机类|期刊】SCI期刊专刊截稿信息4条
  3. [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
  4. 模块化数据中心成未来互联网企业首选
  5. 一文看尽8篇目标检测最新论文(EfficientDet/EdgeNet/ASFF/RoIMix/SCL/EFGRNet等)
  6. 远程桌面连接数超过最大限制解决方法
  7. 【C语言进阶深度学习记录】二十八 数组指针与指针数组的分析
  8. C++(17)--详解const
  9. Repeater绑定ArrayList数据源
  10. 目录_视觉SLAM十四讲_0
  11. 4SUM Leetcode
  12. 使用matlab解决收益和风险问题 数学建模算法与应用
  13. oracle mysql 推荐书籍
  14. Asterisk-Javanbsp;教程(中文版)…
  15. 常见路由器默认用户名和密码
  16. css 实现一个尖角_纯CSS实现页面的尖角、小三角、不同方向尖角的方法小结
  17. Python爬虫实践-网易云音乐
  18. python图片镜像翻转_python中镜像实现方法
  19. Window SendMessage,PostMessage分析
  20. 避免论文查重小窍门五则

热门文章

  1. protobuf repeated数组类型的使用
  2. python案例——数学问题案例
  3. MATLAB错误使用 surf (第 71 行) X、Y、Z 和 C 不能是复数。解决办法。
  4. python doc 转docx
  5. 移动支付模式再添新军:指纹支付
  6. 腾讯地图标记点击事件
  7. 第4章 数据的概括性度量
  8. 用原生js代码实现虚拟滚动条
  9. Python网络爬虫的概念和基本原理
  10. 读懂2014年全球互联网广告新生态