vs-panel.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. // 代码编辑器窗口
  2. // 编辑功能 MonaocEditor 编辑器面板
  3. Editor.require('packages://simple-code/panel/vs-panel/ace/ace.js');
  4. const statistical = Editor.require('packages://simple-code/tools/statistical.js');
  5. const vsEditorPanel = Editor.require('packages://simple-code/panel/vs-panel/vs-panel-base.js');
  6. const acePanel = Editor.require('packages://simple-code/panel/vs-panel/ace-panel.js');
  7. const tools = Editor.require('packages://simple-code/tools/tools.js');
  8. const config = Editor.require('packages://simple-code/config.js');
  9. const keyMap = Editor.require('packages://simple-code/keyMap.js');
  10. const packageCfg = Editor.require('packages://simple-code/package.json');
  11. const updater = Editor.require('packages://simple-code/tools/updater.js');
  12. const fs = require('fs');
  13. const path = require("path");
  14. const electron = require('electron');
  15. const eventMerge = Editor.require('packages://simple-code/tools/eventMerge');
  16. const prsPath = Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectPath;
  17. let _scripts = [];
  18. let is_hint = false;
  19. tools.initI18t()
  20. /** @extends vsEditorPanel */
  21. let layer = {
  22. style:'',
  23. template: `
  24. <div id="box">
  25. <div id="editorA"></div>
  26. <div id="editorB"></div>
  27. <div id="layoutTab" class="layout horizontal justified titleBarFontSize">
  28. <div id="tabList" class="layout horizontal">
  29. <img src=file://${Editor.url("packages://simple-code/panel/images/settingIco.png")} id="waitIco" class="turnAnim"></img> <span></span> <span></span>
  30. <div id="title0" class="closeTab">
  31. <div class="tabTitle"><nobr>无文件<nobr></div>
  32. <div class="closeBtn"><nobr> x <nobr></div>
  33. </div>
  34. </div>
  35. <div id="toolsPanel" class="layout horizontal">
  36. <ui-checkbox id="lockChk" title="锁定当前文件后不再自动关闭">${tools.translate('lock-tab')}</ui-checkbox>
  37. <ui-checkbox id="lockWindowChk" title="锁定后窗口不再自动缩放">${tools.translate('lock-win')}</ui-checkbox>
  38. <ui-button id="manualCompile" class="">${tools.translate('manual-compile')}</ui-button>
  39. <ui-button id="gotoFileBtn" class="blue">${tools.translate('goto-file-btn')}</ui-button>
  40. <ui-button id="settingBtn" class="green">${tools.translate('set')}</ui-button>
  41. <ui-button id="resetBtn" class="red">${tools.translate('reset')}</ui-button>
  42. </div>
  43. </div>
  44. <div id="overlay" class="overlay"></div>
  45. <div id="dropBg" class="dropBg"></div>
  46. </div>
  47. `,
  48. $: {
  49. lockChk: '#lockChk',
  50. lockWindowChk: '#lockWindowChk',
  51. layoutTab: '#layoutTab',
  52. manualCompile: '#manualCompile',
  53. settingBtn: '#settingBtn',
  54. resetBtn: '#resetBtn',
  55. gotoFileBtn: '#gotoFileBtn',
  56. editorA: '#editorA',
  57. editorB: '#editorB',
  58. title0: '#title0',
  59. tabList: '#tabList',
  60. box: '#box',
  61. waitIco: '#waitIco',
  62. overlay: '#overlay',
  63. dropBg:'#dropBg',
  64. toolsPanel: '#toolsPanel',
  65. },
  66. // 启动事件
  67. ready()
  68. {
  69. this.initStartData()
  70. this.initCSS()
  71. this.runExtendFunc("ready",this);
  72. this.initVsEditor(()=>{
  73. this.initData();
  74. this.initBindEvent();
  75. this.initKeybody();
  76. this.setWaitIconActive(false);
  77. this.upCurrSceneChildrenInfo();
  78. this.is_init_finish = true;
  79. this.runExtendFunc("onLoad",this);
  80. this.setOptions(this.cfg,true);
  81. window._panel = this;
  82. });
  83. },
  84. initCSS()
  85. {
  86. let text =
  87. // ace.editorCss +
  88. fs.readFileSync(Editor.url("packages://simple-code/panel/vs-panel/vs-panel.css"), "utf-8") + '\n'+
  89. fs.readFileSync(Editor.url("packages://simple-code/panel/vs-panel/monaco-editor/dev/vs/editor/editor.main.css"), "utf-8");
  90. var style = document.createElement("style");
  91. style.innerHTML = text;
  92. this.$box.appendChild(style);
  93. this.styleSheet = style.sheet;
  94. },
  95. initStartData(){
  96. // 游戏资源路径缓存
  97. this.file_list_buffer = [];
  98. this.file_list_map = {};
  99. // ipc event
  100. this.listenIpcList = []
  101. // creator编辑资源选择信息
  102. this.currCreatorEditorSelectInfo = {}
  103. // 读取配置文件
  104. this.$title0.style.display = 'none';
  105. this.timer_map = {};
  106. this.cfg = config.getLocalStorage();
  107. this.pro_cfg = config.getProjectLocalStorage()
  108. this.ace = new acePanel(this)
  109. },
  110. // 设置选项
  111. setOptions(cfg,isInit)
  112. {
  113. // 基类
  114. this._super(cfg,isInit);
  115. if (cfg.newFileType != null) {
  116. localStorage.setItem("newFileType", cfg.newFileType || "ts");
  117. }
  118. if(cfg.tabBarPos != null){
  119. this.setTabBarPos(cfg.tabBarPos);
  120. }
  121. if(cfg.hideToolsBar != null){
  122. this.$toolsPanel.hidden = cfg.hideToolsBar;
  123. }
  124. if(cfg.codeCompileMode != null || isInit){
  125. this.$manualCompile.hidden = cfg.codeCompileMode != 'manual';
  126. this.$gotoFileBtn.hidden = cfg.codeCompileMode == 'manual';
  127. }
  128. if(cfg.titleBarFontSize != null){
  129. this.setCssByName('.titleBarFontSize',`{font-size: ${cfg.titleBarFontSize}px}`)
  130. }
  131. if(cfg.isCheckUpdater != null && cfg.isCheckUpdater){
  132. this.checkUpdate();
  133. }
  134. this.runExtendFunc("setOptions", cfg,isInit);
  135. if(!isInit) this.saveOptionsByDelayTime()
  136. },
  137. saveOptionsByDelayTime(){
  138. this.setTimeoutById(()=>{
  139. this.saveOptions()
  140. },1000,'saveOptionsByDelayTime')
  141. },
  142. saveOptions(){
  143. // 写入配置
  144. this.cfg.fontSize = this.vs_editor.getRawOptions().fontSize;
  145. this.cfg.search_history = this.search_history;
  146. this.cfg.self_flex_per = this.self_flex_per;
  147. delete this.cfg.language;
  148. config.saveStorage();
  149. },
  150. setCssByName(name,infoText){
  151. for (let i = 0; i < this.styleSheet.cssRules.length; i++) {
  152. const css_rule = this.styleSheet.cssRules[i];
  153. if(css_rule.selectorText == name){
  154. this.styleSheet.deleteRule(i)
  155. this.styleSheet.insertRule(name +' '+ infoText,0)
  156. break;
  157. }
  158. }
  159. },
  160. // 补充缺失的配置,升级版本导致的
  161. loadDefineMeunCfg(cfg){
  162. for (const key in config.optionGroups) {
  163. const groups = config.optionGroups[key];
  164. for (const k in groups) {
  165. const option = groups[k];
  166. if(cfg[option.path] === undefined && option.defaultValue !== undefined){
  167. cfg[option.path] = option.defaultValue; // 补充缺失的配置,升级版本导致的
  168. }
  169. }
  170. }
  171. return cfg;
  172. },
  173. // 加载数据
  174. initData() {
  175. this.mouse_pos;
  176. this.is_init_finish = false;
  177. this.waitSaveIntervals = {}
  178. // 当前场景所有子节点信息缓存
  179. this.currSceneChildrenInfo = [];
  180. // 搜索历史
  181. this.search_history = this.pro_cfg.search_history = this.pro_cfg.search_history || [];
  182. this.setLockWindow(this.cfg.is_lock_window);
  183. },
  184. // 綁定事件
  185. initBindEvent() {
  186. // 失去焦点,编译代码
  187. // this.addEventListener('blur', () => {
  188. // if(this.cfg.codeCompileMode == 'blur'){
  189. // this.refreshSaveFild(false)
  190. // }
  191. // },false);
  192. // 失去焦点
  193. this.$box.addEventListener("blur",()=>
  194. {
  195. if(this.cfg.autoSaveFile == 'blur'){
  196. let oldEditId = this.edit_id || -1;
  197. // 失去焦点自動保存文件,延迟为了防止点击node切换时切换不了标签
  198. this.setTimeoutById(()=>{
  199. if (!this.getTabDiv(oldEditId)) return;
  200. this.saveFileFromDelayTime(false,false,oldEditId,false);
  201. // 失去焦点時編譯文件
  202. if(this.cfg.codeCompileMode == 'blur'){
  203. this.refreshSaveFild(false)
  204. }
  205. },500,'autoSaveFileInterval_'+oldEditId);
  206. }else{
  207. if(this.cfg.codeCompileMode == 'blur'){
  208. this.refreshSaveFild(false) // 失去焦点時編譯文件
  209. }
  210. }
  211. },true)
  212. // 手动编译
  213. this.$manualCompile.addEventListener('confirm', () => {
  214. // if (this.file_info) this.saveFile(true);
  215. this.refreshSaveFild(true)
  216. },false);
  217. // 设置
  218. this.$settingBtn.addEventListener('confirm', () => {
  219. // if (this.file_info) this.saveFile(true);
  220. this.ace.openMenu()
  221. },false);
  222. // 重置
  223. this.$resetBtn.addEventListener('confirm', () => {
  224. if (this.file_info) {
  225. let text = this.fileMgr.checkCurrFileChange(this.file_info);
  226. if (this.file_info.data != this.vs_editor.getValue()) {
  227. if (text) {
  228. this.vs_editor.setValue(text);
  229. this.file_info.is_need_save = false;
  230. this.file_info.data = text;
  231. this.upTitle();
  232. }
  233. }
  234. if (!text) {
  235. this.file_info.uuid = null; // 文件已被删除
  236. this.file_info.is_need_save = false;
  237. this.oepnDefindFile();
  238. }
  239. }
  240. });
  241. // 定位文件
  242. this.$gotoFileBtn.addEventListener('confirm', () => {
  243. if (this.file_info) {
  244. Editor.Ipc.sendToAll('assets:hint', this.file_info.uuid);
  245. }
  246. });
  247. // 锁定编辑
  248. this.$lockChk.addEventListener('change', () => {
  249. this.setLockEdit(this.$lockChk.checked ? true : false);
  250. });
  251. // 锁定窗口
  252. this.$lockWindowChk.addEventListener('change', () => {
  253. this.setLockWindow(this.$lockWindowChk.checked ? true : false);
  254. this.saveOptionsByDelayTime()
  255. });
  256. // node或assets 启动拖拽事件
  257. let dragsArgs = {}
  258. this.addListenerIpc("editor:dragstart", (e, t)=>{
  259. dragsArgs = {
  260. type : t.type,
  261. items : t.items,
  262. options : t.options
  263. }
  264. });
  265. this.addListenerIpc("editor:dragend", ()=>{
  266. dragsArgs = null;
  267. });
  268. // 读取拖入的文件
  269. this.$editorB.addEventListener('dragover',(e)=>{
  270. // if(e.dataTransfer.files[0]){
  271. this.$dropBg.style.display = "block";
  272. e.preventDefault();
  273. e.stopPropagation();
  274. // }
  275. },false)
  276. // 读取拖入的文件
  277. this.$editorB.addEventListener('drop',(e)=>{
  278. this.$dropBg.style.display = "none";
  279. this.onDrag(e,dragsArgs || {});
  280. },false);
  281. this.$editorB.addEventListener('dragleave',(e)=>{
  282. this.$dropBg.style.display = "none";
  283. },false);
  284. this.addListenerIpc('selection:hoverin',(e,type,uuid)=>{
  285. this.onEditorSelectionHoverin(type,uuid);
  286. })
  287. // 鼠标右键nodeTree|asset
  288. this.addListenerIpc('selection:context',(e,type,uuid)=>{
  289. if(uuid == null){
  290. let curSls = Editor.Selection.curGlobalActivate()
  291. if(curSls && curSls.id != null){
  292. return; // 下面函数 selection:activated 继续调用
  293. }
  294. }
  295. this.onEditorSelection(type,uuid);
  296. })
  297. // 鼠标左键选中、取消
  298. this.addListenerIpc('selection:activated',(e,type,uuid)=>{
  299. this.onEditorSelection(type,uuid);
  300. })
  301. // 记录鼠标位置,用于菜单位置
  302. let mousemove = (e)=>{
  303. this.mouse_pos = {y:e.clientY,x:e.clientX}
  304. }
  305. this.addWindowEventListener('mousemove',mousemove,true)
  306. // 用于触发双击事件
  307. let mousedown = (e)=>{
  308. let now_time = new Date().getTime();
  309. if(this._mousedown_time == null || now_time - this._mousedown_time>300){
  310. this._mousedown_time = new Date().getTime()
  311. }else{
  312. // 双击事件分发
  313. let mouse_pos = {y:e.clientY,x:e.clientX}
  314. this.onMouseDoubleClick(mouse_pos);
  315. }
  316. if(!this.isFocused()){
  317. this._isMoveDown = true
  318. this.setTimeoutById(()=>this._isMoveDown = false,2000,'mousedow')
  319. }
  320. }
  321. this.addWindowEventListener('mousedown',mousedown,true)
  322. // 关闭页面提示
  323. this.onDestroy = this.onDestroy.bind(this)
  324. window.addEventListener("beforeunload", this.onDestroy, false);
  325. // 检测窗口改变大小调整
  326. this.schFunc = this.setTimeoutToJS(() =>
  327. {
  328. if(this.parentElement == null){
  329. // 本窗口已被删除
  330. this.onDestroy();
  331. return;
  332. }
  333. let is_up_layout = this.is_init_finish && this.upLayout()
  334. this.upNeedImportListWorker()
  335. this.onCheckLayout(is_up_layout)
  336. }, 0.5);
  337. },
  338. addListenerIpc(name,callback){
  339. this.listenIpcList.push({name,callback});
  340. electron.ipcRenderer.on(name,callback);
  341. },
  342. upLayout(){
  343. if (this.old_width == null || Math.abs(this.$box.clientWidth - this.old_width) >3 || this.old_height == null || Math.abs(this.$box.clientHeight - this.old_height) >3) {
  344. this.old_width = this.$box.clientWidth;
  345. this.old_height = this.$box.clientHeight;
  346. this.vs_editor.layout();
  347. return true;
  348. }
  349. },
  350. // 键盘键事件
  351. initKeybody() {
  352. let pressedKeys = {};
  353. let _this = this;
  354. let ret_type;
  355. let onApplyEvent = (e, type) => {
  356. let ret_type = true;
  357. let count = 0;
  358. let removeKey;
  359. for (let n in pressedKeys) if(pressedKeys[n]) count++;
  360. // let removeList = []
  361. _this.key_cfg.forEach((cfg, i) =>
  362. {
  363. if (type == cfg.touch_type && cfg.keys.length == count) {
  364. if (cfg.mode == 2 || _this.vs_editor.hasTextFocus() == cfg.mode) {
  365. let isHas = true;
  366. cfg.keys.forEach((key) => {
  367. if (!pressedKeys[key] && !pressedKeys["Key"+key.toLocaleUpperCase()]) {
  368. isHas = false;
  369. }
  370. });
  371. if (isHas) {
  372. if (cfg.callback) {
  373. removeKey = e.key;
  374. // Array.prototype.push.apply(removeList,cfg.keys)
  375. if(count == 1 && e.key.length == 1 && tools.inputTypeChk(e)){
  376. return; // 单键情况下且处于编辑文本状态则不触发快捷键
  377. }
  378. ret_type = ret_type && cfg.callback(e);
  379. }
  380. }
  381. }
  382. }
  383. });
  384. // removeList.forEach((key)=> delete pressedKeys[key]);
  385. if (removeKey) delete pressedKeys[removeKey];
  386. return ret_type;
  387. }
  388. this.addWindowEventListener("keydown", function (e) {
  389. pressedKeys = {
  390. [config.keyMap[e.keyCode] ? config.keyMap[e.keyCode] : e.key] : 1,
  391. ['Alt'] : e.altKey,
  392. ['Ctrl'] : e.ctrlKey,
  393. ['Meta'] : e.metaKey,
  394. ['Shift'] : e.shiftKey,
  395. }
  396. ret_type = onApplyEvent(e, 'keydown');
  397. _this.runExtendFunc("onKeyDown", e);
  398. // console.log("A",e.key,pressedKeys)
  399. return ret_type;
  400. }, true);
  401. this.addWindowEventListener("keypress", function (e) {
  402. pressedKeys = {
  403. [config.keyMap[e.keyCode] ? config.keyMap[e.keyCode] : e.key] : 1,
  404. ['Alt'] : e.altKey,
  405. ['Ctrl'] : e.ctrlKey,
  406. ['Meta'] : e.metaKey,
  407. ['Shift'] : e.shiftKey,
  408. }
  409. ret_type = onApplyEvent(e, 'keypress');
  410. // _this.runExtendFunc("onKeypRess",e);
  411. // console.log("B",e.key,pressedKeys)
  412. return ret_type;
  413. }, true);
  414. this.addWindowEventListener("keyup", function (e) {
  415. // pressedKeys = {};
  416. pressedKeys = {
  417. [config.keyMap[e.keyCode] ? config.keyMap[e.keyCode] : e.key] : 1,
  418. ['Alt'] : e.altKey,
  419. ['Ctrl'] : e.ctrlKey,
  420. ['Meta'] : e.metaKey,
  421. ['Shift'] : e.shiftKey,
  422. }
  423. _this.runExtendFunc("onKeyUp", e);
  424. }, true);
  425. // 重置key
  426. this.addWindowEventListener("focus", () => pressedKeys = {},true)
  427. // 阻挡冒泡creator的快捷键
  428. // this.$box.addEventListener("keydown", (e)=> {
  429. // let className = e.path[0] && e.path[0].className || ''
  430. // if (className.indexOf('monaco') != -1 && (e.key == "w" || e.key == "e" || e.key == "r" || e.key == "t")) e.stopPropagation()
  431. // }, false);
  432. this.addKeybodyEvent([["Ctrl", "s"], ["Meta", "s"]], (e) =>
  433. {
  434. let id = this.file_info.id;
  435. this.saveFileFromDelayTime(true,false,id);
  436. e.preventDefault();// 吞噬捕获事件
  437. return false;
  438. }, 1, "keydown");
  439. // 关闭页面
  440. this.addKeybodyEventByName('closeTab', (e) => {
  441. this.closeTab(this.edit_id);
  442. e.preventDefault();// 吞噬捕获事件
  443. return false;
  444. }, 1, "keydown");
  445. // tab 左移
  446. this.addKeybodyEventByName('prevView', (e) => {
  447. this.tabToLeft(true);
  448. e.preventDefault();// 吞噬捕获事件
  449. return false;
  450. }, 1, "keydown");
  451. // tab 右移
  452. this.addKeybodyEventByName('nextView', (e) => {
  453. this.tabToRight(true);
  454. e.preventDefault();// 吞噬捕获事件
  455. return false;
  456. }, 1, "keydown");
  457. // tab
  458. this.addKeybodyEventByName('switchTab', (e) => {
  459. this.setTabPage(this.old_edit_id);
  460. e.preventDefault();// 吞噬捕获事件
  461. e.stopPropagation()
  462. return false;
  463. }, 1, "keydown");
  464. },
  465. // 获得下拉条列表目数据
  466. getItem(value, meta, score, args) {
  467. let item_cfg = {
  468. value: value, // 命令
  469. meta: meta, // 描述
  470. score: score,//搜索优先级
  471. args: args, // 自定义数据
  472. matchMask: 0,
  473. exactMatch: 1,
  474. };
  475. return item_cfg;
  476. },
  477. setTabBarPos(str){
  478. this.$box.style.flexDirection = str ? 'column' : 'column-reverse';
  479. },
  480. // 锁定编辑
  481. setLockEdit(is_lock,id)
  482. {
  483. id = id == null ? this.edit_id : id;
  484. let info = this.edit_list[id] || {};
  485. // 打开文件解除锁定编辑
  486. if (id == this.edit_id) this.$lockChk.checked = is_lock;
  487. info.is_lock = is_lock;
  488. this.vs_editor.updateOptions({ lineNumbers: info.is_cmd_mode || id != 0 ? "on" : 'off' });
  489. this.vs_editor.updateOptions({ lineNumbers: info.is_cmd_mode || id != 0 ? "on" : 'off' });
  490. this.upTitle(id);
  491. },
  492. // 锁定窗口
  493. setLockWindow(is_lock)
  494. {
  495. this.cfg.is_lock_window = is_lock;
  496. this.$lockWindowChk.checked = is_lock ? true : false;
  497. },
  498. // 添加快捷键, 例子: this.addKeybodyEvent([ ["Ctrl","x"] ],()=>{})
  499. addKeybodyEvent(arrKeys, callback, isOnEditorRun, touchType = "keydown") {
  500. arrKeys.forEach((keys) => {
  501. keys.forEach((v, i) => {
  502. keys[i] = v == "Control" ? "Ctrl" : keys[i];
  503. })
  504. this.key_cfg.push({ keys, callback, mode: isOnEditorRun, touch_type: touchType });
  505. })
  506. },
  507. // 按钮事件
  508. addKeybodyEventByName(keyName, callback, isOnEditorRun, touchType = "keydown") {
  509. let arrKeys = this.getKeys(keyName);
  510. if(arrKeys){
  511. this.addKeybodyEvent(arrKeys, callback, isOnEditorRun, touchType)
  512. }
  513. },
  514. getKeys(keyName){
  515. let keyInfo = keyMap[keyName];
  516. if(keyInfo){
  517. return Editor.isWin32 ? keyInfo.win32 : keyInfo.mac;
  518. }
  519. },
  520. setWaitIconActive(isActive){
  521. if(this.$waitIco){
  522. this.$waitIco.className = isActive ? 'turnAnim' : '';
  523. }
  524. },
  525. // 刷新场景所有的子节点信息缓存
  526. upCurrSceneChildrenInfo() {
  527. if(!this.isInitEditorScene){
  528. return
  529. }
  530. // 从场景获得代码数据
  531. Editor.Scene.callSceneScript('simple-code', 'scene-children-info', "", (err, data) => {
  532. if (!data || data == "") return;
  533. this.currSceneChildrenInfo = JSON.parse(data);
  534. this.onCurrSceneChildrenInfo(this.currSceneChildrenInfo);
  535. }, -1)
  536. },
  537. onCheckLayout(isUpLayout){
  538. this.runExtendFunc("onCheckLayout", isUpLayout);
  539. },
  540. onCurrSceneChildrenInfo(currSceneChildrenInfo) {
  541. this.runExtendFunc("onCurrSceneChildrenInfo", currSceneChildrenInfo);
  542. },
  543. onMouseDoubleClick(mousePos){
  544. this.runExtendFunc("onMouseDoubleClick",mousePos);
  545. },
  546. // 窗口获得焦点
  547. onFocus(){
  548. this._super()
  549. this.runExtendFunc("onFocus");
  550. },
  551. // 窗口失去焦点
  552. // onBlur(){
  553. // this._super()
  554. // this.runExtendFunc("onBlur");
  555. // },
  556. // onclose(){
  557. // this.onDestroy()
  558. // },
  559. // 页面关闭
  560. onDestroy()
  561. {
  562. if(this._is_destroy || this.edit_list == null) return;
  563. this._is_destroy = true;
  564. this._super();
  565. this.runExtendFunc("onDestroy");
  566. // 移除 window 事件
  567. window.removeEventListener('beforeunload',this.onDestroy,false);
  568. for (let i = 0; i < this.window_event_listener.length; i++) {
  569. const event = this.window_event_listener[i];
  570. window.removeEventListener(event.eventName,event.callback,event.option)
  571. }
  572. // 移除ipc事件
  573. for (let i = 0; i < this.listenIpcList.length; i++) {
  574. const event = this.listenIpcList[i];
  575. electron.ipcRenderer.removeListener(event.name,event.callback);
  576. }
  577. // 停止事件
  578. if (this.schFunc) this.schFunc();
  579. if(this.menu && this.menu.destroy) this.menu.destroy()
  580. this.menu = null;
  581. // 手动编译的文件
  582. this.refreshSaveFild();
  583. // 保存编辑信息
  584. let temp_path_map = {}
  585. this.edit_list.forEach((editInfo, id) => {
  586. if (editInfo) {
  587. if (editInfo.uuid && editInfo.is_need_save) {
  588. let time = new Date().getTime();
  589. if (editInfo.uuid != "outside" && confirm("窗口即将关闭!" + editInfo.path + " 文件被修改是否保存?")) {
  590. this.saveFile();
  591. } else {
  592. let dff_time = (new Date().getTime()) - time;
  593. if (dff_time < 10) {
  594. this.saveFile();
  595. } else {
  596. Editor.log("丢弃修改:", editInfo.new_data);
  597. }
  598. }
  599. }
  600. temp_path_map[editInfo.path] = editInfo.is_lock;
  601. this.file_cfg[editInfo.path] = this.file_cfg[editInfo.path] = {}
  602. this.file_cfg[editInfo.path].is_open = editInfo.is_lock;
  603. this.file_cfg[editInfo.path].is_show = editInfo.vs_model == this.vs_editor.getModel() ? 1 : 0;
  604. }
  605. });
  606. for (const url in this.file_cfg) {
  607. if(this.getTabIdByPath(url) == null){
  608. delete this.file_cfg[url];
  609. }
  610. }
  611. for (let key in this.file_cfg) {
  612. if (!temp_path_map[key]) delete this.file_cfg[key];
  613. }
  614. this.edit_list.forEach((_,id) => {
  615. this.closeTab(id);
  616. });
  617. // 延迟清除缓存,如果creator窗口被关闭就不需要清除
  618. let models = this.monaco.editor.getModels();
  619. setTimeout(()=>{
  620. for (const key in models) {
  621. const model = models[key];
  622. if(model) model.dispose();
  623. }
  624. },0.01)
  625. this.saveOptions();
  626. },
  627. initExtend()
  628. {
  629. // 合并事件函数,分发
  630. let info = eventMerge.eventMerge(this.messages, "panel_ex.js");
  631. _scripts = info.scripts;
  632. this.messages = info.messages;
  633. },
  634. runExtendFunc(funcName, ...args) {
  635. _scripts.forEach((obj) => {
  636. if (obj[funcName]) {
  637. obj[funcName](...args);
  638. }
  639. })
  640. },
  641. /**鼠标左或右点击节点树或资源目录时触发
  642. * @param type = node | asset
  643. * */
  644. onEditorSelection(type,uuid){
  645. if(!this.isInitEditorScene){
  646. return;
  647. }
  648. this.onRefreshCreatorMenu(type,uuid);
  649. this.runExtendFunc('onEditorSelection',type,uuid);
  650. },
  651. /**鼠标移动经过节点树或资源目录时触发
  652. * @param type = node | asset
  653. * */
  654. onEditorSelectionHoverin(type,uuid){
  655. if(!this.isInitEditorScene){
  656. return;
  657. }
  658. this.onRefreshCreatorMenu(type,uuid);
  659. this.runExtendFunc('onEditorSelectionHoverin',type,uuid)
  660. },
  661. /** 需要刷新creator右键菜单
  662. * @param type = node | asset
  663. * */
  664. onRefreshCreatorMenu(type,uuid){
  665. if(!this.is_init_finish) return;
  666. this.currCreatorEditorSelectInfo.type = type;
  667. this.currCreatorEditorSelectInfo.uuid = uuid;
  668. this.runExtendFunc('onRefreshCreatorMenu',type,uuid)
  669. },
  670. /**
  671. * 拖入事件
  672. * @param {evnt} e
  673. * @param {object} dragsArgs - {type:'node',items:[{id:'uuidxx',name:''}]} || {}
  674. */
  675. onDrag(e,dragsArgs){
  676. e.preventDefault();
  677. var fileObj = e.dataTransfer.files[0];
  678. if(fileObj){
  679. if(!this.openOutSideFile(fileObj.path,true))
  680. {
  681. Editor.log('暂不支持该文本类型:',path.extname(fileObj.path));
  682. }
  683. }
  684. this.runExtendFunc('onDrag',e,dragsArgs)
  685. },
  686. // 扩展使用的事件
  687. onAssetsChangedEvent(file){
  688. this._super(file);
  689. this.runExtendFunc('onAssetsChangedEvent',file)
  690. },
  691. onAssetsCreatedEvent(files){
  692. this.runExtendFunc('onAssetsCreatedEvent',files)
  693. },
  694. onAssetsDeletedEvent(files){
  695. this.runExtendFunc('onAssetsDeletedEvent',files)
  696. },
  697. onAssetsMovedEvent(files){
  698. this.runExtendFunc('onAssetsMovedEvent',files)
  699. },
  700. // 正在切换页面标签栏
  701. onSwitchTab(oldEditId = -1,newEditId){
  702. this._super(oldEditId,newEditId);
  703. if (!this.getTabDiv(oldEditId)){
  704. return;
  705. }
  706. if(this.cfg.autoSaveFile == 'blur'){
  707. // 失去焦点自動保存文件
  708. this.saveFileFromDelayTime(false,false,oldEditId,false);
  709. }
  710. },
  711. // 检查更新
  712. async checkUpdate() {
  713. const newVersionDesc = await updater.check();
  714. // 打印到控制台
  715. if (newVersionDesc) {
  716. let hitnText = tools.translateZhAndEn('发现新版本,请过”扩展商店”下载更新,更新内容如下:\n','If you find the new version, please go to the "Extension Store" to download the update as follows :\n')
  717. Editor.info(`[${packageCfg.description}]`, hitnText ,newVersionDesc);
  718. }
  719. statistical.countStartupTimes();
  720. },
  721. messages: {
  722. // 场景保存
  723. 'scene:saved'(event) {
  724. if(!this.is_init_finish) return;
  725. this.saveFileFromDelayTime();
  726. this.upCurrSceneChildrenInfo();
  727. },
  728. // 场景加载完
  729. 'scene:ready'(event) {
  730. if(!this.is_init_finish) return;
  731. this.upCurrSceneChildrenInfo();
  732. },
  733. // 预制节点加载完
  734. 'scene:enter-prefab-edit-mode'(event) {
  735. if(!this.is_init_finish) return;
  736. this.upCurrSceneChildrenInfo();
  737. },
  738. // 选择改变
  739. 'selection:activated'(event) {
  740. if(!this.is_init_finish ||this.is_not_select_active) return;
  741. // 阻止保存时tab乱切换
  742. if(this._isMoveDown || !this.isFocused()){
  743. this.openActiveFile(!this.is_save_wait_up && this.cfg.clickToViewCode,!this.is_save_wait_up);
  744. }
  745. },
  746. // 项目资源文件uuid发生改变
  747. 'asset-db:asset-uuid-changed'(event) {
  748. },
  749. // 项目资源文件发生改变
  750. 'asset-db:asset-changed'(event, info) {
  751. if(!this.is_init_finish || this.is_not_select_active) return;
  752. this.fileMgr.assetsChangedEvent(info);
  753. this.onAssetsChangedEvent(info);
  754. },
  755. // 项目资源创建
  756. 'asset-db:assets-created'(event, files) {
  757. if(!this.is_init_finish) return;
  758. if (!files && this.file_list_buffer) return;
  759. this.fileMgr.assetsCreatedEvent(files)
  760. this.onAssetsCreatedEvent(files);
  761. },
  762. // 项目文件被删除
  763. 'asset-db:assets-deleted'(event, files) {
  764. if(!this.is_init_finish) return;
  765. if (!files && this.file_list_buffer) return;
  766. this.fileMgr.assetsDeletedEvent(files)
  767. this.onAssetsDeletedEvent(files);
  768. },
  769. // 项目文件被移动了
  770. 'asset-db:assets-moved'(event, files)
  771. {
  772. if(!this.is_init_finish) return;
  773. if (!files) return;
  774. this.fileMgr.assetsMovedEvent(files)
  775. this.onAssetsMovedEvent(files);
  776. },
  777. 'open-code-file'(e,file){
  778. this.openOutSideFile(file,true)
  779. },
  780. // 快捷键打开当前选中文件/节点进入编辑
  781. 'custom-cmd'(event, info) {
  782. if(!this.is_init_finish) return;
  783. if (info.cmd == "openFile") {
  784. this.openActiveFile(true,false);
  785. } else if (info.cmd == "setting") {
  786. this.ace.openMenu();
  787. }
  788. }
  789. }
  790. };
  791. layer.initExtend();
  792. tools.extendTo(layer,vsEditorPanel);
  793. Editor.Panel.extend(layer);
  794. module.exports = layer;