cocos2dx 3.17 spine怎么实现动态换肤?求指教

void HXSkeletonAnimation::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
SkeletonBatch* batch = SkeletonBatch::getInstance();
SkeletonTwoColorBatch* twoColorBatch = SkeletonTwoColorBatch::getInstance();
bool isTwoColorTint = this->isTwoColorTint();

if (_effect) _effect->begin(_effect, _skeleton);

Color4F nodeColor;
nodeColor.r = getDisplayedColor().r / (float)255;
nodeColor.g = getDisplayedColor().g / (float)255;
nodeColor.b = getDisplayedColor().b / (float)255;
nodeColor.a = getDisplayedOpacity() / (float)255;

Color4F color;
Color4F darkColor;
AttachmentVertices* attachmentVertices = nullptr;
TwoColorTrianglesCommand* lastTwoColorTrianglesCommand = nullptr;
for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
    spSlot* slot = _skeleton->drawOrder[i];
    if (!slot->attachment) {
        spSkeletonClipping_clipEnd(_clipper, slot);
        continue;
    }

    cocos2d::TrianglesCommand::Triangles triangles;
    TwoColorTriangles trianglesTwoColor;
    
    switch (slot->attachment->type) {
        case SP_ATTACHMENT_REGION: {

            if(strcmp(slot->data->name,"face") == 0){
                CCLOG("face slot SP_ATTACHMENT_REGION");
            }
            
            spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
            attachmentVertices = getAttachmentVertices(attachment);
            
            if (!isTwoColorTint) {
                triangles.indices = attachmentVertices->_triangles->indices;
                triangles.indexCount = attachmentVertices->_triangles->indexCount;
                triangles.verts = batch->allocateVertices(attachmentVertices->_triangles->vertCount);
                triangles.vertCount = attachmentVertices->_triangles->vertCount;
                memcpy(triangles.verts, attachmentVertices->_triangles->verts, sizeof(cocos2d::V3F_C4B_T2F) * attachmentVertices->_triangles->vertCount);
                spRegionAttachment_computeWorldVertices(attachment, slot->bone, (float*)triangles.verts, 0, 6);
            } else {
                trianglesTwoColor.indices = attachmentVertices->_triangles->indices;
                trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
                trianglesTwoColor.verts = twoColorBatch->allocateVertices(attachmentVertices->_triangles->vertCount);
                trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
                for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
                    trianglesTwoColor.verts[ii].texCoords = attachmentVertices->_triangles->verts[ii].texCoords;
                }
                spRegionAttachment_computeWorldVertices(attachment, slot->bone, (float*)trianglesTwoColor.verts, 0, 7);
            }
            
            color.r = attachment->color.r;
            color.g = attachment->color.g;
            color.b = attachment->color.b;
            color.a = attachment->color.a;
            
            break;
        }
        case SP_ATTACHMENT_MESH: {
            
            if(strcmp(slot->data->name,"face") == 0){
                CCLOG("face slot SP_ATTACHMENT_MESH");
            }
            
            spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
            attachmentVertices = getAttachmentVertices(attachment);
            
            if (!isTwoColorTint) {
                triangles.indices = attachmentVertices->_triangles->indices;
                triangles.indexCount = attachmentVertices->_triangles->indexCount;
                triangles.verts = batch->allocateVertices(attachmentVertices->_triangles->vertCount);
                triangles.vertCount = attachmentVertices->_triangles->vertCount;
                memcpy(triangles.verts, attachmentVertices->_triangles->verts, sizeof(cocos2d::V3F_C4B_T2F) * attachmentVertices->_triangles->vertCount);
                spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, triangles.vertCount * sizeof(cocos2d::V3F_C4B_T2F) / 4, (float*)triangles.verts, 0, 6);
            } else {
                trianglesTwoColor.indices = attachmentVertices->_triangles->indices;
                trianglesTwoColor.indexCount = attachmentVertices->_triangles->indexCount;
                trianglesTwoColor.verts = twoColorBatch->allocateVertices(attachmentVertices->_triangles->vertCount);
                trianglesTwoColor.vertCount = attachmentVertices->_triangles->vertCount;
                for (int ii = 0; ii < trianglesTwoColor.vertCount; ii++) {
                    trianglesTwoColor.verts[ii].texCoords = attachmentVertices->_triangles->verts[ii].texCoords;
                }
                spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, trianglesTwoColor.vertCount * sizeof(V3F_C4B_C4B_T2F) / 4, (float*)trianglesTwoColor.verts, 0, 7);
            }
            
            color.r = attachment->color.r;
            color.g = attachment->color.g;
            color.b = attachment->color.b;
            color.a = attachment->color.a;
            
            break;
        }
        case SP_ATTACHMENT_CLIPPING: {
            
            if(strcmp(slot->data->name,"face") == 0){
                CCLOG("face slot SP_ATTACHMENT_CLIPPING");
            }
            
            spClippingAttachment* clip = (spClippingAttachment*)slot->attachment;
            spSkeletonClipping_clipStart(_clipper, slot, clip);
        }
        default:
            
            
            if(strcmp(slot->data->name,"face") == 0){
                CCLOG("face slot SP_ATTACHMENT_CLIPPING");
            }
            
            spSkeletonClipping_clipEnd(_clipper, slot);
            continue;
    }
    
    if (slot->darkColor) {
        darkColor.r = slot->darkColor->r * 255;
        darkColor.g = slot->darkColor->g * 255;
        darkColor.b = slot->darkColor->b * 255;
    } else {
        darkColor.r = 0;
        darkColor.g = 0;
        darkColor.b = 0;
    }
    
    color.a *= nodeColor.a * _skeleton->color.a * slot->color.a * 255;
    // skip rendering if the color of this attachment is 0
    if (color.a == 0){
        spSkeletonClipping_clipEnd(_clipper, slot);
        continue;
    }
    float multiplier = _premultipliedAlpha ? color.a : 255;
    color.r *= nodeColor.r * _skeleton->color.r * slot->color.r * multiplier;
    color.g *= nodeColor.g * _skeleton->color.g * slot->color.g * multiplier;
    color.b *= nodeColor.b * _skeleton->color.b * slot->color.b * multiplier;
    
    BlendFunc blendFunc;
    switch (slot->data->blendMode) {
        case SP_BLEND_MODE_ADDITIVE:
            blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
            blendFunc.dst = GL_ONE;
            break;
        case SP_BLEND_MODE_MULTIPLY:
            blendFunc.src = GL_DST_COLOR;
            blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
            break;
        case SP_BLEND_MODE_SCREEN:
            blendFunc.src = GL_ONE;
            blendFunc.dst = GL_ONE_MINUS_SRC_COLOR;
            break;
        default:
            blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
            blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
    }
    
    if (!isTwoColorTint) {
        if (spSkeletonClipping_isClipping(_clipper)) {
            spSkeletonClipping_clipTriangles(_clipper, (float*)&triangles.verts[0].vertices, triangles.vertCount * sizeof(cocos2d::V3F_C4B_T2F) / 4, triangles.indices, triangles.indexCount, (float*)&triangles.verts[0].texCoords, 6);
            batch->deallocateVertices(triangles.vertCount);
            
            if (_clipper->clippedTriangles->size == 0){
                spSkeletonClipping_clipEnd(_clipper, slot);
                continue;
            }
            
            triangles.vertCount = _clipper->clippedVertices->size >> 1;
            triangles.verts = batch->allocateVertices(triangles.vertCount);
            triangles.indexCount = _clipper->clippedTriangles->size;
            triangles.indices = batch->allocateIndices(triangles.indexCount);
            memcpy(triangles.indices, _clipper->clippedTriangles->items, sizeof(unsigned short) * _clipper->clippedTriangles->size);
            
            cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags);
            
            float* verts = _clipper->clippedVertices->items;
            float* uvs = _clipper->clippedUVs->items;
            if (_effect) {
                spColor light;
                spColor dark;
                light.r = color.r / 255.0f;
                light.g = color.g / 255.0f;
                light.b = color.b / 255.0f;
                light.a = color.a / 255.0f;
                dark.r = dark.g = dark.b = dark.a = 0;
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv+=2) {
                    V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    spColor lightCopy = light;
                    spColor darkCopy = dark;
                    vertex->vertices.x = verts[vv];
                    vertex->vertices.y = verts[vv + 1];
                    vertex->texCoords.u = uvs[vv];
                    vertex->texCoords.v = uvs[vv + 1];
                    _effect->transform(_effect, &vertex->vertices.x, &vertex->vertices.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
                    vertex->colors.r = (GLubyte)(lightCopy.r * 255);
                    vertex->colors.g = (GLubyte)(lightCopy.g * 255);
                    vertex->colors.b = (GLubyte)(lightCopy.b * 255);
                    vertex->colors.a = (GLubyte)(lightCopy.a * 255);
                }
            } else {
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv+=2) {
                    V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    vertex->vertices.x = verts[vv];
                    vertex->vertices.y = verts[vv + 1];
                    vertex->texCoords.u = uvs[vv];
                    vertex->texCoords.v = uvs[vv + 1];
                    vertex->colors.r = (GLubyte)color.r;
                    vertex->colors.g = (GLubyte)color.g;
                    vertex->colors.b = (GLubyte)color.b;
                    vertex->colors.a = (GLubyte)color.a;
                }
            }
        } else {
            cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags);
            
            if (_effect) {
                spColor light;
                spColor dark;
                light.r = color.r / 255.0f;
                light.g = color.g / 255.0f;
                light.b = color.b / 255.0f;
                light.a = color.a / 255.0f;
                dark.r = dark.g = dark.b = dark.a = 0;
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
                    V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    spColor lightCopy = light;
                    spColor darkCopy = dark;
                    _effect->transform(_effect, &vertex->vertices.x, &vertex->vertices.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
                    vertex->colors.r = (GLubyte)(lightCopy.r * 255);
                    vertex->colors.g = (GLubyte)(lightCopy.g * 255);
                    vertex->colors.b = (GLubyte)(lightCopy.b * 255);
                    vertex->colors.a = (GLubyte)(lightCopy.a * 255);
                }
            } else {
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
                    V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    vertex->colors.r = (GLubyte)color.r;
                    vertex->colors.g = (GLubyte)color.g;
                    vertex->colors.b = (GLubyte)color.b;
                    vertex->colors.a = (GLubyte)color.a;
                }
            }
        }
    } else {
        if (spSkeletonClipping_isClipping(_clipper)) {
            spSkeletonClipping_clipTriangles(_clipper, (float*)&trianglesTwoColor.verts[0].position, trianglesTwoColor.vertCount * sizeof(V3F_C4B_C4B_T2F) / 4, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float*)&trianglesTwoColor.verts[0].texCoords, 7);
            twoColorBatch->deallocateVertices(trianglesTwoColor.vertCount);
            
            if (_clipper->clippedTriangles->size == 0){
                spSkeletonClipping_clipEnd(_clipper, slot);
                continue;
            }
            
            trianglesTwoColor.vertCount = _clipper->clippedVertices->size >> 1;
            trianglesTwoColor.verts = twoColorBatch->allocateVertices(trianglesTwoColor.vertCount);
            trianglesTwoColor.indexCount = _clipper->clippedTriangles->size;
            trianglesTwoColor.indices = twoColorBatch->allocateIndices(trianglesTwoColor.indexCount);
            memcpy(trianglesTwoColor.indices, _clipper->clippedTriangles->items, sizeof(unsigned short) * _clipper->clippedTriangles->size);
            
            TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags);
            
            float* verts = _clipper->clippedVertices->items;
            float* uvs = _clipper->clippedUVs->items;
            
            if (_effect) {
                spColor light;
                spColor dark;
                light.r = color.r / 255.0f;
                light.g = color.g / 255.0f;
                light.b = color.b / 255.0f;
                light.a = color.a / 255.0f;
                dark.r = darkColor.r / 255.0f;
                dark.g = darkColor.g / 255.0f;
                dark.b = darkColor.b / 255.0f;
                dark.a = darkColor.a / 255.0f;
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv += 2) {
                    V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    spColor lightCopy = light;
                    spColor darkCopy = dark;
                    vertex->position.x = verts[vv];
                    vertex->position.y = verts[vv + 1];
                    vertex->texCoords.u = uvs[vv];
                    vertex->texCoords.v = uvs[vv + 1];
                    _effect->transform(_effect, &vertex->position.x, &vertex->position.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
                    vertex->color.r = (GLubyte)(lightCopy.r * 255);
                    vertex->color.g = (GLubyte)(lightCopy.g * 255);
                    vertex->color.b = (GLubyte)(lightCopy.b * 255);
                    vertex->color.a = (GLubyte)(lightCopy.a * 255);
                    vertex->color2.r = (GLubyte)(darkCopy.r * 255);
                    vertex->color2.g = (GLubyte)(darkCopy.g * 255);
                    vertex->color2.b = (GLubyte)(darkCopy.b * 255);
                    vertex->color2.a = 1;
                }
            } else {
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv += 2) {
                    V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    vertex->position.x = verts[vv];
                    vertex->position.y = verts[vv + 1];
                    vertex->texCoords.u = uvs[vv];
                    vertex->texCoords.v = uvs[vv + 1];
                    vertex->color.r = (GLubyte)color.r;
                    vertex->color.g = (GLubyte)color.g;
                    vertex->color.b = (GLubyte)color.b;
                    vertex->color.a = (GLubyte)color.a;
                    vertex->color2.r = (GLubyte)darkColor.r;
                    vertex->color2.g = (GLubyte)darkColor.g;
                    vertex->color2.b = (GLubyte)darkColor.b;
                    vertex->color2.a = 1;
                }
            }
        } else {
            TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags);
            
            if (_effect) {
                spColor light;
                spColor dark;
                light.r = color.r / 255.0f;
                light.g = color.g / 255.0f;
                light.b = color.b / 255.0f;
                light.a = color.a / 255.0f;
                dark.r = darkColor.r / 255.0f;
                dark.g = darkColor.g / 255.0f;
                dark.b = darkColor.b / 255.0f;
                dark.a = darkColor.a / 255.0f;
                
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
                    V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    spColor lightCopy = light;
                    spColor darkCopy = dark;
                    _effect->transform(_effect, &vertex->position.x, &vertex->position.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
                    vertex->color.r = (GLubyte)(lightCopy.r * 255);
                    vertex->color.g = (GLubyte)(lightCopy.g * 255);
                    vertex->color.b = (GLubyte)(lightCopy.b * 255);
                    vertex->color.a = (GLubyte)(lightCopy.a * 255);
                    vertex->color2.r = (GLubyte)(darkCopy.r * 255);
                    vertex->color2.g = (GLubyte)(darkCopy.g * 255);
                    vertex->color2.b = (GLubyte)(darkCopy.b * 255);
                    vertex->color2.a = 1;
                }
            } else {
                for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
                    V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
                    vertex->color.r = (GLubyte)color.r;
                    vertex->color.g = (GLubyte)color.g;
                    vertex->color.b = (GLubyte)color.b;
                    vertex->color.a = (GLubyte)color.a;
                    vertex->color2.r = (GLubyte)darkColor.r;
                    vertex->color2.g = (GLubyte)darkColor.g;
                    vertex->color2.b = (GLubyte)darkColor.b;
                    vertex->color2.a = 1;
                }
            }
        }
    }
    spSkeletonClipping_clipEnd(_clipper, slot);
}
spSkeletonClipping_clipEnd2(_clipper);

