cocos2dx-3.x spine换装

来源:互联网 发布:纹身图案软件 编辑:程序博客网 时间:2024/05/19 11:47

SpineNode.cpp文件


#include "SpineNode.h"

#include "SpineUtils.h"
using namespace cocos2d;


static Vector<Texture2D*>*  _displayTexs = nullptr;


struct _Entry
{
    int slotIndex;
    const char* name;
    spAttachment* attachment;
    _Entry* next;
};


typedef struct
{
    spSkin super;
    _Entry* entries;
} _spSkin;


SpineNode::SpineNode(spSkeletonData* skeletonData)
: SkeletonAnimation(skeletonData)
{
    
}


SpineNode::SpineNode(const std::string& skeletonDataFile, spAtlas* atlas, float scale)
: SkeletonAnimation(skeletonDataFile, atlas, scale)
{
    
}


SpineNode::SpineNode(const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
: SkeletonAnimation(skeletonDataFile, atlasFile, scale)
{
    
}


SpineNode* SpineNode::createWithData(spSkeletonData* skeletonData)
{
    SpineNode* node = new SpineNode(skeletonData);
    node->autorelease();
    return node;
}


SpineNode* SpineNode::createWithFile(const std::string& skeletonDataFile, spAtlas* atlas, float scale)
{
    SpineNode* node = new SpineNode(skeletonDataFile, atlas, scale);
    node->autorelease();
    return node;
}


SpineNode* SpineNode::createWithFile(const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
{
    SpineNode* node = new SpineNode(skeletonDataFile, atlasFile, scale);
    node->autorelease();
    return node;
}


bool SpineNode::isFlippedX() const
{
    return _skeleton->flipX != 0;
}


void SpineNode::setFlippedX(bool flippedX)
{
    _skeleton->flipX = flippedX ? 1 : 0;
}


bool SpineNode::isFlippedY() const
{
    return _skeleton->flipY != 0;
}


void SpineNode::setFlippedY(bool flippedY)
{
    _skeleton->flipY = flippedY ? 1 : 0;
}


bool SpineNode::replacementParts(const std::string& skinName, const std::string& attachmentName)
{
    CCLOG("in replacementParts 0");
    if (skinName.empty())
    {
        return false;
    }
    CCLOG("in replacementParts 1");
    spSkin *skin = spSkeletonData_findSkin(_skeleton->data, skinName.c_str());
    if (!skin) return false;
    CCLOG("in replacementParts 2");
    if (_skeleton->skin)
    {
        const _Entry *entry = reinterpret_cast<_spSkin *>(_skeleton->skin)->entries;
        while (entry)
        {
            spSlot *slot = _skeleton->slots[entry->slotIndex];
            if (strcmp(slot->data->name, attachmentName.c_str()) == 0)
            {
                spAttachment *attachment = spSkin_getAttachment(skin, entry->slotIndex, entry->name);
                if (attachment) spSlot_setAttachment(slot, attachment);
                CCLOG("in replacementParts 3");
                return true;
            }
            entry = entry->next;
        }
    }
    else
    {
        for (int i = 0; i < _skeleton->slotsCount; ++i)
        {
            spSlot* slot = _skeleton->slots[i];
            if (strcmp(slot->data->name, attachmentName.c_str()) == 0)
            {
                spAttachment* attachment = spSkin_getAttachment(skin, i, slot->data->attachmentName);
                if (attachment)
                {
                    spSlot_setAttachment(slot, attachment);
                    CCLOG("in replacementParts 4");
                    return true;
                }
            }
        }
    }
    CCLOG("in replacementParts 5");
    return false;
}


void SpineNode::setSlotVisble(const string& slotName, bool isVisble)
{
    auto slot = findSlot(slotName);
    if(slot)
    {
        slot->a = isVisble ? 1 : 0 ;
    }
    else
    {
        log(" ERRNO not find slot %s ",slotName.c_str());
        exit(1);
    }
}


void SpineNode::replaceSlotImage(const string& slotName,const string& imgPath)
{
//    SpineUtils::changeDisplay(this, slotName, imgPath);
    Texture2D* imgTex = Director::getInstance()->getTextureCache()->addImage(imgPath);
    replaceSlotImage(slotName, imgTex);
}


void SpineNode::replaceSlotImage(const string& slotName,Texture2D* imgTex)
{
    if (!_displayTexs)
    _displayTexs = new Vector<Texture2D*>();
    if (_displayTexs->find(imgTex) == _displayTexs->end())
    _displayTexs->pushBack(imgTex);
    
    
    spSlot* slot = this->findSlot(slotName);
    spAttachment* attchment = slot->attachment;
    if (attchment)
    {
        switch (slot->attachment->type) {
            case SP_ATTACHMENT_REGION:{
                spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
                spAtlas* atlas = this->getAtlas();
                spAtlasPage* page =  atlas->pages;
                spAtlasPage* newPage =  this->copyAtlasPage(atlas,page,imgTex);
                this->setAtlasRegion((spAtlasRegion*)attachment->rendererObject, newPage);
                
                spRegionAttachment_setUVs(attachment, 0, 0, 1, 1, 0);
                break;}
            case SP_ATTACHMENT_MESH:{
                spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
                spAtlas* atlas = this->getAtlas();
                spAtlasPage* page =  atlas->pages;
                spAtlasPage* newPage =  this->copyAtlasPage(atlas,page,imgTex);
                this->setAtlasRegion((spAtlasRegion*)attachment->rendererObject, newPage);
                
                attachment->regionU = 0;
                attachment->regionV = 0;
                attachment->regionU2 = 1;
                attachment->regionV2 = 1;
                
                spMeshAttachment_updateUVs(attachment);
                break;}
            case SP_ATTACHMENT_SKINNED_MESH:{
                spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
                spAtlas* atlas = this->getAtlas();
                spAtlasPage* page =  atlas->pages;
                spAtlasPage* newPage =  this->copyAtlasPage(atlas,page,imgTex);
                this->setAtlasRegion((spAtlasRegion*)attachment->rendererObject, newPage);
                
                attachment->regionU = 0;
                attachment->regionV = 0;
                attachment->regionU2 = 1;
                attachment->regionV2 = 1;
                attachment->regionRotate = 0;
                
                spSkinnedMeshAttachment_updateUVs(attachment);
                break;}
            
            default:
            break;
        }
    }
    else
    {
        log("==== attachment is nullptr ====");
    }
}


spAtlasPage* SpineNode::copyAtlasPage(spAtlas* atlas,spAtlasPage* src,Texture2D* imgTex)
{
    Size size = imgTex->getContentSize();
    spAtlasPage* page =  atlas->pages;
    spAtlasPage* newPage = spAtlasPage_create(atlas , "SelfAtlasPage");
    newPage->format = page->format;
    newPage->magFilter = page->magFilter;
    newPage->minFilter = page->minFilter;
    newPage->rendererObject = imgTex;
    newPage->width = size.width;
    newPage->height = size.height;
    newPage->uWrap = page->uWrap;
    newPage->vWrap = page->vWrap;
    
    return newPage;
}


void SpineNode::setAtlasRegion(spAtlasRegion* region,spAtlasPage* atlasPage)
{
    /*自己替换的图片只有一张*/
    region->height= atlasPage->height;
    region->width = atlasPage->width;
    region->offsetX = 0;
    region->offsetY = 0;
    region->originalHeight = atlasPage->height;
    region->originalWidth = atlasPage->width;
    region->rotate = 0;
    region->u = 0;
    region->v = 0;
    region->u2 = 1;
    region->v2 = 1;
    
    /*自己创建的Page自己释放一下,默认创建的,在骨骼动画释放时会释放*/
    if (region->page &&
        strcmp(region->page->name, "SelfAtlasPage") == 0)
    {
        FREE(region->page->name);
        FREE(region->page);
    }
    region->page = atlasPage;
}


spSkeleton* SpineNode::get_skeleton()
{
    return _skeleton;

}



SpineNode.h文件


#ifndef SPINENODE_H
#define SPINENODE_H


#include <iostream>
#include "cocos2d.h"
#include "editor-support/spine/spine-cocos2dx.h"
#include "editor-support/spine/extension.h"
#include "spine/SkeletonAnimation.h"
#include "string.h"


USING_NS_CC;
using namespace spine;
using namespace std;


class SpineNode final : public spine::SkeletonAnimation
{
public:
    static SpineNode* createWithData(spSkeletonData* skeletonData);
    static SpineNode* createWithFile(const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1);
    static SpineNode* createWithFile(const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
    
public:
    /**
     * 新增函数
     * 是否已经翻转x轴
     */
    bool isFlippedX() const;
    
    /**
     * 新增函数
     * 设置x轴翻转
     */
    void setFlippedX(bool flippedX);
    
    /**
     * 新增函数
     * 是否已经翻转y轴
     */
    bool isFlippedY() const;
    
    /**
     * 新增函数
     * 设置y轴翻转
     */
    void setFlippedY(bool flippedY);
    
    /**
     * 新增函数
     * 更换部件,将目标皮肤的的某个部件替换到当前皮肤上
     * @ 参数 std::string 皮肤名称, std::string 附件名称
     */
    bool replacementParts(const std::string& skinName, const std::string& attachmentName);
    
private:
    SpineNode(spSkeletonData* skeletonData);
    SpineNode(const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1);
    SpineNode(const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
    
private:
    cocos2d::CustomCommand _customCommand;
    
public:
    void setSlotVisble(const string& slotName, bool isVisble);
    
    void replaceSlotImage(const string& slotName,const string& imgPath);
    
    void replaceSlotImage(const string& slotName,Texture2D* imgTex);
    
    spSkeleton* get_skeleton();
    
private:
    spAtlasPage* copyAtlasPage(spAtlas* atlas,spAtlasPage* src,Texture2D* imgTex);
    
    void setAtlasRegion(spAtlasRegion* region,spAtlasPage* atlasPage);
};


#endif