提一个2.4.2spine引用外部图片换装方案

#引擎版本 2.4.2 ###
##新项目可能用到spine下载远端纹理然后换装:mag:了下论坛并没有能用于生产环境的帖子,那就自己造轮子咯:smile:
###感谢 帖子 里面提供换装的思路
##需要的知识点:2.0JSB自动绑定
#修改步骤
1.先了解:point_right:帖子里面关于换装的代码逻辑。(ps:web上已经可以使用了,原生上需要hack一下。)
2.修改c++ 源码
2.1在SkeletonRenderer类增加函数loadTextureForSpine(函数实现: 帖子已经有了)
2.2在SkeletonCacheAnimation类中同上操作。()
SkeletonRenderer 对应spine realTime模式; SkeletonCacheAnimation对应另外2个模式。

3.通过工具 /Resources/cocos2d-x/tools/tojs/genbindings.py 生成中间的侨联文件 (ps:需要一些工具 具体参考 /Resources/cocos2d-x/tools/bindings-generator/README.md )
4. 生成文件后,编辑模拟器便于调试:打开工程/Resources/cocos2d-x/tools/simulator/frameworks/runtime-src/proj.ios_mac/simulator.xcodeproj 编译模拟器即可(ps:这是mac工程 window找对应的工程)

#js 使用方式

var path = 远端图片url地址;
cc.assetManager.loadRemote(path,cc.Texture2D,function (err,texture) {
    if (cc.sys.isNative) {
        var medTex = new middleware.Texture2D();
        medTex.setRealTextureIndex(0);//参数随便设置的没怎么研究
        medTex.setPixelsHigh(texture.height);
        medTex.setPixelsWide(texture.width);
        medTex.setNativeTexture(texture.getImpl());
        spineComp._nativeSkeleton.loadTextureForSpine(slotName,medTex);
    }else {
        //web不赘述了
    }
})

##到这一步,如果不出错在模拟器上已实现换装了
##是不是觉得已经完事?太native了。
#解决下一个问题:缓存问题。
##认真测试一下,其实可以发现如果共用一个sp.SkeletonData,其中一个实例换装了,其他实例也换装了。
###这里提供一个解决思路
####通过运行时复制指定sp.SkeletonData数据来避免缓存问题

    var spdata = spineComp.skeletonData;//spineComp某个sp.Skeleton组件
    var copy = new sp.SkeletonData()//拷贝一份纹理,避免重复纹理缓存
    cc.js.mixin(copy,spdata)
    copy._uuid = spdata._uuid+"_"+Date.newDate().getTime()+"_copy";//增加一个时间戳 读取到毫秒应该不会重复吧?
    var old = copy.name;
    var newName = copy.name+'_copy'
    copy.name = newName;
    copy.atlasText = copy.atlasText.replace(old,newName)
    copy.textureNames[0] = newName+'.png'
    copy.init && copy.init()
    spineComp.skeletonData = copy;//重新设置一下数据

##现在换装应该ok了。
#Ps:存在的问题:毕竟只是demo测试代码,没有测试过,释放复制出来的资源释是否需要对资源计数+1。

7赞

论坛都多少人折腾好久了,不知道是不是因为有难度官方一直不能提供一个可行安全都方案,官方目前都那个换装就是玩具,压根不适合实际开发用。

3赞

其实官方只要把挂点层级问题解决了,基本上就好了

3赞

mark~~~~

谢谢反馈,我们有空看看

cc.js.mixin 深拷贝 get了
之前是先拷贝一个skelentData 然后更换runtimeData的skin里面的RegionAttachment里面的region
明显这个简洁

我现在的项目就是先尝试了使用图片换装,但效果不太好,并且不同武器握持位置不一样,还得加配置来调整。最终还是使用了spine到spine的换装方案。希望官方尽早提供图片换装接口。

兄弟,有没方法不改引擎文件就实现native外部图片换装的功能?:sweat_smile:

不改引擎就要实现的,等官方更新吧

我们是做成使用裸膜+套装的方式,同一套骨骼,写工具把套装拆分成独立的spine文件。

不修改引擎的话,换装可以使用 sp.SkeletonDatatextures, textureNames , atlasText 这几个属性来实现

问题主要出在这几个地方

Cocos Creator 默认的使用方式只支持骨骼上用到的所有图片都打成一个图集,和导出的 json 一起加载进来才能生成一个 sp.SkeletonData 实例。
最终 spine 运行时代码里面是解析 atlasText 得到一系列的 pagesregions ,解析骨骼对应的 json 文件得到所有的皮肤以及附件信息后再通过 AtlasAttachmentLoader#findRegion 去找到对应的 region,然后生成 attachment。每个 page 需要提前准备好对应的 texture , 将 texturename 放在 texturestextureNames 上。如果对应的 texture 不存在,则对应的 attachment 都不会生成。到了这里,问题就简单了,把你想要渲染的附件的图片都加载出来,自己生成对应的 atlasText,然后赋值 texturestextureNames 属性就可以解决第一个问题。

web 端的 sp.spine 里面基本上都是 spine 官方 js 运行时的代码,而在 native 上则是通过 jsb暴露给 js 的接口,这些接口是在 spine下的,在 jsb-adapters 里面赋给了 sp.spine 所以两边会有 api 上的不一致,会造成比如 sp.spine.TextureAtlas is not a constructor 的问题。所以有些 api 不能用

最终加载出来的 SkeletonData 会根据 _uuidc++ 里面缓存,同一个骨骼文件加载出来的 SkeletonData 是同一个实例,没有 _uuid 属性的会报错,楼主已经写了解决办法

2赞

哎,不能设置挂点的层级吗? 只能在最上层?

哎,不能设置挂点的层级吗? 只能在最上层?
有什么办法让挂点显示在整体的后面?

经过实测,只能更换大小相同的图片,否则大小显示不对,比如原始图100 100,替换为200 200的图片,结果图片会自动缩放到100*100大小,这样基本上没法用了,不知道怎么才能正确显示替换后的图片大小。

可以分享下方案代码嘛