spine是否可以用外部图片进行换皮

Mark一下

支持插槽替换个外部的spine动画上去吗?

mark~~

native的MeshAttachment无法更换有排查建议吗,RegionAttachment的可以,也没报错之类,不知道怎么看

同求,这个问题不解决,很多地方也用不成

3.x 版本的局部换装的 native上更换 MeshAttachment 方案,(目前)需要定制引擎

在 3.4.0以上版本,合并以下PR

  • 修改 engine cocos/spine/skeleton.ts 文件
    platforms/native/engine/jsb-spine-skeleton.js 文件
  • 修改 engine-native
    cocos/editor-support/spine-creator-support/SkeletonRenderer.cpp
    cocos/editor-support/spine-creator-support/SkeletonRenderer.h
    cocos/editor-support/spine/Attachment.cpp
    cocos/editor-support/spine/Attachment.h
    cocos/editor-support/spine/MeshAttachment.cpp
    cocos/editor-support/spine/RegionAttachment.cpp
    tools/tojs/spine.ini

备注

  1. 修改engine后,记得在编辑器顶部菜单栏点击编译引擎
  2. 修改engine-native后,记得运行 engine-native\tools\tojs目录下的genbindings.py脚本,重新生成绑定
  3. 用户脚本上,直接调用 changeSlotSkin(slotName, tex2d)函数完成换肤
3赞

mark~

https://note.youdao.com/s/P4bOPqRw 这是我有道笔记的总结

2赞

请问这些pr会被添加到之后的哪个新版本?

如果用了自动图集的话可以用下面的方法 v2.4.8可用

/**
 * 获取spine运行时图片数据
 */
private loadRegion(frame:cc.SpriteFrame):sp.spine.TextureAtlasRegion{
    let texture=frame.getTexture()

    let skeletonTexture = new sp.SkeletonTexture()
    skeletonTexture.setRealTexture(texture)

    let page = new sp.spine.TextureAtlasPage()
    page.texture = skeletonTexture
    page.name = texture.name
    page.uWrap = sp.spine.TextureWrap.ClampToEdge
    page.vWrap = sp.spine.TextureWrap.ClampToEdge
    page.texture = skeletonTexture
    page.texture.setWraps(page.uWrap, page.vWrap)
    page.width = texture.width
    page.height = texture.height

    let region = new sp.spine.TextureAtlasRegion()
    region.page = page

    let size=frame.getOriginalSize()
    region.width = size.width
    region.height = size.height
    region.originalWidth = size.width
    region.originalHeight = size.height

    region.u = frame["uv"][0]
    region.v = frame["uv"][7]
    region.u2 = frame["uv"][6]
    region.v2 = frame["uv"][1]

    region.texture = skeletonTexture
    return region
}

原生打包这个方案直接寄了。。。

spine换装,mark一个~

原生不能这么干要另外做处理
if (JSB) {

        // @ts-ignore

        let skeleton = cc.internal.SpineSkeleton.prototype;

        // @ts-ignore

        let spineSkeletonData = cc.internal.SpineSkeletonData.prototype;

        // 局部换装

        skeleton.updateRegion = function (attachment: any, tex2d: any) {

            // @ts-ignore

            var jsbTex2d = new middleware.Texture2D();

            jsbTex2d.setRealTextureIndex(spineSkeletonData.recordTexture(tex2d));

            jsbTex2d.setPixelsWide(tex2d.width);

            jsbTex2d.setPixelsHigh(tex2d.height);

            // @ts-ignore

            sp.spine.updateRegion(attachment, jsbTex2d);

        }

    }

十分感谢,我最后还是用了官方的方案,新建了一个全部是武器的spine文件来替换使用了。。。

赞,有用。

1赞

mark~~

请问怎么用呢

在其他帖子找到的答案,用这个转一下 var medTex = new middleware.Texture2D();
medTex.setRealTextureIndex(0);//参数随便设置的没怎么研究
medTex.setPixelsHigh(texture.height);
medTex.setPixelsWide(texture.width);
medTex.setNativeTexture(texture.getImpl());

            skeleton._nativeSkeleton.loadTextureForSpine(regionName, medTex);

大佬,如果是MeshAttachment类型要怎么改

贴一下支持mesh的,测试过了没啥问题
void SkeletonRenderer::loadTextureForSpine(const std::string& slotName, cocos2d::middleware::Texture2D* texture)
{
if (!texture || slotName.empty()) {
CCLOG(“Error: Invalid texture or slot name”);
return;
}

Slot *slot = _skeleton->findSlot(slotName.c_str());
if (!slot) {
    CCLOG("Error: Slot '%s' not found", slotName.c_str()); 
    return;
}

Attachment* attachment = slot->getAttachment();
if (!attachment) {
    CCLOG("Error: No attachment found for slot '%s'", slotName.c_str());
    return;
}

Texture* texture2D = texture->getNativeTexture();
float width = texture2D->getWidth();
float height = texture2D->getHeight();

float wide = texture->getPixelsWide();
float high = texture->getPixelsHigh();
texture->setPixelsWide(width);
texture->setPixelsHigh(height);
texture->setRealTextureIndex(1);

// 处理RegionAttachment
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
    RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
    AttachmentVertices *attachV = (AttachmentVertices *)regionAttachment->getRendererObject();
    if (attachV->_texture == texture) return;
    
    CC_SAFE_RELEASE(attachV->_texture);
    attachV->_texture = texture;
    CC_SAFE_RETAIN(texture);
    
    // 设置UV和尺寸信息
    regionAttachment->setUVs(0, 0, 1, 1, false);
    regionAttachment->setWidth(wide);
    regionAttachment->setHeight(high);
    regionAttachment->setRegionWidth(wide);
    regionAttachment->setRegionHeight(high);
    regionAttachment->setRegionOriginalWidth(wide);
    regionAttachment->setRegionOriginalHeight(high);
    regionAttachment->setRegionOffsetX(0);
    regionAttachment->setRegionOffsetY(15);
    
    // 更新顶点UV坐标
    V2F_T2F_C4B* vertices = attachV->_triangles->verts;
    auto& uvsVector = regionAttachment->getUVs();
    for (int i = 0, ii = 0; i < 4; ++i, ii += 2) {
        vertices[i].texCoord.u = uvsVector[ii];
        vertices[i].texCoord.v = uvsVector[ii+1];
    }
    
    // 更新偏移量
    regionAttachment->updateOffset();
    
    // 强制更新骨架变换
    _skeleton->updateWorldTransform();
}
// 处理MeshAttachment - 正确实现换皮功能
    else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
        MeshAttachment* meshAttachment = (MeshAttachment*)attachment;
        AttachmentVertices *attachV = (AttachmentVertices *)meshAttachment->getRendererObject();
        if (attachV->_texture == texture) return;
        
        CC_SAFE_RELEASE(attachV->_texture);
        attachV->_texture = texture;
        CC_SAFE_RETAIN(texture);
        
        // 关键步骤1: 设置MeshAttachment的区域参数,使其使用整个新纹理
        meshAttachment->setRegionU(0);
        meshAttachment->setRegionV(0);
        meshAttachment->setRegionU2(1);
        meshAttachment->setRegionV2(1);
        meshAttachment->setRegionWidth(wide);
        meshAttachment->setRegionHeight(high);
        meshAttachment->setRegionOriginalWidth(wide);
        meshAttachment->setRegionOriginalHeight(high);
        meshAttachment->setRegionOffsetX(0);
        meshAttachment->setRegionOffsetY(0);
        meshAttachment->setRegionRotate(false);
        meshAttachment->setRegionDegrees(0);
        
        // 关键步骤2: 调用updateUVs()方法重新计算UV坐标
        meshAttachment->updateUVs();
        
        // 关键步骤3: 将重新计算的UV坐标应用到渲染顶点
        if (attachV->_triangles && attachV->_triangles->verts) {
            V2F_T2F_C4B* vertices = attachV->_triangles->verts;
            auto& uvsVector = meshAttachment->getUVs();
            int vertexCount = meshAttachment->getWorldVerticesLength() / 2;
            
            // 确保顶点数量不超过实际可用顶点数
            int actualVertexCount = (vertexCount < (int)(uvsVector.size() / 2)) ? vertexCount : (int)(uvsVector.size() / 2);
            
            for (int i = 0; i < actualVertexCount; i++) {
                // 直接使用updateUVs()计算后的UV坐标
                vertices[i].texCoord.u = uvsVector[i * 2];
                vertices[i].texCoord.v = uvsVector[i * 2 + 1];
            }
        }
        
        // 关键步骤4: 更新骨架变换,确保渲染正确
        _skeleton->updateWorldTransform();
    }
else {
    CCLOG("Warning: Unsupported attachment type for slot '%s'", slotName.c_str());
    return;
}

CCLOG("Texture loaded successfully for slot '%s'", slotName.c_str());

}

1赞