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

接着昨天的文章,记录一下昨天做的东西。

要说明下,这不是一篇教程,因为很多东西我也不懂,就像论坛大部分认为的,做插件就是 玄学,你得像侦探一样去寻找线索,去推理,最后找到真相,这是一件蛋疼的事,但是对于提升学习能力来说,那是很好的锻炼。

入侵

这里主要记录一下,如何在 Creator 插件系统中,将 Cocos2d-x 的游戏(当然是 js HTML5 的 )集成进来。

首先是 cocos2-js 的启动原理,很简单,页面中主要就是一个 canvas,然后游戏就在上面被渲染,执行。

<body>
<div id="gameCanvasWrapper">
    <canvas id="gameCanvas"></canvas>
</div>
<script src="game.min.js"></script>
</body>

因此想法很简单,只要在 Creator 的插件运行起来后,创建一个 Canvas ,然后在上面渲染游戏就可以了。

于是我就照着教程创建了一个 test-plugin 项目,然后查看了一下实际运行时,插件的 DOM 结构:

<ui-main-dock class="fit">
    <ui-dock-panel style="...">
        <ui-panel-frame class="fit" id="test-plugin" style="...">
        </ui-panel-frame>
    </ui-dock-panel>
</ui-main-dock>

可以看到,我的插件 test-plugin 所对应的最内部的容器应该就是 ui-panel-frame 了,那么做个手术,把

<canvas id="gameCanvas"></canvas> 移植过去,应该就可以了。

先要修改一下 cocos2d-js 的源码,frameworks/cocos2d-html5/CCBoot.js:initRenderer,原先的 Canvas 是这样获取的:

element = cc.$(el) || cc.$('#' + el)

那么在 Creator中就应该是:

element = document.getElementById("gameCanvas")

但是实际运行却发现,这样获取到的 element == null,通过查看 DOM 树,

可以发现,里面包含了 shadow-root 的东西,网上查了写文章,还没有细看:

想了解Shadow DOM?看这里

[神秘的 shadow-dom 浅析](https://www.cnblogs.com/coco1s/p/5711795.html)

先试试能不能搞定:

element = document.getElementById("test-plugin").shadowRoot.getElementById("gameCanvas")

果然和想的一样,这样就可以正确的获取到 Canvas 了,那么自然 cocos2d-js 的内容也就成功的被渲染出来了。

上面的修改是针对 Creator2D 的,同样的修改方式在 Creator3D 中没有效果,实际运行可以看到,两边的 DOM 树结构是不同的:

所以调整一下代码:

element = document.getElementById("dock").shadowRoot.querySelector("panel-frame").shadowRoot.getElementById("gameCanvas");

当然也许还有更简单的方法,因为我暂时没有研究 Shadow DOM ,所以只是先寻找一种可以实现的方案。

笔记

效果达到了,顺便记录一些笔记,和问题。

  1. 自己写的脚本,引用要写 Editor.require(......js)
  2. 读文件可以 Fs.readFileSync(Editor.url('packages://test-plugin/...'), 'utf-8'),
  3. 插件项目路径 Editor.Project.path 可以获取到
  4. 3D 注册菜单栏,文档中提到了 contributions.menu,但是我怎么试都没效果,啥都不出来
  5. 3D 中,没了 Editor.log
  6. 3D 的控件语法和 2D 有差别,是无法直接把 2D 的代码拿来用的
  7. 3D 中有个 __dirname 似乎是和 2DEditor.Project.path 等价的

对我这种现在还在起手 var 的人来说,学写插件可以慢慢的让自己学习并使用 vscode, ts, es6, vue ,是一件很好事情。入侵以后,接下来就要想办法实现内外的交互了。

6赞

大佬又来更新啦 要成系列啦

3D 中注册菜单我是酱紫弄的:

{
  "contributions": {
    "menu": [
      {
         "path": "i18n:menu.extension/test",
         "label": "open",
         "message": "open"
      },
      {
         "path": "i18n:menu.extension/test",
         "label": "settings",
         "message": "settings"
      },
      {
         "path": "i18n:menu.extension/test/extra",
         "label": "test",
         "message": "test"
      }
    ],
    "messages": {
        "open": {
            "public": true,
            "methods": [ "open" ]
        },
        "settings": {
            "public": false,
            "methods": [ "settings" ]
        },
        "test": {
            "public": false,
            "methods": [ "test" ]
        }
     },
  }
}

3D 里 Editor.log 没有了,直接用 console.log 就可以打印

谢谢回复,有空我试一下 :grin:

太感谢了,帮我解决了个大问题