【教你一招】编辑器启动时自动贴靠插件到内部

教你一招

Cocoscreator插件在编辑器启动时,如何自动加载并贴靠到编辑器内部?


Like This


1. package.json

配置package.json中panel的属性「popable->false」「type->‘dockable’」
{
  "panel": {
    //...
    "type": "dockable",
    "popable": false,
    "title": "太帅了名称显示异常",
    //...
  }
}

2. main.js

判断插件是否加载、打开插件、注入贴靠脚本
	load() {
	    //1.先判断扩展是否已经加载了
		if (this.isPackageInUsing()) {
			return;
		}
		let timer = setInterval(() => {
		    //2.等找到主窗口的时候,开始加载任务
			if (Editor.Window && Editor.Window.main && Editor.Window.main.nativeWin) {
				Editor.Window.main.nativeWin.__main__ = true;
				let webContents = Editor.Window.main.nativeWin.webContents;
				if (webContents) {
					clearInterval(timer)
					//3.打开自己的插件
					Editor.Panel.open('my-package')
					let windows = electron.BrowserWindow.getAllWindows();
					windows.forEach((win) => {
						if (!win.__main__) {
						    //4. 打开插件的同时,先隐藏掉插件,不然会很尬
							win.hide()
						}
					});
				    //5.重点来了,由于贴靠插件需要在renderer进程,所以开始注入脚本,脚本内容「template-auto-dock.js」
				    webContents.executeJavaScript(fs.readFileSync(path.join(__dirname, 'template-auto-dock.js'), 'utf-8'));
				}
			}
		}, 1000 / 30);
	},
	
	/**
	* 判断扩展是否已经加载了,方法是,读取local://layout.editor.json
	* 然后判断文件内是否有自己的插件名
	**/
	isPackageInUsing() {

		let localProfile = Editor.Profile.load("local://layout.editor.json");
		if (!localProfile) {
			return false;
		}

		function getLocalPath() {
			let result;
			localProfile._chain.map((item) => {
				if (item && item.type === 'local') {
					result = item.path;
				}
			})
			return result;
		}

		let fs = require('fire-fs');
		let path = require('path')
		let localPath = getLocalPath();
		let fileName = localProfile._file;
		let wholePath = path.join(localPath, fileName)
		let has = fs.existsSync(wholePath)
		let content;
		if (!has) {
			return false
		} else {
			content = fs.readFileSync(wholePath, 'utf-8');
		}
		try {
			let data = JSON.parse(content);
			// 1.重点就是这一句
			if (!(data && data.windows && data.windows.main && data.windows.main.panels && data.windows.main.panels.indexOf('my-package') != -1)) {
				return false
			} else {
				return true;
			}
		} catch (error) {}
	},

3. template-auto-dock.js

贴靠插件到creator编辑器内的脚本,其中第3处注释是重点
(function(){
    var timerLoadPackage = setInterval(() => {
        // 1.判断是否已经贴靠
        if (!window.__MY_PACKAGE_LOADED) {
            try {
                var dockUtil;
                var dropMgr;
                var panelMgr;
                var tabs;
                var package = 'my-package';
                
                // 2.从renderer内存中找到这几个贴靠插件需要用到的助手,下面这段代码是核心,看不明白的留言
                Object.keys(require.cache).map((file)=>{
                    if (/dock-utils\.js$|dock-utils\.ccc$/.test(file)) {
                        dockUtil = require(file);
                    }
                    if (/drag-drop\.js$|drag-drop\.ccc$/.test(file)) {
                        dropMgr = require(file);
                    }
                    if (/renderer\/panel\.js$|renderer\/panel\.ccc$|renderer\\panel\.js$|renderer\\panel\.ccc$/.test(file)) {
                        panelMgr = require(file);
                    }
                });
                [...document.getElementsByTagName('ui-dock-panel')].map((panel) => {
                    if (/inspector/.test(panel.innerHTML)) {
                        tabs = panel.$tabs;
                    }
                })
                
                if (dockUtil && tabs && panelMgr) {
                    panelMgr.close = (function(orgFunc){
                        return function(...args){
                            if ([...args][0] == package) {
                                let callback = [...args][1];
                                return orgFunc([...args][0], (error, others)=>{
                                    callback(null, others)
                                }); 
                            }
                            return orgFunc(...args);
                        }
                    })(panelMgr.close);
                    dropMgr.items = (function(orgFunc){
                        return function(...args){
                            let result = window.__specified_panel ? [window.__specified_panel] : orgFunc(...args)
                            return result;
                        }
                    })(dropMgr.items);
                
                
                    window.__specified_panel = {
                        panelID: package,
                        panelPreferredHeight: 0,
                        panelPreferredWidth: 0,
                        panelRectHeight: 0,
                        panelRectWidth: 0
                    };
                    
                    //3.贴靠插件,上文所有代码,都是为这句服务的
                    dockUtil.dropTab(tabs)
                    window.__specified_panel = null;
                    //4.可选,让自己的插件失去焦点,可以让用户无感知地加载
                    panelMgr.focus('inspector');
                    Editor.Selection.select("node");
                }
            } catch (error) {
                console.log(error)
            }
        } else {
            clearInterval(timerLoadPackage)
        }
    }, 1000 / 30);
})()
5赞

感谢分享!

写插件时,全局变量『window.xxx』总是莫名其妙地丢失怎么办?

	(function (){
		let cache = Object.keys(require.cache);
		cache.map((dir) => {
			if (/sandbox\.js$|sandbox\.ccc$/.test(dir)) {
				let sandbox = require(dir)
				if (sandbox) {
					for(var key in sandbox) {
						let item = sandbox[key]
						if (item && typeof item === 'object' && item.restore
                            // 防止被sandbox回滚
							item.restore = ()=>{}
						}
					}
				}
			}
		})
	})();
1赞

不戳不戳.

mark~,你有编辑器源码吧?发我一份呗

额,你发我微信, 我加你

我想知道有多帅,才显示不出来

cool

太帅了,这根本不可能有任何编辑器能显示出来

这年头 说实话的人已经不多了

刚注意到置顶帖子,大家快来给我提个插件需求吧!我想搞,不知道做什么

template-auto-dock.js是自己创建的文件吗,放在项目哪个位置?

main.js同级

是自己创建的

好快,感谢大佬

:+1: 有点难理解,看个大概,是不是用脚本模拟了用户的手动操作?

明白人 :smile: