From 8ef417cfb2bdac11fb427d74f8d8202b60ac8eaa Mon Sep 17 00:00:00 2001 From: liteng <930372551@qq.com> Date: Thu, 30 Aug 2018 20:19:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4CodeMirrorChangeEvent.js?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/editor/script/ScriptEditor.js | 185 ++++++++++++++- ShadowEditor.Web/src/event/EventDispatcher.js | 7 +- ShadowEditor.Web/src/event/EventList.js | 3 +- .../src/event/script/CodeMirrorChangeEvent.js | 213 ------------------ 4 files changed, 185 insertions(+), 223 deletions(-) delete mode 100644 ShadowEditor.Web/src/event/script/CodeMirrorChangeEvent.js diff --git a/ShadowEditor.Web/src/editor/script/ScriptEditor.js b/ShadowEditor.Web/src/editor/script/ScriptEditor.js index 3a9a51d8..bba32915 100644 --- a/ShadowEditor.Web/src/editor/script/ScriptEditor.js +++ b/ShadowEditor.Web/src/editor/script/ScriptEditor.js @@ -165,8 +165,7 @@ ScriptEditor.prototype.onAppStarted = function () { codemirror.setOption('theme', 'monokai'); codemirror.on('change', () => { - debugger - // this.app.call('codeMirrorChange', this, codemirror, this.currentMode, this.currentScript, this.currentObject); + }); // 防止回退键删除物体 @@ -213,4 +212,186 @@ ScriptEditor.prototype.onAppStarted = function () { this.server = server; }; +ScriptEditor.prototype.onCodeMirrorChange = function (codemirror, currentMode, currentScript, currentObject) { + if (codemirror.state.focused === false) { + return; + } + + clearTimeout(this.delay); + + var _this = this; + + this.delay = setTimeout(function () { + var value = codemirror.getValue(); + + if (!_this.validate(codemirror, currentMode, currentObject, value)) { + return; + } + + if (typeof (currentScript) === 'object') { + if (value !== currentScript.source) { + _this.app.editor.execute(new SetScriptValueCommand(currentObject, currentScript, 'source', value, codemirror.getCursor(), codemirror.getScrollInfo())); + } + return; + } + + if (currentScript !== 'programInfo') { + return; + } + + var json = JSON.parse(value); + + if (JSON.stringify(currentObject.material.defines) !== JSON.stringify(json.defines)) { + var cmd = new SetMaterialValueCommand(currentObject, 'defines', json.defines); + cmd.updatable = false; + editor.execute(cmd); + } + if (JSON.stringify(currentObject.material.uniforms) !== JSON.stringify(json.uniforms)) { + var cmd = new SetMaterialValueCommand(currentObject, 'uniforms', json.uniforms); + cmd.updatable = false; + editor.execute(cmd); + } + if (JSON.stringify(currentObject.material.attributes) !== JSON.stringify(json.attributes)) { + var cmd = new SetMaterialValueCommand(currentObject, 'attributes', json.attributes); + cmd.updatable = false; + editor.execute(cmd); + } + }, 1000); +}; + +ScriptEditor.prototype.validate = function (codemirror, currentMode, currentObject, string) { + var errorLines = this.errorLines; + var widgets = this.widgets; + + var valid; + var errors = []; + + var _this = this; + + return codemirror.operation(function () { + + while (errorLines.length > 0) { + codemirror.removeLineClass(errorLines.shift(), 'background', 'errorLine'); + } + + while (widgets.length > 0) { + codemirror.removeLineWidget(widgets.shift()); + } + + // + switch (currentMode) { + case 'javascript': + try { + var syntax = esprima.parse(string, { tolerant: true }); + errors = syntax.errors; + } catch (error) { + errors.push({ + lineNumber: error.lineNumber - 1, + message: error.message + }); + } + + for (var i = 0; i < errors.length; i++) { + var error = errors[i]; + error.message = error.message.replace(/Line [0-9]+: /, ''); + } + break; + case 'json': + errors = []; + + jsonlint.parseError = function (message, info) { + message = message.split('\n')[3]; + errors.push({ + lineNumber: info.loc.first_line - 1, + message: message + }); + }; + + try { + jsonlint.parse(string); + } catch (error) { + // ignore failed error recovery + } + break; + case 'glsl': + try { + var shaderType = currentScript === 'vertexShader' ? + glslprep.Shader.VERTEX : glslprep.Shader.FRAGMENT; + glslprep.parseGlsl(string, shaderType); + } catch (error) { + if (error instanceof glslprep.SyntaxError) { + errors.push({ + lineNumber: error.line, + message: "Syntax Error: " + error.message + }); + } else { + console.error(error.stack || error); + } + } + + if (errors.length !== 0) { + break; + } + if (_this.app.editor.renderer instanceof THREE.WebGLRenderer === false) { + break; + } + + currentObject.material[currentScript] = string; + currentObject.material.needsUpdate = true; + + _this.app.call('materialChanged', _this, currentObject.material); + + var programs = _this.app.editor.renderer.info.programs; + + valid = true; + var parseMessage = /^(?:ERROR|WARNING): \d+:(\d+): (.*)/g; + + for (var i = 0, n = programs.length; i !== n; ++i) { + var diagnostics = programs[i].diagnostics; + + if (diagnostics === undefined || diagnostics.material !== currentObject.material) { + continue; + } + + if (!diagnostics.runnable) { + valid = false; + } + + var shaderInfo = diagnostics[currentScript]; + var lineOffset = shaderInfo.prefix.split(/\r\n|\r|\n/).length; + + while (true) { + var parseResult = parseMessage.exec(shaderInfo.log); + if (parseResult === null) break; + + errors.push({ + lineNumber: parseResult[1] - lineOffset, + message: parseResult[2] + }); + } // messages + break; + } // programs + + } // mode switch + + for (var i = 0; i < errors.length; i++) { + var error = errors[i]; + + var message = document.createElement('div'); + message.className = 'esprima-error'; + message.textContent = error.message; + + var lineNumber = Math.max(error.lineNumber, 0); + errorLines.push(lineNumber); + + codemirror.addLineClass(lineNumber, 'background', 'errorLine'); + + var widget = codemirror.addLineWidget(lineNumber, message); + widgets.push(widget); + } + + return valid !== undefined ? valid : errors.length === 0; + }); +}; + export default ScriptEditor; \ No newline at end of file diff --git a/ShadowEditor.Web/src/event/EventDispatcher.js b/ShadowEditor.Web/src/event/EventDispatcher.js index 008b6032..632151ed 100644 --- a/ShadowEditor.Web/src/event/EventDispatcher.js +++ b/ShadowEditor.Web/src/event/EventDispatcher.js @@ -94,8 +94,6 @@ import EditorControlsEvent from './viewport/EditorControlsEvent'; import GridChangeEvent from './statusBar/GridChangeEvent'; -import CodeMirrorChangeEvent from './script/CodeMirrorChangeEvent'; - /** * 事件执行器 * @author tengge / https://github.com/tengge1 @@ -198,10 +196,7 @@ function EventDispatcher(app) { new EditorControlsEvent(this.app), // 状态栏事件 - new GridChangeEvent(this.app), - - // 代码编辑器中的事件 - new CodeMirrorChangeEvent(this.app), + new GridChangeEvent(this.app) ]; } diff --git a/ShadowEditor.Web/src/event/EventList.js b/ShadowEditor.Web/src/event/EventList.js index 8f4e17d2..ffdee68e 100644 --- a/ShadowEditor.Web/src/event/EventList.js +++ b/ShadowEditor.Web/src/event/EventList.js @@ -146,8 +146,7 @@ var EventList = [ 'selectPropertyTab', // 切换属性选项卡 // 状态栏 - 'gridChange', // 状态栏网格改变事件 - 'codeMirrorChange', // CodeMirror改变事件 + 'gridChange' // 状态栏网格改变事件 ]; export default EventList; \ No newline at end of file diff --git a/ShadowEditor.Web/src/event/script/CodeMirrorChangeEvent.js b/ShadowEditor.Web/src/event/script/CodeMirrorChangeEvent.js deleted file mode 100644 index 2aea9891..00000000 --- a/ShadowEditor.Web/src/event/script/CodeMirrorChangeEvent.js +++ /dev/null @@ -1,213 +0,0 @@ -import BaseEvent from '../BaseEvent'; -import SetScriptValueCommand from '../../command/SetScriptValueCommand'; -import SetMaterialValueCommand from '../../command/SetMaterialValueCommand'; - -/** - * CodeMirror改变事件 - * @author tengge / https://github.com/tengge1 - * @param {*} app - */ -function CodeMirrorChangeEvent(app) { - BaseEvent.call(this, app); - this.delay = null; - this.errorLines = []; - this.widgets = []; -} - -CodeMirrorChangeEvent.prototype = Object.create(BaseEvent.prototype); -CodeMirrorChangeEvent.prototype.constructor = CodeMirrorChangeEvent; - -CodeMirrorChangeEvent.prototype.start = function () { - var _this = this; - this.app.on('codeMirrorChange.' + this.id, function (codemirror, currentMode, currentScript, currentObject) { - _this.onCodeMirrorChange(codemirror, currentMode, currentScript, currentObject); - }); -}; - -CodeMirrorChangeEvent.prototype.stop = function () { - this.app.on('codeMirrorChange.' + this.id, null); -}; - -CodeMirrorChangeEvent.prototype.onCodeMirrorChange = function (codemirror, currentMode, currentScript, currentObject) { - if (codemirror.state.focused === false) { - return; - } - - clearTimeout(this.delay); - - var _this = this; - - this.delay = setTimeout(function () { - var value = codemirror.getValue(); - - if (!_this.validate(codemirror, currentMode, currentObject, value)) { - return; - } - - if (typeof (currentScript) === 'object') { - if (value !== currentScript.source) { - _this.app.editor.execute(new SetScriptValueCommand(currentObject, currentScript, 'source', value, codemirror.getCursor(), codemirror.getScrollInfo())); - } - return; - } - - if (currentScript !== 'programInfo') { - return; - } - - var json = JSON.parse(value); - - if (JSON.stringify(currentObject.material.defines) !== JSON.stringify(json.defines)) { - var cmd = new SetMaterialValueCommand(currentObject, 'defines', json.defines); - cmd.updatable = false; - editor.execute(cmd); - } - if (JSON.stringify(currentObject.material.uniforms) !== JSON.stringify(json.uniforms)) { - var cmd = new SetMaterialValueCommand(currentObject, 'uniforms', json.uniforms); - cmd.updatable = false; - editor.execute(cmd); - } - if (JSON.stringify(currentObject.material.attributes) !== JSON.stringify(json.attributes)) { - var cmd = new SetMaterialValueCommand(currentObject, 'attributes', json.attributes); - cmd.updatable = false; - editor.execute(cmd); - } - }, 1000); -}; - -CodeMirrorChangeEvent.prototype.validate = function (codemirror, currentMode, currentObject, string) { - var errorLines = this.errorLines; - var widgets = this.widgets; - - var valid; - var errors = []; - - var _this = this; - - return codemirror.operation(function () { - - while (errorLines.length > 0) { - codemirror.removeLineClass(errorLines.shift(), 'background', 'errorLine'); - } - - while (widgets.length > 0) { - codemirror.removeLineWidget(widgets.shift()); - } - - // - switch (currentMode) { - case 'javascript': - try { - var syntax = esprima.parse(string, { tolerant: true }); - errors = syntax.errors; - } catch (error) { - errors.push({ - lineNumber: error.lineNumber - 1, - message: error.message - }); - } - - for (var i = 0; i < errors.length; i++) { - var error = errors[i]; - error.message = error.message.replace(/Line [0-9]+: /, ''); - } - break; - case 'json': - errors = []; - - jsonlint.parseError = function (message, info) { - message = message.split('\n')[3]; - errors.push({ - lineNumber: info.loc.first_line - 1, - message: message - }); - }; - - try { - jsonlint.parse(string); - } catch (error) { - // ignore failed error recovery - } - break; - case 'glsl': - try { - var shaderType = currentScript === 'vertexShader' ? - glslprep.Shader.VERTEX : glslprep.Shader.FRAGMENT; - glslprep.parseGlsl(string, shaderType); - } catch (error) { - if (error instanceof glslprep.SyntaxError) { - errors.push({ - lineNumber: error.line, - message: "Syntax Error: " + error.message - }); - } else { - console.error(error.stack || error); - } - } - - if (errors.length !== 0) { - break; - } - if (_this.app.editor.renderer instanceof THREE.WebGLRenderer === false) { - break; - } - - currentObject.material[currentScript] = string; - currentObject.material.needsUpdate = true; - - _this.app.call('materialChanged', _this, currentObject.material); - - var programs = _this.app.editor.renderer.info.programs; - - valid = true; - var parseMessage = /^(?:ERROR|WARNING): \d+:(\d+): (.*)/g; - - for (var i = 0, n = programs.length; i !== n; ++i) { - var diagnostics = programs[i].diagnostics; - - if (diagnostics === undefined || diagnostics.material !== currentObject.material) { - continue; - } - - if (!diagnostics.runnable) { - valid = false; - } - - var shaderInfo = diagnostics[currentScript]; - var lineOffset = shaderInfo.prefix.split(/\r\n|\r|\n/).length; - - while (true) { - var parseResult = parseMessage.exec(shaderInfo.log); - if (parseResult === null) break; - - errors.push({ - lineNumber: parseResult[1] - lineOffset, - message: parseResult[2] - }); - } // messages - break; - } // programs - - } // mode switch - - for (var i = 0; i < errors.length; i++) { - var error = errors[i]; - - var message = document.createElement('div'); - message.className = 'esprima-error'; - message.textContent = error.message; - - var lineNumber = Math.max(error.lineNumber, 0); - errorLines.push(lineNumber); - - codemirror.addLineClass(lineNumber, 'background', 'errorLine'); - - var widget = codemirror.addLineWidget(lineNumber, message); - widgets.push(widget); - } - - return valid !== undefined ? valid : errors.length === 0; - }); -}; - -export default CodeMirrorChangeEvent; \ No newline at end of file