egret-pro编辑器分析

287 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

egeret已经倒闭了,想看下egret-pro编辑器,现在只能通过第三方的备份进行下载了。

image.png

相关环境的版本信息:

场景窗口是一个单独的窗口

image.png

在编辑器安装目录发现了熟悉的目录结构

image.png

开发过electron应用的话,肯定对resources目录非常熟悉,还好egret-pro并没有对编辑器代码加密,仅仅是通过webpack进行了压缩混淆,顺着package.json一路就能找到入口

image.png

image.png

resources/app/out/main/Main.js中找到打开项目创建BrowserWindow的地方,加上打开devtools的逻辑

this.projectWindow = new electron_1.BrowserWindow(windowOption);
this.projectWindow.webContents.openDevTools();

这样打开项目后,就能看到编辑器的devtool

image.png

随后发现,这个场景窗口是无法拾取到,那么这个场景窗口是怎么回事呢?

image.png

先将其他窗口都关闭,只剩场景窗口:

image.png 尝试将div依次都display:none,发现当场景窗口消失不见的时候,我们会看到

image.png 这就更加说明这个场景窗口是一个window,覆盖在egret-pro上

image.png 通过Spy++并没有得到我们想要的答案,看来又只能看源码了

突破口

var electron=require("electron")
var rect={x:0,y:0,width:100,height:100};
electron.ipcRenderer.send("scenepanel:resize", rect);
electron_1.ipcMain.addListener("scenepanel:resize", function (evt) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    var rect = args[0];
    console.log(`x:${rect.x}, y:${rect.y}, width:${rect.width}, height:${rect.height}`);
    var view = _this.projectWindow.getBrowserView();
    if (view !== null && rect) {
        view.setBounds(rect);
    }
});

发现尝试着移动到窗口外边,还是无法突破主窗口的限制,应该还不是一个window,仍旧是一个dom,但是为啥找不到这个dom呢?

image.png

image.png

一个实验性的api:调整大小并且移动view到相对于window的指定区域。

image.png

electron_1.ipcMain.addListener("scene:createbrowserview", function (evt) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    // BrowserView加载的url 
    var baseUrl = "http://localhost:3000/editor.html?player-mode=4&content-width=2048&content-height=1024&";
    var url = baseUrl + "projectPath=" + args[0] + "&projectTmpPath=" + args[1] + "&rootPath=" + args[2] + "&userPath=" + args[3];
    var options = {
        webPreferences: { preload: path.join(args[2], "./out/runtime/runtime.js") }
    };
    if (_this.runtimeView) {
        _this.runtimeView.webContents.closeDevTools();
        // TODO:destory会导致crash bug
        //ref:https://github.com/electron/electron/issues/19921#event-2776839618;
        //ref:https://github.com/electron/electron/issues/21410
        // this.runtimeView.destroy();
        // this.runtimeView = null;
    }
    //如果每次都使用同一个browserview,刷新编辑器渲染进程主进程会出现uncaughterror.
    //如果每次都创建一个新的browserview且不destory,会导致browserview无法回收,同时rpc重复发送多次reconnect消息,进一步导致编辑器无法正常通讯。
    //如果每次都创建一个新的browserview且destory,上条问题解决,但编辑器resize的时候会crash.
    //升级electron至v8.1.1,依然未修正这些问题,目前采用方式1.
    if (!_this.runtimeView) {
        _this.runtimeView = new electron_1.BrowserView(options);
    }
    var rect = args[4];
    if (rect) {
        _this.runtimeView.setBounds(rect);
    }
    // 最终BrowserVIew还是需要加载一个URL
    _this.runtimeView.webContents.loadURL(url);
    UserSetting_1.UserSetting.openDevtools && _this.runtimeView.webContents.openDevTools({ mode: "detach" });
    _this.projectWindow.setBrowserView(_this.runtimeView);
});

很显然这个是一个BrowserView,我们用浏览器打开后可以看到真正的面貌

image.png

感觉是为了做engine环境的隔离,cocos creator是将canvas内嵌在iframe里面了

可能会遇到无法打开的问题

http://tool.egret-labs.org/EgretPro/engine/proupdate.json?v=0.29059651250877794

image.png 可以改下host

image.png