123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- * @Author: CGT (caogtaa@gmail.com)
- * @Date: 2020-01-16 22:09:08
- * @Last Modified by: CGT (caogtaa@gmail.com)
- * @Last Modified time: 2020-01-16 23:46:33
- */
- 'use strict';
- let _menuTemplateCache = null;
- let _paramCache = {};
- function createNode(uuid) {
- let param = {uuid: uuid};
- Object.assign(param, _paramCache);
- Editor.Scene.callSceneScript('cc-ext-scene-menu', 'create-node', param, (err) => {
- if (err)
- Editor.log(err);
- });
- }
- function sendCommand(command, param) {
- let p = {};
- Object.assign(p, _paramCache);
- p.customParam = param;
- Editor.Ipc.sendToMain(command, p, null);
- }
- function generateMenuTemplate(conf) {
- let result = [];
- for (let c of conf) {
- // https://electronjs.org/docs/api/menu
- let item = {};
- item.label = c.name;
- // item.click = createNode.bind(c.uuid);
- // the menu item auto unbound my function, why?
- // so I put uuid in closure
- if (c.type == 0) {
- // prefab
- let uuid = c.uuid;
- item.click = () => {
- createNode(uuid);
- };
- } else if (c.type == 1) {
- // command
- item.click = () => {
- sendCommand(c.command, c.param);
- };
- } else if (c.submenu) {
- item.submenu = generateMenuTemplate(c.submenu);
- } else {
- // unexpected
- }
- result.push(item);
- }
- return result;
- }
- function loadMenu() {
- const fs = require('fs');
- let configPath = Editor.Project.path + '/scene-menu-config.json';
- if (!fs.existsSync(configPath)) {
- // read default config
- configPath = Editor.url('packages://cc-ext-scene-menu/default-config.json');
- }
- fs.readFile(configPath, function (err, data) {
- if (err) {
- // file not exists
- return;
- }
- try {
- // Editor.log(`main.js read data: ${data}`);
- let config = JSON.parse(data);
- _menuTemplateCache = generateMenuTemplate(config);
- } catch (err) {
- // if any error occur, old template cache is not replaced
- } finally {
- }
- });
- }
- function injectContextMenu(webContents) {
- if (webContents.__gt_injected) {
- // already injected
- return;
- }
- if (Editor.Window.main && webContents != Editor.Window.main.nativeWin.webContents) {
- // not cc main app window
- return;
- }
- webContents.__gt_injected = true;
- let hackCode = `
- (() => {
- function appendListener(node, eventType, fn = null) {
- node.addEventListener(eventType, (e) => {
- if (fn) fn(e);
- }, true);
- }
-
- let getLabelRoot = (gridRoot, className) => {
- for (let c of gridRoot.children) {
- if (c.className === className)
- return c;
- }
-
- return null;
- };
-
- let getPixel = (elem) => {
- return parseFloat(elem.style.transform.match(/(-?[0-9\.]+)/g)[0]);
- };
-
- let getWorldPos = (elem) => {
- return parseFloat(elem.innerText.replace(/,/g, ''));
- };
-
- let pixelToWorld = (labelRoot, pixel) => {
- let pmin = getPixel(labelRoot.firstChild);
- let pmax = getPixel(labelRoot.lastChild);
- let wmin = getWorldPos(labelRoot.firstChild);
- let wmax = getWorldPos(labelRoot.lastChild);
- return (pixel - pmin) * (wmax - wmin) / (pmax - pmin) + wmin;
- };
-
- let svgPosToWorld = (x, y) => {
- let gridRoot = document.getElementById('scene').shadowRoot.getElementById('sceneView').shadowRoot.getElementById('grid').shadowRoot;
- let vLabelRoot = getLabelRoot(gridRoot, 'vLabels');
- let hLabelRoot = getLabelRoot(gridRoot, 'hLabels');
- let worldX = pixelToWorld(hLabelRoot, x+4); // horizontal label offset = 4 (move rightward in svg)
- let worldY = pixelToWorld(vLabelRoot, y-15); // vertical label offset = -15 (move upward in svg)
- return [worldX, worldY];
- };
- let svgNode = null;
- let downX = 0;
- let downY = 0;
- let isDown = false;
- let postContextMenuMsg = () => {
- let rect = svgNode.getBoundingClientRect();
- downX -= rect.left;
- downY -= rect.top;
- let worldX = 0;
- let worldY = 0;
- try {
- let arr = svgPosToWorld(downX, downY);
- worldX = arr[0];
- worldY = arr[1];
- } catch(error) {}
- Editor.Ipc.sendToMain('cc-ext-scene-menu:on-context-menu',
- {x: downX, y: downY, worldX: worldX, worldY: worldY}, null);
- };
-
- appendListener(document, 'mousedown', (e) => {
- if (e.button != 2)
- return;
- // check if inside svg view
- if (!svgNode)
- svgNode = document.getElementById('scene').shadowRoot.getElementById('sceneView').shadowRoot.getElementById('gizmosView').shadowRoot.getElementById('SvgjsSvg1000');
-
- if (!svgNode) {
- Editor.log('svg view not ready');
- return;
- }
-
- let rect = svgNode.getBoundingClientRect();
- if (e.pageX >= rect.left && e.pageX < rect.right && e.pageY >= rect.top && e.pageY < rect.bottom) {
- downX = e.pageX;
- downY = e.pageY;
- isDown = true;
- }
- });
-
- appendListener(document, 'mouseup', (e) => {
- if (e.button == 2 && isDown && e.pageX == downX && e.pageY == downY) {
- isDown = false;
- postContextMenuMsg();
- }
- });
- })();
- 1+2+3
- `;
- webContents.executeJavaScript(hackCode, function (result) {
- // result = 6
- });
- }
- module.exports = {
- load() {
- loadMenu();
- try {
- if (Editor.Window.main && Editor.Window.main.nativeWin.webContents.__gt_injected) {
- // in case plugin if reloaded
- return;
- }
- } catch (error) {
- // usually happen when creator is just started and main window is not created
- Editor.log(error);
- }
- // todo: 如果插件是中途加载的,判断webContents如果就绪了就注入
- const electron = require('electron');
- let injectFn = injectContextMenu;
- electron.app.on('web-contents-created', (sender, webContents) => {
- webContents.on('dom-ready', (e) => {
- injectFn(e.sender);
- });
- });
- },
- unload() {
- // let webContenst = Editor.Window.main.nativeWin.webContents;
- // if (webContenst.__gt_injected) {
- // // todo: removeEventListeners
- // webContenst.__gt_injected = false;
- // }
- // execute when package unloaded
- },
- // register your ipc messages here
- messages: {
- 'create-node'() {
- Editor.Scene.callSceneScript('cc-ext-scene-menu', 'create-node', null, function (err) {
- // Editor.log('create-node finish');
- });
- },
- 'on-context-menu'(event, param) {
- param = param || {x: 0, y: 0, worldX: 0, worldY: 0};
- _paramCache = param;
- if (_menuTemplateCache) {
- Editor.Window.main.popupMenu(_menuTemplateCache, param.x, param.y);
- }
- },
- 'custom-context-menu'() {
- Editor.Panel.open('cc-ext-scene-menu');
- },
- 'editGame'() {
- // Editor.log('打开导入关卡面板')
- Editor.Panel.open('cc-ext-scene-menu.editGame');
- },
- 'update-context-menu'() {
- loadMenu();
- },
- 'say-hello'(event, param) {
- Editor.log(`Hello! param: {worldX = ${param.worldX}, worldY = ${param.worldY}}, customParam = ${param.customParam}`);
- }
- },
- };
|