diff --git a/src/event/menu/edit/RedoEvent.js b/src/event/menu/edit/RedoEvent.js index e134db66..11166481 100644 --- a/src/event/menu/edit/RedoEvent.js +++ b/src/event/menu/edit/RedoEvent.js @@ -16,10 +16,14 @@ RedoEvent.prototype.start = function () { this.app.on('mRedo.' + this.id, function () { _this.onRedo(); }); + this.app.on('historyChanged.' + this.id, function () { + _this.onHistoryChanged(); + }); }; RedoEvent.prototype.stop = function () { this.app.on('mRedo.' + this.id, null); + this.app.on('historyChanged.' + this.id, null); }; RedoEvent.prototype.onRedo = function () { @@ -28,4 +32,19 @@ RedoEvent.prototype.onRedo = function () { editor.redo(); }; +RedoEvent.prototype.onHistoryChanged = function () { + var history = this.app.editor.history; + var dom = document.getElementById('mRedo'); + + if (history.redos.length === 0) { + if (!dom.classList.contains('inactive')) { + dom.classList.add('inactive'); + } + } else { + if (dom.classList.contains('inactive')) { + dom.classList.remove('inactive'); + } + } +}; + export default RedoEvent; \ No newline at end of file diff --git a/src/event/menu/edit/UndoEvent.js b/src/event/menu/edit/UndoEvent.js index 3ffb9cb5..d329ef26 100644 --- a/src/event/menu/edit/UndoEvent.js +++ b/src/event/menu/edit/UndoEvent.js @@ -16,10 +16,14 @@ UndoEvent.prototype.start = function () { this.app.on('mUndo.' + this.id, function () { _this.onUndo(); }); + this.app.on('historyChanged.' + this.id, function () { + _this.onHistoryChanged(); + }); }; UndoEvent.prototype.stop = function () { this.app.on('mUndo.' + this.id, null); + this.app.on('historyChanged.' + this.id, null); }; UndoEvent.prototype.onUndo = function () { @@ -28,4 +32,19 @@ UndoEvent.prototype.onUndo = function () { editor.undo(); }; +UndoEvent.prototype.onHistoryChanged = function () { + var history = this.app.editor.history; + var dom = document.getElementById('mUndo'); + + if (history.undos.length === 0) { + if (!dom.classList.contains('inactive')) { + dom.classList.add('inactive'); + } + } else { + if (dom.classList.contains('inactive')) { + dom.classList.remove('inactive'); + } + } +}; + export default UndoEvent; \ No newline at end of file diff --git a/src/menu/EditMenu.js b/src/menu/EditMenu.js deleted file mode 100644 index d60523f4..00000000 --- a/src/menu/EditMenu.js +++ /dev/null @@ -1,213 +0,0 @@ -import AddObjectCommand from '../command/AddObjectCommand'; -import RemoveObjectCommand from '../command/RemoveObjectCommand'; -import SetMaterialValueCommand from '../command/SetMaterialValueCommand'; -import MultiCmdsCommand from '../command/MultiCmdsCommand'; -import UI from '../ui/UI'; - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function EditMenu(editor) { - - var container = new UI.Panel(); - container.setClass('menu'); - - var title = new UI.Panel(); - title.setClass('title'); - title.setTextContent('编辑'); - container.add(title); - - var options = new UI.Panel(); - options.setClass('options'); - container.add(options); - - // Undo - - var undo = new UI.Row(); - undo.setClass('option'); - undo.setTextContent('撤销(Ctrl+Z)'); - undo.onClick(function () { - - editor.undo(); - - }); - options.add(undo); - - // Redo - - var redo = new UI.Row(); - redo.setClass('option'); - redo.setTextContent('重做(Ctrl+Shift+Z)'); - redo.onClick(function () { - - editor.redo(); - - }); - options.add(redo); - - // Clear History - - var option = new UI.Row(); - option.setClass('option'); - option.setTextContent('清空历史记录'); - option.onClick(function () { - - if (confirm('撤销/重做历史纪录将被清空。确定吗?')) { - - editor.history.clear(); - - } - - }); - options.add(option); - - - editor.app.on('historyChanged.EditMenu', function () { - - var history = editor.history; - - undo.setClass('option'); - redo.setClass('option'); - - if (history.undos.length == 0) { - - undo.setClass('inactive'); - - } - - if (history.redos.length == 0) { - - redo.setClass('inactive'); - - } - - }); - - // --- - - options.add(new UI.HorizontalRule()); - - // Clone - - var option = new UI.Row(); - option.setClass('option'); - option.setTextContent('复制'); - option.onClick(function () { - - var object = editor.selected; - - if (object.parent === null) return; // avoid cloning the camera or scene - - object = object.clone(); - - editor.execute(new AddObjectCommand(object)); - - }); - options.add(option); - - // Delete - - var option = new UI.Row(); - option.setClass('option'); - option.setTextContent('删除(Del)'); - option.onClick(function () { - - var object = editor.selected; - - if (confirm('Delete ' + object.name + '?') === false) return; - - var parent = object.parent; - if (parent === undefined) return; // avoid deleting the camera or scene - - editor.execute(new RemoveObjectCommand(object)); - - }); - options.add(option); - - // Minify shaders - - var option = new UI.Row(); - option.setClass('option'); - option.setTextContent('清除着色'); - option.onClick(function () { - - var root = editor.selected || editor.scene; - - var errors = []; - var nMaterialsChanged = 0; - - var path = []; - - function getPath(object) { - - path.length = 0; - - var parent = object.parent; - if (parent !== undefined) getPath(parent); - - path.push(object.name || object.uuid); - - return path; - - } - - var cmds = []; - root.traverse(function (object) { - - var material = object.material; - - if (material instanceof THREE.ShaderMaterial) { - - try { - - var shader = glslprep.minifyGlsl([ - material.vertexShader, material.fragmentShader]); - - cmds.push(new SetMaterialValueCommand(object, 'vertexShader', shader[0])); - cmds.push(new SetMaterialValueCommand(object, 'fragmentShader', shader[1])); - - ++nMaterialsChanged; - - } catch (e) { - - var path = getPath(object).join("/"); - - if (e instanceof glslprep.SyntaxError) - - errors.push(path + ":" + - e.line + ":" + e.column + ": " + e.message); - - else { - - errors.push(path + - ": 未预料到的错误(详情请见控制台)。"); - - console.error(e.stack || e); - - } - - } - - } - - }); - - if (nMaterialsChanged > 0) { - - editor.execute(new MultiCmdsCommand(cmds), 'Minify Shaders'); - - } - - window.alert(nMaterialsChanged + - "材质已经改变。\n" + errors.join("\n")); - - }); - options.add(option); - - - return container; - -}; - -export default EditMenu; \ No newline at end of file diff --git a/src/menu/Menubar.js b/src/menu/Menubar.js index 09f1aa39..3ea6899c 100644 --- a/src/menu/Menubar.js +++ b/src/menu/Menubar.js @@ -6,7 +6,6 @@ import ExampleMenu from './ExampleMenu'; import HelpMenu from './HelpMenu'; import StatusMenu from './StatusMenu'; import ViewMenu from './ViewMenu'; -import UI from '../ui/UI'; import UI2 from '../ui2/UI'; /** @@ -20,16 +19,19 @@ function Menubar(app) { this.data = [{ text: '场景', children: [{ + id: 'mNewScene', text: '新建', onClick: function () { app.call('mNewScene'); } }, { + id: 'mLoadScene', text: '载入', onClick: function () { app.call('mLoadScene'); } }, { + id: 'mSaveScene', text: '保存', onClick: function () { app.call('mSaveScene'); @@ -37,6 +39,7 @@ function Menubar(app) { }, { text: '-' }, { + id: 'mPublishScene', text: '发布', onClick: function () { app.call('mPublishScene'); @@ -45,16 +48,19 @@ function Menubar(app) { }, { text: '编辑', children: [{ + id: 'mUndo', text: '撤销(Ctrl+Z)', onClick: function () { app.call('mUndo'); } }, { + id: 'mRedo', text: '重做(Ctrl+Shift+Z)', onClick: function () { app.call('mRedo'); } }, { + id: 'mClearHistory', text: '清空历史记录', onClick: function () { app.call('mClearHistory'); @@ -62,16 +68,19 @@ function Menubar(app) { }, { text: '-' }, { + id: 'mClone', text: '复制', onClick: function () { app.call('mClone'); } }, { + id: 'mDelete', text: '删除(Del)', onClick: function () { app.call('mDelete'); } }, { + id: 'mMinifyShader', text: '删除着色器', onClick: function () { app.call('mMinifyShader'); @@ -80,6 +89,7 @@ function Menubar(app) { }, { text: '添加', children: [{ + id: 'mAddGroup', text: '组', onClick: function () { app.call('mAddGroup'); @@ -87,56 +97,67 @@ function Menubar(app) { }, { text: '-' }, { + id: 'mAddPlane', text: '平板', onClick: function () { app.call('mAddPlane'); } }, { + id: 'mAddBox', text: '正方体', onClick: function () { app.call('mAddBox'); } }, { + id: 'mAddCircle', text: '圆', onClick: function () { app.call('mAddCircle'); } }, { + id: 'mAddCylinder', text: '圆柱体', onClick: function () { app.call('mAddCylinder'); } }, { + id: 'mAddSphere', text: '球体', onClick: function () { app.call('mAddSphere'); } }, { + id: 'mAddIcosahedron', text: '二十面体', onClick: function () { app.call('mAddIcosahedron'); } }, { + id: 'mAddTorus', text: '轮胎', onClick: function () { app.call('mAddTorus'); } }, { + id: 'mAddTorusKnot', text: '扭结', onClick: function () { app.call('mAddTorusKnot'); } }, { + id: 'mAddTeaport', text: '茶壶', onClick: function () { app.call('mAddTeaport'); } }, { + id: 'mAddLathe', text: '花瓶', onClick: function () { app.call('mAddLathe'); } }, { + id: 'mAddSprite', text: '精灵', onClick: function () { app.call('mAddSprite'); @@ -144,26 +165,31 @@ function Menubar(app) { }, { text: '-' }, { + id: 'mAddPointLight', text: '点光源', onClick: function () { app.call('mAddPointLight'); } }, { + id: 'mAddSpotLight', text: '聚光灯', onClick: function () { app.call('mAddSpotLight'); } }, { + id: 'mAddDirectionalLight', text: '平行光源', onClick: function () { app.call('mAddDirectionalLight'); } }, { + id: 'mAddHemisphereLight', text: '半球光', onClick: function () { app.call('mAddHemisphereLight'); } }, { + id: 'mAddAmbientLight', text: '环境光', onClick: function () { app.call('mAddAmbientLight'); @@ -171,6 +197,7 @@ function Menubar(app) { }, { text: '-' }, { + id: 'mAddPerspectiveCamera', text: '透视相机', onClick: function () { app.call('mAddPerspectiveCamera'); @@ -179,39 +206,46 @@ function Menubar(app) { }, { text: '资源', children: [{ + id: 'mImportAsset', text: '导入', onClick: function () { - app.call('mNewScene'); + app.call('mImportAsset'); } }, { text: '-' }, { + id: 'mExportGeometry', text: '导出Geometry', onClick: function () { app.call('mExportGeometry'); } }, { + id: 'mExportObject', text: '导出Object', onClick: function () { app.call('mExportObject'); } }, { + id: 'mExportScene', text: '导出场景', onClick: function () { app.call('mExportScene'); } }, { + id: 'mExportOBJ', text: '导出OBJ', onClick: function () { app.call('mExportOBJ'); } }, { + id: 'mExportSTL', text: '导出STL', onClick: function () { app.call('mExportSTL'); } }] }, { + id: 'mPlay', text: '启动', onClick: function () { app.call('mPlay'); @@ -219,6 +253,7 @@ function Menubar(app) { }, { text: '视图', children: [{ + id: 'mVRMode', text: 'VR模式', onClick: function () { app.call('mVRMode'); @@ -227,21 +262,25 @@ function Menubar(app) { }, { text: '示例', children: [{ + id: 'mArkanoid', text: '打砖块', onClick: function () { app.call('mArkanoid'); } }, { + id: 'mCamera', text: '相机', onClick: function () { app.call('mCamera'); } }, { + id: 'mParticles', text: '粒子', onClick: function () { app.call('mParticles'); } }, { + id: 'mPong', text: '乒乓球', onClick: function () { app.call('mPong'); @@ -250,11 +289,13 @@ function Menubar(app) { }, { text: '帮助', children: [{ + id: 'mSourceCode', text: '源码', onClick: function () { app.call('mSourceCode'); } }, { + id: 'mAbout', text: '关于', onClick: function () { app.call('mAbout'); @@ -277,6 +318,7 @@ function Menubar(app) { // 菜单标题 var title = new UI2.Panel({ + id: n.id, cls: 'title', html: n.text }); @@ -295,6 +337,7 @@ function Menubar(app) { options.add(hr); } else { // 其他文字 var option = new UI2.Panel({ + id: m.id, cls: 'option', html: m.text }); @@ -302,7 +345,7 @@ function Menubar(app) { // 菜单子项click事件 if (typeof (m.onClick) === 'function') { - option.onClick = m.onClick.bind(_this); + option.onClick = m.onClick; // this是具体菜单对应的Panel } } }); @@ -310,31 +353,13 @@ function Menubar(app) { // 主菜单click事件 if (typeof (n.onClick) === 'function') { - menu.onClick = n.onClick.bind(_this); + menu.onClick = n.onClick; // this是具体菜单对应的Panel } _this.dom.add(menu); }); this.dom.render(); - - // var editor = this.app.editor; - - // var container = new UI.Panel(); - // container.setId('menubar'); - - // container.add(new FileMenu(editor)); - // container.add(new EditMenu(editor)); - // container.add(new AddMenu(editor)); - // container.add(new AssetMenu(editor)); - // container.add(new PlayMenu(editor)); - // container.add(new ViewMenu(editor)); - // container.add(new ExampleMenu(editor)); - // container.add(new HelpMenu(editor)); - - // container.add(new StatusMenu(editor)); - - // return container; }; export default Menubar; \ No newline at end of file diff --git a/src/ui2/Panel.js b/src/ui2/Panel.js index 6fb02a91..02685911 100644 --- a/src/ui2/Panel.js +++ b/src/ui2/Panel.js @@ -1,6 +1,8 @@ import Control from './Control'; import Container from './Container'; +var ID = -1; + /** * 面板 * @param {*} options @@ -8,7 +10,7 @@ import Container from './Container'; function Panel(options) { Container.call(this, options); this.cls = options.cls || 'Panel'; - this.id = options.id || null; + this.id = options.id || 'Panel' + ID--; this.html = options.html || null; this.onClick = options.onClick || null; };