spine 动态换皮功能

前言:

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);
}


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值