native使用的是c++版本的DragonBones,js引擎则使用的是js版本的dragonBones
适配DragonBones native
dragonBones.ObjectDataParser
native并没有这个属性,所以这种修复方式只适合js平台,如果native也遇到相关的bug,需要修改c++
dragonBones.ObjectDataParser
slot.displayList
也只有js层有,native没有导出
const slotArray: dragonBones.Slot[] = armatureDisplay.armature().getSlots();
const frames = spAtlas.getSpriteFrames();
for (let i = 0; i < slotArray.length; i++) {
const slot = slotArray[i];
slot.displayList.forEach((display) => { // slot.displayList是数组类型
if (display instanceof dragonBones.Armature) {
if (display.name === armatureName) {
frames.forEach((item) => {
const s: any = display.getSlot(item.name); // display.getSlot也没有导出
if (s) {
s.setSpriteFrame(item);
} else {
cc.log(`can't find any slot use sprite frame: ${item.name}`);
}
});
}
}
})
}
查阅binding工具的python相关导出逻辑,尝试导出getDisplayList()
match的原因,会导致即使从skip中删除getDisplayList,仍旧无法导出,需要把getDisplay也从skip中删了,正常导出后,发现生成的代码并没有对类型转换做处理,所以仍旧无法正常使用,这也是存在manual的原因。
还需要另找
有些api是手动导出的
我明明定义的是function
__jsb_dragonBones_Slot_proto->defineFunction("getDisplayList", _SE(js_cocos2dx_dragonbones_Slot_getDisplayList));
为啥slot.displayList效果和它一样呢?
设置texture宽高
static bool js_gfx_Texture2D_init(se::State& s)
{
cocos2d::renderer::Texture2D* cobj = (cocos2d::renderer::Texture2D*)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "js_gfx_Texture2D_init : Invalid Native Object");
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
cocos2d::renderer::DeviceGraphics* arg0 = nullptr;
cocos2d::renderer::Texture::Options arg1; // js层传递过来的宽高
ok &= seval_to_native_ptr(args[0], &arg0);
ok &= seval_to_TextureOptions(args[1], &arg1);
SE_PRECONDITION2(ok, false, "js_gfx_Texture2D_init : Error processing arguments");
bool result = cobj->init(arg0, arg1);
ok &= boolean_to_seval(result, &s.rval());
SE_PRECONDITION2(ok, false, "js_gfx_Texture2D_init : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(js_gfx_Texture2D_init)
native龙骨的渲染
还是有点区别,触发渲染的逻辑堆栈
void ModelBatcher::commitIA(NodeProxy* node, CustomAssembler* assembler, int cullingMask)
{
auto customIA = assembler->getIA(0);
_ia.setVertexBuffer(customIA->getVertexBuffer());
_ia.setIndexBuffer(customIA->getIndexBuffer());
_ia.setStart(customIA->getStart());
_ia.setCount(0);
}
追到了设置customIA的buffer的逻辑,有一个非常相似的逻辑traverseArmature
void CCArmatureDisplay::traverseArmature(Armature* armature, float parentOpacity)
{
middleware::MeshBuffer* mb = mgr->getMeshBuffer(VF_XYUVC);
IOBuffer& vb = mb->getVB();
IOBuffer& ib = mb->getIB();
// 中间省略了很多的代码
for (std::size_t i = 0, len = slots.size(); i < len; i++)
{
slot = (CCSlot*)slots[i];
texture = slot->getTexture();// 换肤其实hack这个逻辑即可,给slot增加一个设置纹理的接口
middleware::V2F_T2F_C4B* worldTriangles = slot->worldVerts;
for (int v = 0, w = 0, vn = triangles.vertCount; v < vn; ++v, w += 2)
{
// 都是在计算更新x、y,需要知道更新uv的位置
middleware::V2F_T2F_C4B* vertex = triangles.verts + v;
middleware::V2F_T2F_C4B* worldVertex = worldTriangles + v;
worldVertex->vertex.x = vertex->vertex.x * worldMatrix->m[0] + vertex->vertex.y * worldMatrix->m[4] + worldMatrix->m[12];
worldVertex->vertex.y = vertex->vertex.x * worldMatrix->m[1] + vertex->vertex.y * worldMatrix->m[5] + worldMatrix->m[13];
worldVertex->color.r = (GLubyte)r;
worldVertex->color.g = (GLubyte)g;
worldVertex->color.b = (GLubyte)b;
worldVertex->color.a = (GLubyte)a;
}
middleware::V2F_T2F_C4B* worldTriangles = slot->worldVerts;
auto vertexOffset = vb.getCurPos() / sizeof(middleware::V2F_T2F_C4B);
vb.writeBytes((char*)worldTriangles, vbSize); // 写入vertexBuffer
}
}
更新slot->worldVerts的地方在slot._updateFrame,接下来其实就是将_updateFrame的部分逻辑迁移到我自己写的setSpriteFrame
龙骨的节点在设置Assembler setAssembler
jsb-adapter/jsb-engine.js有在修改Assembler
构建jsb-engine.js和CC_NATIVERENDERER有关系
armatureDisplayProto
这个工程是用来生成适配jsb的,对应的仓库: github.com/cocos-creat…
感觉和jsb-dragonbones.js有关系,最后发现和这个关联不是很大