From 4254d38cddbb3cc18d0807d7180a4f8903a9985d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:40:21 -0800 Subject: [PATCH 01/10] Update buttons to grid tool --- examples/html/gridControls.html | 145 +++++++++++++------------------- examples/html/style.css | 95 +++++++++++++++++++++ examples/libraries/gridTool.js | 9 ++ 3 files changed, 163 insertions(+), 86 deletions(-) create mode 100644 examples/html/style.css diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html index e7bf1cdf8c..4cb935e600 100644 --- a/examples/html/gridControls.html +++ b/examples/html/gridControls.html @@ -1,5 +1,6 @@ + -
-
+
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
+
+ + + + +
+ +
+ + +
+ +
+ + + +
+
+ + +
diff --git a/examples/html/style.css b/examples/html/style.css new file mode 100644 index 0000000000..1625fd094f --- /dev/null +++ b/examples/html/style.css @@ -0,0 +1,95 @@ +* { +} + +body { + margin: 0; + padding: 0; + + background-color: #efefef; + font-family: Sans-Serif; + font-size: 12px; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +input { + line-height: 2; +} + +.input-left { + display: inline-block; + width: 20px; +} + +.color-box { + display: inline-block; + width: 20px; + height: 20px; + border: 1px solid black; + margin: 2px; + cursor: pointer; +} + +.color-box.highlight { + width: 18px; + height: 18px; + border: 2px solid black; +} + +.section-header { + background: #AAA; + border-bottom: 1px solid #CCC; + background-color: #333333; + color: #999; + padding: 4px; +} + +.section-header label { + font-weight: bold; +} + +.multi-property-section { +} +.property-section { + display: block; + margin: 10 10; + height: 30px; +} + +.property-section label { + font-weight: bold; + vertical-align: middle; +} + +.property-section span { + float: right; +} + +.grid-section { + border-top: 1px solid #DDD; + background-color: #efefef; +} + +input[type=button] { + cursor: pointer; + background-color: #608e96; + border-color: #608e96; + border-radius: 5px; + padding: 5px 10px; + border: 0; + color: #fff; + font-weight: bold; + margin: 0 2px; + margin-top: 5px; + font-size: .9em; +} + +input.coord { + width: 6em; + height: 2em; +} diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 34e25d6733..04547a6918 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -174,6 +174,15 @@ GridTool = function(opts) { for (var i = 0; i < listeners.length; i++) { listeners[i](data); } + } else if (data.type == "action") { + var action = data.action; + if (action == "moveToAvatar") { + grid.setPosition(MyAvatar.position); + } else if (action == "moveToSelection") { + var newPosition = selectionManager.worldPosition; + newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); + grid.setPosition(newPosition); + } } }); From 49563dbff7a9c90844e8c837de015f38649a880d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:41:51 -0800 Subject: [PATCH 02/10] Add entityProperties tool window --- examples/html/entityProperties.html | 561 ++++++++++++++++++++++ examples/libraries/entitySelectionTool.js | 15 +- examples/newEditEntities.js | 35 +- 3 files changed, 605 insertions(+), 6 deletions(-) create mode 100644 examples/html/entityProperties.html diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html new file mode 100644 index 0000000000..408e83198f --- /dev/null +++ b/examples/html/entityProperties.html @@ -0,0 +1,561 @@ + + + + + + +
+ +
+
+
+ + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + X + Y + Z + +
+ +
+ + + X + Y + Z + +
+ +
+ + + + +
+
+ + + + +
+
+ + + + +
+ +
+ + + X + Y + Z + +
+
+ + + + +
+
+ + + Pitch + Roll + Yaw + +
+
+ + + + +
+ +
+ + + X + Y + Z + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ + +
+
+ + + Red + Green + Blue + +
+
+ + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + +
+
+ + + + +
+
+ + + Red + Green + Blue + +
+
+ + + Red + Green + Blue + +
+
+ + + Red + Green + Blue + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+
+ + + diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 22f75cb187..6733ccaf39 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -23,12 +23,13 @@ SelectionManager = (function() { that.savedProperties = {}; - that.eventListener = null; that.selections = []; // These are selections that don't have a known ID yet that.pendingSelections = []; var pendingSelectionTimer = null; + var listeners = []; + that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.localPosition = { x: 0, y: 0, z: 0 }; that.localDimensions = { x: 0, y: 0, z: 0 }; @@ -46,8 +47,8 @@ SelectionManager = (function() { } }; - that.setEventListener = function(func) { - that.eventListener = func; + that.addEventListener = function(func) { + listeners.push(func); }; that.hasSelection = function() { @@ -187,8 +188,12 @@ SelectionManager = (function() { SelectionDisplay.setSpaceMode(SPACE_WORLD); } - if (that.eventListener) { - that.eventListener(); + for (var i = 0; i < listeners.length; i++) { + try { + listeners[i](); + } catch (e) { + print("got exception"); + } } }; diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 68e0d0c146..f5af558fa1 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -39,7 +39,7 @@ Script.include("libraries/gridTool.js"); var grid = Grid(); gridTool = GridTool({ horizontalGrid: grid }); -selectionManager.setEventListener(selectionDisplay.updateHandles); +selectionManager.addEventListener(selectionDisplay.updateHandles); var windowDimensions = Controller.getViewportDimensions(); var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; @@ -908,3 +908,36 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) { } UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); } + +PropertiesTool = function(opts) { + var that = {}; + + var url = Script.resolvePath('html/entityProperties.html'); + var webView = new WebWindow('Entity Properties', url, 200, 280); + + webView.setVisible(true); + + selectionManager.addEventListener(function() { + data = { + type: 'update', + }; + if (selectionManager.hasSelection()) { + data.properties = Entities.getEntityProperties(selectionManager.selections[0]); + } + webView.eventBridge.emitScriptEvent(JSON.stringify(data)); + }); + + webView.eventBridge.webEventReceived.connect(function(data) { + print(data); + data = JSON.parse(data); + if (data.type == "update") { + Entities.editEntity(selectionManager.selections[0], data.properties); + selectionManager._update(); + } + }); + + return that; +}; + +propertiesTool = PropertiesTool(); + From 55612cc5962f6c2b30445b1a6fdbe6938d4d6f47 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:46:20 -0800 Subject: [PATCH 03/10] Add title to WebWindowClass --- examples/libraries/gridTool.js | 2 +- interface/src/scripting/WebWindowClass.cpp | 8 +++++--- interface/src/scripting/WebWindowClass.h | 2 +- interface/src/scripting/WindowScriptingInterface.cpp | 4 ++-- interface/src/scripting/WindowScriptingInterface.h | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 04547a6918..9945fe3e98 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -159,7 +159,7 @@ GridTool = function(opts) { var listeners = []; var url = Script.resolvePath('html/gridControls.html'); - var webView = new WebWindow(url, 200, 280); + var webView = new WebWindow('Grid', url, 200, 280); horizontalGrid.addListener(function(data) { webView.eventBridge.emitScriptEvent(JSON.stringify(data)); diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index d280d8eecf..01a7983098 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -28,7 +28,8 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) { emit scriptEventReceived(data); } -WebWindowClass::WebWindowClass(const QString& url, int width, int height) + +WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height) : QObject(NULL), _window(new QWidget(NULL, Qt::Tool)), _eventBridge(new ScriptEventBridge(this)) { @@ -59,8 +60,9 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* QMetaObject::invokeMethod(WindowScriptingInterface::getInstance(), "doCreateWebWindow", Qt::BlockingQueuedConnection, Q_RETURN_ARG(WebWindowClass*, retVal), Q_ARG(const QString&, file), - Q_ARG(int, context->argument(1).toInteger()), - Q_ARG(int, context->argument(2).toInteger())); + Q_ARG(QString, context->argument(1).toString()), + Q_ARG(int, context->argument(2).toInteger()), + Q_ARG(int, context->argument(3).toInteger())); connect(engine, &QScriptEngine::destroyed, retVal, &WebWindowClass::deleteLater); diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index 7b77299774..928b8fb23b 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -34,7 +34,7 @@ class WebWindowClass : public QObject { Q_OBJECT Q_PROPERTY(QObject* eventBridge READ getEventBridge) public: - WebWindowClass(const QString& url, int width, int height); + WebWindowClass(const QString& title, const QString& url, int width, int height); ~WebWindowClass(); static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 8c2066f253..8a79cad6e1 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -34,8 +34,8 @@ WindowScriptingInterface::WindowScriptingInterface() : { } -WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& url, int width, int height) { - return new WebWindowClass(url, width, height); +WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) { + return new WebWindowClass(title, url, width, height); } QScriptValue WindowScriptingInterface::hasFocus() { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 5529d31efd..0b320f23a1 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -78,7 +78,7 @@ private slots: void nonBlockingFormAccepted() { _nonBlockingFormActive = false; _formResult = QDialog::Accepted; emit nonBlockingFormClosed(); } void nonBlockingFormRejected() { _nonBlockingFormActive = false; _formResult = QDialog::Rejected; emit nonBlockingFormClosed(); } - WebWindowClass* doCreateWebWindow(const QString& url, int width, int height); + WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); private: WindowScriptingInterface(); From 03f155bcd8d5f9405563cae5fd43bafa3f2b0779 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:47:02 -0800 Subject: [PATCH 04/10] Add tool window --- interface/src/Application.cpp | 4 ++++ interface/src/Application.h | 4 ++++ interface/src/Menu.cpp | 11 +++++++++++ interface/src/Menu.h | 2 ++ interface/src/scripting/WebWindowClass.cpp | 17 ++++++++++------- interface/src/scripting/WebWindowClass.h | 2 +- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b1c969b66f..3958011ba2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -370,6 +370,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // enable mouse tracking; otherwise, we only get drag events _glWidget->setMouseTracking(true); + _toolWindow = new QMainWindow(); + _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); + _toolWindow->setWindowTitle("Tools"); + // initialization continues in initializeGL when OpenGL context is ready // Tell our voxel edit sender about our known jurisdictions diff --git a/interface/src/Application.h b/interface/src/Application.h index eee2581e2e..a6f94f0ab5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -244,6 +244,8 @@ public: void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); } + QMainWindow* getToolWindow() { return _toolWindow ; } + GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } TextureCache* getTextureCache() { return &_textureCache; } @@ -457,6 +459,8 @@ private: MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features + QMainWindow* _toolWindow; + BandwidthMeter _bandwidthMeter; QThread* _nodeThread; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index cd074805b6..fd0db559ff 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -247,6 +247,12 @@ Menu::Menu() : _chatWindow = new ChatWindow(Application::getInstance()->getWindow()); #endif + addActionToQMenuAndActionHash(toolsMenu, + MenuOption::ToolWindow, + Qt::CTRL | Qt::ALT | Qt::Key_T, + this, + SLOT(toggleToolWindow())); + addActionToQMenuAndActionHash(toolsMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J, @@ -1461,6 +1467,11 @@ void Menu::toggleConsole() { _jsConsole->setVisible(!_jsConsole->isVisible()); } +void Menu::toggleToolWindow() { + QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + toolWindow->setVisible(!toolWindow->isVisible()); +} + void Menu::audioMuteToggled() { QAction *muteAction = _actionHash.value(MenuOption::MuteAudio); if (muteAction) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8af91ccae4..badd79759f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -224,6 +224,7 @@ private slots: void showScriptEditor(); void showChat(); void toggleConsole(); + void toggleToolWindow(); void toggleChat(); void audioMuteToggled(); void displayNameLocationResponse(const QString& errorString); @@ -491,6 +492,7 @@ namespace MenuOption { const QString StringHair = "String Hair"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString TestPing = "Test Ping"; + const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; const QString UploadAttachment = "Upload Attachment Model"; diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 01a7983098..1645fe2f56 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -11,9 +11,13 @@ #include #include +#include +#include #include #include +#include +#include "Application.h" #include "WindowScriptingInterface.h" #include "WebWindowClass.h" @@ -31,18 +35,17 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) { WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height) : QObject(NULL), - _window(new QWidget(NULL, Qt::Tool)), _eventBridge(new ScriptEventBridge(this)) { + QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + + _window = new QDockWidget(title, toolWindow); QWebView* webView = new QWebView(_window); webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge); webView->setUrl(url); - QVBoxLayout* layout = new QVBoxLayout(_window); - _window->setLayout(layout); - layout->addWidget(webView); - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - _window->setGeometry(0, 0, width, height); + _window->setWidget(webView); + + toolWindow->addDockWidget(Qt::RightDockWidgetArea, _window); connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater); } diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index 928b8fb23b..c37b7aea48 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -44,7 +44,7 @@ public slots: ScriptEventBridge* getEventBridge() const { return _eventBridge; } private: - QWidget* _window; + QDockWidget* _window; ScriptEventBridge* _eventBridge; }; From a6f027e33aadc9bc22cd1ac74b2f6003ebd7b354 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 18:31:32 -0800 Subject: [PATCH 05/10] Fix entity edit grid not hiding when disabling tools --- examples/libraries/gridTool.js | 8 +++++++- examples/newEditEntities.js | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 9945fe3e98..d8b84babf9 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -31,6 +31,7 @@ Grid = function(opts) { that.getMajorIncrement = function() { return minorGridSpacing * majorGridEvery; }; that.visible = false; + that.enabled = false; that.getOrigin = function() { return origin; @@ -38,6 +39,11 @@ Grid = function(opts) { that.getSnapToGrid = function() { return snapToGrid; }; + that.setEnabled = function(enabled) { + that.enabled = enabled; + updateGrid(); + } + that.setVisible = function(visible, noUpdate) { that.visible = visible; updateGrid(); @@ -127,7 +133,7 @@ Grid = function(opts) { function updateGrid() { Overlays.editOverlay(gridOverlay, { position: { x: origin.y, y: origin.y, z: -origin.y }, - visible: that.visible, + visible: that.visible && that.enabled, minorGridWidth: minorGridSpacing, majorGridEvery: majorGridEvery, color: gridColor, diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 8a2c8a636d..0b8eebfee5 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -272,11 +272,13 @@ var toolBar = (function () { isActive = !isActive; if (!isActive) { gridTool.setVisible(false); + grid.setEnabled(false); selectionManager.clearSelections(); cameraManager.disable(); } else { cameraManager.enable(); gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); + grid.setEnabled(true); } return true; } From 3658d65028c57945cef9d6376f3814d90fe24a02 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 20:02:19 -0800 Subject: [PATCH 06/10] Remove grid tool from menu --- examples/newEditEntities.js | 25 ++++++++++------------ interface/src/scripting/WebWindowClass.cpp | 13 +++++------ interface/src/scripting/WebWindowClass.h | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 0b8eebfee5..cc3c0fceda 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -55,13 +55,11 @@ var wantEntityGlow = false; var SPAWN_DISTANCE = 1; var DEFAULT_DIMENSION = 0.20; -var MENU_GRID_TOOL_ENABLED = 'Grid Tool'; var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_GRID_TOOL_ENABLED = 'GridToolEnabled'; var modelURLs = [ HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", @@ -273,12 +271,14 @@ var toolBar = (function () { if (!isActive) { gridTool.setVisible(false); grid.setEnabled(false); + propertiesTool.setVisible(false); selectionManager.clearSelections(); cameraManager.disable(); } else { cameraManager.enable(); - gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); + gridTool.setVisible(true); grid.setEnabled(true); + propertiesTool.setVisible(true); } return true; } @@ -610,10 +610,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true }); - Menu.addMenuItem({ menuName: "View", menuItemName: MENU_GRID_TOOL_ENABLED, afterItem: "Edit Entities Help...", isCheckable: true, - isChecked: Settings.getValue(SETTING_GRID_TOOL_ENABLED) == 'true'}); - Menu.addMenuItem({ menuName: "View", menuItemName: MENU_INSPECT_TOOL_ENABLED, afterItem: MENU_GRID_TOOL_ENABLED, - isCheckable: true, isChecked: Settings.getValue(SETTING_INSPECT_TOOL_ENABLED) == "true" }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); } @@ -638,8 +634,6 @@ function cleanupModelMenus() { Menu.removeMenuItem("File", "Import Models"); Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems"); - Settings.setValue(SETTING_GRID_TOOL_ENABLED, Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); - Menu.removeMenuItem("View", MENU_GRID_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); } @@ -751,10 +745,6 @@ function handeMenuEvent(menuItem) { } } else if (menuItem == "Import Models") { modelImporter.doImport(); - } else if (menuItem == MENU_GRID_TOOL_ENABLED) { - if (isActive) { - gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); - } } tooltip.show(false); } @@ -920,7 +910,14 @@ PropertiesTool = function(opts) { var url = Script.resolvePath('html/entityProperties.html'); var webView = new WebWindow('Entity Properties', url, 200, 280); - webView.setVisible(true); + var visible = false; + + webView.setVisible(visible); + + that.setVisible = function(newVisible) { + visible = newVisible; + webView.setVisible(visible); + }; selectionManager.addEventListener(function() { data = { diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 1645fe2f56..7f11dbe580 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -39,22 +39,23 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); - _window = new QDockWidget(title, toolWindow); - QWebView* webView = new QWebView(_window); + _dockWidget = new QDockWidget(title, toolWindow); + _dockWidget->setFeatures(QDockWidget::DockWidgetMovable); + QWebView* webView = new QWebView(_dockWidget); webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge); webView->setUrl(url); - _window->setWidget(webView); + _dockWidget->setWidget(webView); - toolWindow->addDockWidget(Qt::RightDockWidgetArea, _window); + toolWindow->addDockWidget(Qt::RightDockWidgetArea, _dockWidget); - connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater); + connect(this, &WebWindowClass::destroyed, _dockWidget, &QWidget::deleteLater); } WebWindowClass::~WebWindowClass() { } void WebWindowClass::setVisible(bool visible) { - QMetaObject::invokeMethod(_window, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); + QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); } QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) { diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index c37b7aea48..ae0d14ae06 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -44,7 +44,7 @@ public slots: ScriptEventBridge* getEventBridge() const { return _eventBridge; } private: - QDockWidget* _window; + QDockWidget* _dockWidget; ScriptEventBridge* _eventBridge; }; From 20fdd6d8117405296b02e7a383630dc95aab0ae4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 14 Nov 2014 10:31:30 -0800 Subject: [PATCH 07/10] Disable model overlay properties example It causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() --- examples/overlaysExample.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 3ab70a0562..0d47f7ca64 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -194,20 +194,23 @@ print("Cube overlay color =\n" + "green: " + cubeColor.green + "\n" + "blue: " + cubeColor.blue ); -var modelOverlayProperties = { - textures: { - filename1: "http://url1", - filename2: "http://url2" - } -} -var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); -var textures = Overlays.getProperty(modelOverlay, "textures"); -var textureValues = ""; -for (key in textures) { - textureValues += "\n" + key + ": " + textures[key]; -} -print("Model overlay textures =" + textureValues); -Overlays.deleteOverlay(modelOverlay); + +// This model overlay example causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() +//var modelOverlayProperties = { +// textures: { +// filename1: HIFI_PUBLIC_BUCKET + "images/testing-swatches.svg", +// filename2: HIFI_PUBLIC_BUCKET + "images/hifi-interface-tools.svg" +// } +//} +//var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); +//var textures = Overlays.getProperty(modelOverlay, "textures"); +//var textureValues = ""; +//for (key in textures) { +// textureValues += "\n" + key + ": " + textures[key]; +//} +//print("Model overlay textures =" + textureValues); +//Overlays.deleteOverlay(modelOverlay); + print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined // When our script shuts down, we should clean up all of our overlays From 86284036f1c6d8054c97bef7b43c9ca39b3b2d6a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Nov 2014 10:35:13 -0800 Subject: [PATCH 08/10] put back timestamp in log --- libraries/shared/src/LogHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index dfac02b912..a13f3a9dad 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -119,6 +119,8 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont char dateString[100]; strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); + prefixString.append(QString(" [%1]").arg(dateString)); + if (_shouldOutputPID) { prefixString.append(QString(" [%1").arg(getpid())); From 903cd05ff83eb1f79c80829ef556ce28788d1b88 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Nov 2014 10:39:45 -0800 Subject: [PATCH 09/10] put newlines back in interface log --- interface/src/Application.cpp | 2 +- interface/src/FileLogger.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 605bd62118..5e158352bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -124,7 +124,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); if (!logMessage.isEmpty()) { - Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage)); + Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n")); } } diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 505cb6a029..4808842036 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -41,7 +41,7 @@ void FileLogger::addMessage(QString message) { QFile file(_fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream out(&file); - out << message << "\n"; + out << message; } } From 604b1b620b628fcb2c9b24699cbe999b79bca0bf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 14 Nov 2014 10:52:08 -0800 Subject: [PATCH 10/10] Move dock window to ToolWindow --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 5 +- interface/src/scripting/WebWindowClass.cpp | 6 +- interface/src/ui/ToolWindow.cpp | 82 ++++++++++++++++++++++ interface/src/ui/ToolWindow.h | 40 +++++++++++ 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 interface/src/ui/ToolWindow.cpp create mode 100644 interface/src/ui/ToolWindow.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eefc41cf24..1664cc700e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -373,7 +373,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // enable mouse tracking; otherwise, we only get drag events _glWidget->setMouseTracking(true); - _toolWindow = new QMainWindow(); + _toolWindow = new ToolWindow(); _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); diff --git a/interface/src/Application.h b/interface/src/Application.h index f2a6615cbf..d31833897f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -82,6 +82,7 @@ #include "ui/overlays/Overlays.h" #include "ui/ApplicationOverlay.h" #include "ui/RunningScriptsWidget.h" +#include "ui/ToolWindow.h" #include "ui/VoxelImportDialog.h" #include "voxels/VoxelFade.h" #include "voxels/VoxelHideShowThread.h" @@ -246,7 +247,7 @@ public: void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); } - QMainWindow* getToolWindow() { return _toolWindow ; } + ToolWindow* getToolWindow() { return _toolWindow ; } GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } @@ -461,7 +462,7 @@ private: MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features - QMainWindow* _toolWindow; + ToolWindow* _toolWindow; BandwidthMeter _bandwidthMeter; diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 7f11dbe580..cc6f4fbfff 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -37,7 +37,7 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid : QObject(NULL), _eventBridge(new ScriptEventBridge(this)) { - QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + ToolWindow* toolWindow = Application::getInstance()->getToolWindow(); _dockWidget = new QDockWidget(title, toolWindow); _dockWidget->setFeatures(QDockWidget::DockWidgetMovable); @@ -55,6 +55,10 @@ WebWindowClass::~WebWindowClass() { } void WebWindowClass::setVisible(bool visible) { + if (visible) { + QMetaObject::invokeMethod( + Application::getInstance()->getToolWindow(), "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); + } QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); } diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp new file mode 100644 index 0000000000..1375ff1ea5 --- /dev/null +++ b/interface/src/ui/ToolWindow.cpp @@ -0,0 +1,82 @@ +// +// ToolWindow.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 11/13/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Application.h" +#include "ToolWindow.h" +#include "UIUtil.h" + +const int DEFAULT_WIDTH = 300; + +ToolWindow::ToolWindow(QWidget* parent) : + QMainWindow(parent), + _hasShown(false), + _lastGeometry() { +} + +bool ToolWindow::event(QEvent* event) { + QEvent::Type type = event->type(); + if (type == QEvent::Show) { + if (!_hasShown) { + _hasShown = true; + + QMainWindow* mainWindow = Application::getInstance()->getWindow(); + QRect mainGeometry = mainWindow->geometry(); + + int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); + int menuBarHeight = Menu::getInstance()->geometry().height(); + int topMargin = titleBarHeight + menuBarHeight; + + _lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin, + DEFAULT_WIDTH, mainGeometry.height() - topMargin); + } + setGeometry(_lastGeometry); + return true; + } else if (type == QEvent::Hide) { + _lastGeometry = geometry(); + return true; + } + + return QMainWindow::event(event); +} + +void ToolWindow::onChildVisibilityUpdated(bool visible) { + if (visible) { + setVisible(true); + } else { + bool hasVisible = false; + QList dockWidgets = findChildren(); + for (int i = 0; i < dockWidgets.count(); i++) { + if (dockWidgets[i]->isVisible()) { + hasVisible = true; + break; + } + } + setVisible(hasVisible); + } +} + +void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) { + QMainWindow::addDockWidget(area, dockWidget); + + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} + +void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation) { + QMainWindow::addDockWidget(area, dockWidget, orientation); + + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} + +void ToolWindow::removeDockWidget(QDockWidget* dockWidget) { + QMainWindow::removeDockWidget(dockWidget); + + disconnect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} diff --git a/interface/src/ui/ToolWindow.h b/interface/src/ui/ToolWindow.h new file mode 100644 index 0000000000..87b94d46df --- /dev/null +++ b/interface/src/ui/ToolWindow.h @@ -0,0 +1,40 @@ +// +// ToolWindow.h +// interface/src/ui +// +// Created by Ryan Huffman on 11/13/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ToolWindow_h +#define hifi_ToolWindow_h + +#include +#include +#include +#include +#include + +class ToolWindow : public QMainWindow { + Q_OBJECT +public: + ToolWindow(QWidget* parent = NULL); + + virtual bool event(QEvent* event); + virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget); + virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation); + virtual void removeDockWidget(QDockWidget* dockWidget); + +public slots: + void onChildVisibilityUpdated(bool visible); + + +private: + bool _hasShown; + QRect _lastGeometry; +}; + +#endif // hifi_ToolWindow_h