[就问你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. 2D 和 3D 也不同,虽然还未深入,但至少 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