[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 2

接着昨天的文章,今天开始尝试很简单的交互。

简单来说:

前端是 Creator 编辑器框架

中间是 Creator 插件框架

后端是 Cocos2d-js 框架

现在需要的,是从后端到前端,从前端到后端的事件监听和数据传输。

同样这篇文章不是教程,今天的文章更应该说是 尝试摸索推理 的过程。


老样子,我还是习惯先挑个简单的需求来实现:

用户在 前端 场景编辑器中创建一个节点

用户挂载Sprite控件

此时 后端 获取到这个信息

cocos2d-js 的世界中,同样的也创建一个 cc.Sprite

反过来,我移动 cocos2d-js 的世界中的 cc.Sprite,场景编辑器中的节点也随之移动

尝试

需求有了,可以开干了,首先第一步,自然是前端创建节点的时候,插件需要能够感知到。

一试

第一个想法,自然是监听事件,于是看文档,没有,或者说我没找到。

扩展编辑器

然后开始搜索论坛,找到了一篇人气很高的文章:

《creator插件开发常用API命令列表》备忘录

通过翻阅一些文章,这里的一些 IPC 事件,有的是用来被动接收的,有的则是给用户主动调用的。

这里我需要的,自然是被动接收消息。

通过翻阅论坛的一些帖子,可以知道,我所要的消息应该是和 scene node 相关的。

于是可以找到:

scene:center-nodes
scene:change-node-lock
scene:copy-nodes
scene:create-node-by-classid
scene:create-node-by-prefab
scene:create-nodes-by-uuids
scene:delete-nodes
scene:duplicate-nodes
scene:move-nodes
scene:node-component-added
scene:node-component-removed
scene:node-component-updated
scene:paste-nodes
scene:query-node
scene:query-node-functions
scene:query-node-info
scene:query-nodes-by-comp-name
scene:reset-node

线索就这些了,那就先挑个比较明显的试试,我先选择了 scene:move-nodes,推理一下,这个应该是场景中的节点被移动的时候,可以收到的消息。

// index.js
'scene:move-nodes' (event, target) {
    Editor.log('scene:move-nodes');
}
// main.js
'scene:move-nodes' (event, target) {
    Editor.log('scene:move-nodes');
}

如上的两个地方都尝试过了,无论是 场景编辑器 中移动节点,还是 资源管理器 中移动节点,还是 资源管理器 中移动节点,都无法收到这个消息。

二试

个人习惯,首先是怀疑自己用的不对,于是又挑了个别的消息尝试一下 scene:node-component-added

// index.js
'scene:node-component-added' (event, target) {
    Editor.log('scene:node-component-added');
},
// main.js
'scene:move-nodes' (event, target) {
    Editor.log('scene:move-nodes');
}

这次非常顺利,场景编辑器中的节点,在随意添加一个组件后,两个监听处,都收到了回调。

看来使用方式应该是没有错。

三试

没办法,只能暂时先不管 scene:move-nodes,从上文的 API 列表 的命名习惯,直猜一波我要的消息了:

scene:create-node
scene:node-create
scene:add-node
scene:node-add

结果是,一个都没中

四试

没办法,那就只能靠着打印,来看看有什么线索了。要打印的自然是:

console.log(window.Editor);

输出内容很丰富:

但是通过寻找,并没有发现想要的,IPC 消息列表,比如说枚举之类的。

五试

既然等被动调用等不到,那就只能试试主动调用了。

一种想法是在 update 中进行主动的轮询,但这种做法实在是不好。

换一种想法,既然是做插件,通常使用的时候,可以让用户在需要享受插件提供的功能时,给节点挂上特定的脚本,比如说,挂上一个 test 脚本。

// test.js
cc.Class({
    extends: cc.Component,
    properties: {},
    editor: CC_EDITOR && { executeInEditMode: true },
    onLoad () {
        if (CC_EDITOR) {
            Editor.Ipc.sendToPanel('test-plugin', 'test-plugin:node-create');
        }
    },
});

简单的试了下,新建一个节点,然后挂载这个自定义脚本,果然,插件也就是中间部分成功的收到了消息。

那么,从中间像后端发送消息,就简单多了,毕竟 cocos2dx 已经入侵了,所以用老一套方法就行了:

cc.eventManager.dispatchCustomEvent("create-node");

这样,后端就可以在前端的节点挂载我们插件对应的脚本的时候,收到消息了:

// game.js
cc.eventManager.addCustomListener("create-node", function (event) {
    cc.log("cocos2dx:create-node");
});

实际尝试也顺利的成功了。

总结

虽然不是很直接的,监听 场景编辑器 中节点创建的消息(实在不知道怎么弄),但是也算是实现了类似的效果。

达到了初步的,交互,当然离想要的效果还差那么一点,还需要继续加油。


吐槽

这是趟坑后对 Creator 插件系统的吐槽,肯定不是无脑黑,毕竟本人是绝对的 cocos 忠实用户。

  1. 真的是玄学
  2. 这么多年了,文档还是不完整,1.4 的时候我就简单研究过,现在看的文档和当年差不了多少
  3. 论坛搜到的解决方案不一定有用,因为版本不同,API 也不稳
  4. 2D3D 也不同,虽然还未深入,但至少 2D 的无法直接在 3D 使用,同样 API 不稳
  5. 接上,很担心现在如果做出了支持 2D 3D 的插件,年底的 2D3D v3,是不是又要重写
  6. )(&%$@!!@$%%^^&&**(()))
  7. 果然是玄学

上面自然都是缺点,优点当然也是有的,我觉得最大的一条,就是 真的很锻炼人,如何在缺少文档,缺少教程,缺人可问的环境下,自己去想办法实现目标,对于技能升级而言,是很好的训练。

3赞

大佬就是爱折腾
监听 场景编辑器 中节点创建的消息可以用这个
child-added 增加子节点监听事件,通过 this.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); 进行监听

谢谢回复,又学到了点新东西。
不过你说的这个,貌似应该是用在前端,也就是 creator 挂载的脚本中的吧
我想要的是,是在插件中监听一个消息,可以收到场景编辑器中所有新建节点时候的消息

都可以用,插件中可以获得场景所有节点对象并像在前端那样调用api