if (lastTwoColorTrianglesCommand) {
    Node* parent = this->getParent();
    
    // We need to decide if we can postpone flushing the current
    // batch. We can postpone if the next sibling node is a
    // two color tinted skeleton with the same global-z.
    // The parent->getChildrenCount() > 100 check is a hack
    // as checking for a sibling is an O(n) operation, and if
    // all children of this nodes parent are skeletons, we
    // are in O(n2) territory.
    if (!parent || parent->getChildrenCount() > 100 || getChildrenCount() != 0) {
        lastTwoColorTrianglesCommand->setForceFlush(true);
    } else {
        Vector<Node*>& children = parent->getChildren();
        Node* sibling = nullptr;
        for (ssize_t i = 0; i < children.size(); i++) {
            if (children.at(i) == this) {
                if (i < children.size() - 1) {
                    sibling = children.at(i+1);
                    break;
                }
            }
        }
        if (!sibling) {
            lastTwoColorTrianglesCommand->setForceFlush(true);
        } else {
            SkeletonRenderer* siblingSkeleton = dynamic_cast<SkeletonRenderer*>(sibling);
            if (!siblingSkeleton || // flush is next sibling isn't a SkeletonRenderer
                !siblingSkeleton->isTwoColorTint() || // flush if next sibling isn't two color tinted
                !siblingSkeleton->isVisible() || // flush if next sibling is two color tinted but not visible
                (siblingSkeleton->getGlobalZOrder() != this->getGlobalZOrder())) { // flush if next sibling is two color tinted but z-order differs
                lastTwoColorTrianglesCommand->setForceFlush(true);
            }
        }
    }
}

if (_effect) _effect->end(_effect);

if (_debugSlots || _debugBones || _debugMeshes) {
    drawDebug(renderer, transform, transformFlags);
}

}