From d14d5f3d2952fd1be1043cdefcdc52db2bf46100 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 14 Apr 2015 15:55:42 -0700 Subject: [PATCH 01/74] Working on new-UI implementations of address bar and login --- CMakeLists.txt | 9 + interface/CMakeLists.txt | 2 +- interface/resources/qml/AddressBarDialog.qml | 84 +++++ interface/resources/qml/CustomBorder.qml | 12 + interface/resources/qml/CustomButton.qml | 23 ++ interface/resources/qml/CustomDialog.qml | 98 ++++++ interface/resources/qml/CustomText.qml | 7 + interface/resources/qml/CustomTextArea.qml | 10 + interface/resources/qml/CustomTextEdit.qml | 7 + interface/resources/qml/CustomTextInput.qml | 34 ++ interface/resources/qml/Icon.qml | 8 + interface/resources/qml/IconControl.qml | 24 ++ interface/resources/qml/LoginDialog.qml | 191 ++++++++++ interface/resources/qml/Root.qml | 14 + interface/resources/qml/componentCreation.js | 27 ++ interface/resources/qml/hifiConstants.js | 4 + interface/src/Application.cpp | 112 +++++- interface/src/Application.h | 3 + interface/src/GLCanvas.cpp | 71 ++-- interface/src/GLCanvas.h | 15 - interface/src/Menu.cpp | 50 ++- interface/src/devices/OculusManager.cpp | 15 +- interface/src/devices/OculusManager.h | 1 + interface/src/devices/TV3DManager.cpp | 2 +- interface/src/main.cpp | 1 + interface/src/ui/AddressBarDialog.cpp | 142 ++------ interface/src/ui/AddressBarDialog.h | 42 +-- interface/src/ui/ApplicationOverlay.cpp | 118 ++++--- interface/src/ui/ApplicationOverlay.h | 8 +- interface/src/ui/DialogsManager.cpp | 16 +- interface/src/ui/FramelessDialog.cpp | 166 --------- interface/src/ui/FramelessDialog.h | 50 --- interface/src/ui/LoginDialog.cpp | 148 +++----- interface/src/ui/LoginDialog.h | 49 +-- libraries/render-utils/CMakeLists.txt | 2 +- libraries/render-utils/src/FboCache.cpp | 98 ++++++ libraries/render-utils/src/FboCache.h | 50 +++ .../render-utils/src/OffscreenGlCanvas.cpp | 43 +++ .../render-utils/src/OffscreenGlCanvas.h | 31 ++ libraries/render-utils/src/OffscreenUi.cpp | 325 ++++++++++++++++++ libraries/render-utils/src/OffscreenUi.h | 136 ++++++++ libraries/render-utils/src/RenderUtil.h | 50 +++ libraries/shared/src/GLMHelpers.h | 11 + libraries/shared/src/ThreadHelpers.h | 13 + tests/render-utils/src/main.cpp | 250 +++++++++----- 45 files changed, 1844 insertions(+), 728 deletions(-) create mode 100644 interface/resources/qml/AddressBarDialog.qml create mode 100644 interface/resources/qml/CustomBorder.qml create mode 100644 interface/resources/qml/CustomButton.qml create mode 100644 interface/resources/qml/CustomDialog.qml create mode 100644 interface/resources/qml/CustomText.qml create mode 100644 interface/resources/qml/CustomTextArea.qml create mode 100644 interface/resources/qml/CustomTextEdit.qml create mode 100644 interface/resources/qml/CustomTextInput.qml create mode 100644 interface/resources/qml/Icon.qml create mode 100644 interface/resources/qml/IconControl.qml create mode 100644 interface/resources/qml/LoginDialog.qml create mode 100644 interface/resources/qml/Root.qml create mode 100644 interface/resources/qml/componentCreation.js create mode 100644 interface/resources/qml/hifiConstants.js delete mode 100644 interface/src/ui/FramelessDialog.cpp delete mode 100644 interface/src/ui/FramelessDialog.h create mode 100644 libraries/render-utils/src/FboCache.cpp create mode 100644 libraries/render-utils/src/FboCache.h create mode 100644 libraries/render-utils/src/OffscreenGlCanvas.cpp create mode 100644 libraries/render-utils/src/OffscreenGlCanvas.h create mode 100644 libraries/render-utils/src/OffscreenUi.cpp create mode 100644 libraries/render-utils/src/OffscreenUi.h create mode 100644 libraries/shared/src/ThreadHelpers.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 81d532fbe2..d27774e169 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,8 +92,17 @@ else () if (NOT QT_CMAKE_PREFIX_PATH) set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) endif () + if (NOT QT_CMAKE_PREFIX_PATH) + get_filename_component(QT_CMAKE_PREFIX_PATH "${Qt5_DIR}/.." REALPATH) + endif () endif () +if (WIN32) + if (NOT EXISTS ${QT_CMAKE_PREFIX_PATH}) + message(FATAL_ERROR "Could not determine QT_CMAKE_PREFIX_PATH.") + endif () +endif() + # figure out where the qt dir is get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f4f390607b..5d2fe5ae38 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -54,7 +54,7 @@ else () list(REMOVE_ITEM INTERFACE_SRCS ${SPEECHRECOGNIZER_CPP}) endif () -find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Script Svg WebKitWidgets) +find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg WebKitWidgets) # grab the ui files in resources/ui file (GLOB_RECURSE QT_UI_FILES ui/*.ui) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml new file mode 100644 index 0000000000..df06fabbe6 --- /dev/null +++ b/interface/resources/qml/AddressBarDialog.qml @@ -0,0 +1,84 @@ +import Hifi 1.0 +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Controls.Styles 1.3 + +AddressBarDialog { + id: addressBarDialog + objectName: "AddressBarDialog" + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + height: 128 + width: 512 + + onVisibleChanged: { + if (!visible) { + reset(); + } else { + addressLine.focus = true + addressLine.forceActiveFocus() + } + } + + Component.onCompleted: { + addressLine.focus = true + addressLine.forceActiveFocus() + } + + function reset() { + addressLine.text = "" + goButton.source = "../images/address-bar-submit.svg" + } + + CustomDialog { + id: dialog + anchors.fill: parent + title: "Go to..." + + // The client area + Item { + id: item1 + anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin + + CustomBorder { + height: 64 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.right: goButton.left + anchors.rightMargin: 8 + anchors.verticalCenter: parent.verticalCenter + CustomTextInput { + id: addressLine + anchors.fill: parent + helperText: "domain, location, @user, /x,y,z" + anchors.margins: 8 + onAccepted: { + addressBarDialog.loadAddress(addressLine.text) + } + } + } + + Image { + id: goButton + width: 32 + height: 32 + anchors.right: parent.right + anchors.rightMargin: 8 + source: "../images/address-bar-submit.svg" + anchors.verticalCenter: parent.verticalCenter + + MouseArea { + anchors.fill: parent + onClicked: { + parent.source = "../images/address-bar-submit-active.svg" + addressBarDialog.loadAddress(addressLine.text) + } + } + } + + } + } +} + diff --git a/interface/resources/qml/CustomBorder.qml b/interface/resources/qml/CustomBorder.qml new file mode 100644 index 0000000000..1bb30d1ebc --- /dev/null +++ b/interface/resources/qml/CustomBorder.qml @@ -0,0 +1,12 @@ +import QtQuick 2.3 + + +Rectangle { + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + property int margin: 5 + color: myPalette.window + border.color: myPalette.dark + border.width: 5 + radius: border.width * 2 +} + diff --git a/interface/resources/qml/CustomButton.qml b/interface/resources/qml/CustomButton.qml new file mode 100644 index 0000000000..ce57d7ce5e --- /dev/null +++ b/interface/resources/qml/CustomButton.qml @@ -0,0 +1,23 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Window 2.2 +import QtQuick.Controls.Styles 1.3 + +Button { + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + text: "Text" + width: 128 + height: 64 + style: ButtonStyle { + background: CustomBorder { + anchors.fill: parent + } + label: CustomText { + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: control.text + color: control.enabled ? myPalette.text : myPalette.dark + } + } +} diff --git a/interface/resources/qml/CustomDialog.qml b/interface/resources/qml/CustomDialog.qml new file mode 100644 index 0000000000..71f36b4108 --- /dev/null +++ b/interface/resources/qml/CustomDialog.qml @@ -0,0 +1,98 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.3 +import "hifiConstants.js" as HifiConstants + +Item { + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + + id: dialog + width: 256 + height: 256 + property rect clientArea: clientBorder + property int topMargin: dialog.height - clientBorder.height + 8 + property int margins: 8 + property string title + property int titleSize: titleBorder.height + 12 + property string frameColor: HifiConstants.color + property string backgroundColor: myPalette.window + property string headerBackgroundColor: myPalette.dark + + CustomBorder { + id: windowBorder + anchors.fill: parent + border.color: dialog.frameColor + color: dialog.backgroundColor + + CustomBorder { + id: titleBorder + height: 48 + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + border.color: dialog.frameColor + color: dialog.headerBackgroundColor + + CustomText { + id: titleText + color: "white" + text: dialog.title + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors.fill: parent + } + + MouseArea { + id: titleDrag + property int startX + property int startY + anchors.right: closeButton.left + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.top: parent.top + anchors.rightMargin: 4 + drag { + target: dialog.parent + minimumX: 0 + minimumY: 0 + maximumX: dialog.parent.parent.width - dialog.parent.width + maximumY: dialog.parent.parent.height - dialog.parent.height + } + } + Image { + id: closeButton + x: 360 + height: 16 + anchors.verticalCenter: parent.verticalCenter + width: 16 + anchors.right: parent.right + anchors.rightMargin: 12 + source: "../styles/close.svg" + MouseArea { + anchors.fill: parent + onClicked: { + dialog.parent.destroy() + } + } + } + + } // header border + + CustomBorder { + id: clientBorder + border.color: dialog.frameColor + color: "#00000000" + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + anchors.top: titleBorder.bottom + anchors.topMargin: -titleBorder.border.width + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + } // client border + } // window border +} diff --git a/interface/resources/qml/CustomText.qml b/interface/resources/qml/CustomText.qml new file mode 100644 index 0000000000..83229b783e --- /dev/null +++ b/interface/resources/qml/CustomText.qml @@ -0,0 +1,7 @@ +import QtQuick 2.3 + +Text { + font.family: "Helvetica" + font.pointSize: 18 +} + diff --git a/interface/resources/qml/CustomTextArea.qml b/interface/resources/qml/CustomTextArea.qml new file mode 100644 index 0000000000..cf3308e2b7 --- /dev/null +++ b/interface/resources/qml/CustomTextArea.qml @@ -0,0 +1,10 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +TextArea { + font.family: "Helvetica" + font.pointSize: 18 + backgroundVisible: false + readOnly: true +} + diff --git a/interface/resources/qml/CustomTextEdit.qml b/interface/resources/qml/CustomTextEdit.qml new file mode 100644 index 0000000000..0602bbc150 --- /dev/null +++ b/interface/resources/qml/CustomTextEdit.qml @@ -0,0 +1,7 @@ +import QtQuick 2.3 + +TextEdit { + font.family: "Helvetica" + font.pointSize: 18 +} + diff --git a/interface/resources/qml/CustomTextInput.qml b/interface/resources/qml/CustomTextInput.qml new file mode 100644 index 0000000000..a706187376 --- /dev/null +++ b/interface/resources/qml/CustomTextInput.qml @@ -0,0 +1,34 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +TextInput { + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + property string helperText: "" + font.family: "Helvetica" + font.pointSize: 18 + width: 256 + height: 64 + color: myPalette.text + clip: true + verticalAlignment: TextInput.AlignVCenter + + onTextChanged: { + if (text == "") { + helperText.visible = true; + } else { + helperText.visible = false; + } + } + + Text { + id: helperText + anchors.fill: parent + font.pointSize: parent.font.pointSize + font.family: "Helvetica" + verticalAlignment: TextInput.AlignVCenter + text: parent.helperText + color: myPalette.dark + clip: true + } +} + diff --git a/interface/resources/qml/Icon.qml b/interface/resources/qml/Icon.qml new file mode 100644 index 0000000000..0d60afb2b7 --- /dev/null +++ b/interface/resources/qml/Icon.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +Image { +id: icon +width: 64 +height: 64 +source: "file.svg" +} \ No newline at end of file diff --git a/interface/resources/qml/IconControl.qml b/interface/resources/qml/IconControl.qml new file mode 100644 index 0000000000..346865aacb --- /dev/null +++ b/interface/resources/qml/IconControl.qml @@ -0,0 +1,24 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Window 2.2 +import QtQuick.Controls.Styles 1.3 + +Button { + text: "Text" + style: ButtonStyle { + background: Item { anchors.fill: parent } + label: Text { + id: icon + width: height + verticalAlignment: Text.AlignVCenter + renderType: Text.NativeRendering + font.family: iconFont.name + font.pointSize: 18 + property alias unicode: icon.text + FontLoader { id: iconFont; source: "/fonts/fontawesome-webfont.ttf"; } + text: control.text + color: control.enabled ? "white" : "dimgray" + } + } +} + diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml new file mode 100644 index 0000000000..c306f4ed7e --- /dev/null +++ b/interface/resources/qml/LoginDialog.qml @@ -0,0 +1,191 @@ +import Hifi 1.0 +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Controls.Styles 1.3 +import "hifiConstants.js" as HifiConstants + +LoginDialog { + SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } + id: loginDialog + objectName: "LoginDialog" + height: 512 + width: 384 + + onVisibleChanged: { + if (!visible) { + reset() + } else { + username.forceActiveFocus() + } + } + + function reset() { + username.text = "" + password.text = "" + loginDialog.statusText = "" + } + + CustomDialog { + anchors.fill: parent + title: "Login" + Item { + id: item1 + anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin + Column { + anchors.topMargin: 8 + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.top: parent.top + spacing: 8 + + Image { + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + width: 64 + source: "../images/hifi-logo.svg" + } + + CustomBorder { + width: 304 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + CustomTextInput { + id: username + anchors.fill: parent + helperText: "Username or Email" + anchors.margins: 8 + KeyNavigation.tab: password + KeyNavigation.backtab: password + onAccepted: { + password.forceActiveFocus() + } + } + } + + CustomBorder { + width: 304 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + CustomTextInput { + id: password + anchors.fill: parent + echoMode: TextInput.Password + helperText: "Password" + anchors.margins: 8 + KeyNavigation.tab: username + KeyNavigation.backtab: username + onAccepted: { + if (username.text == "") { + username.forceActiveFocus() + } else { + loginDialog.login(username.text, password.text) + } + } + onFocusChanged: { + if (password.focus) { + password.selectAll() + } + } + } + } + + CustomText { + anchors.horizontalCenter: parent.horizontalCenter + textFormat: Text.StyledText + width: parent.width + height: 96 + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: loginDialog.statusText + } + } + + Column { + anchors.bottomMargin: 5 + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.bottom: parent.bottom + + Rectangle { + width: 192 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + color: HifiConstants.color + border.width: 0 + radius: 10 + + MouseArea { + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + onClicked: { + loginDialog.login(username.text, password.text) + } + } + + Row { + anchors.centerIn: parent + anchors.verticalCenter: parent.verticalCenter + spacing: 8 + Image { + id: loginIcon + height: 32 + width: 32 + source: "../images/login.svg" + } + CustomText { + text: "Login" + color: "white" + width: 64 + height: parent.height + } + } + + } + + CustomText { + width: parent.width + height: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text:"Create Account" + font.pointSize: 12 + font.bold: true + color: HifiConstants.color + + MouseArea { + anchors.fill: parent + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/signup") + } + } + } + + CustomText { + width: parent.width + height: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pointSize: 12 + text: "Recover Password" + color: HifiConstants.color + + MouseArea { + anchors.fill: parent + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") + } + } + } + } + } + } +} diff --git a/interface/resources/qml/Root.qml b/interface/resources/qml/Root.qml new file mode 100644 index 0000000000..f290a8b5ca --- /dev/null +++ b/interface/resources/qml/Root.qml @@ -0,0 +1,14 @@ +import QtQuick 2.3 +import "componentCreation.js" as Creator + + +Item { + id: root + width: 1280 + height: 720 + + function loadChild(url) { + Creator.createObject(root, url) + } +} + diff --git a/interface/resources/qml/componentCreation.js b/interface/resources/qml/componentCreation.js new file mode 100644 index 0000000000..6e6469adfb --- /dev/null +++ b/interface/resources/qml/componentCreation.js @@ -0,0 +1,27 @@ +var component; +var instance; +var parent; + +function createObject(parentObject, url) { + parent = parentObject; + component = Qt.createComponent(url); + if (component.status == Component.Ready) + finishCreation(); + else + component.statusChanged.connect(finishCreation); +} + +function finishCreation() { + if (component.status == Component.Ready) { + instance = component.createObject(parent, {"x": 100, "y": 100}); + if (instance == null) { + // Error Handling + console.log("Error creating object"); + } else { + instance.focus = true; + } + } else if (component.status == Component.Error) { + // Error Handling + console.log("Error loading component:", component.errorString()); + } +} \ No newline at end of file diff --git a/interface/resources/qml/hifiConstants.js b/interface/resources/qml/hifiConstants.js new file mode 100644 index 0000000000..860226c963 --- /dev/null +++ b/interface/resources/qml/hifiConstants.js @@ -0,0 +1,4 @@ +var color = "#0e7077" +var Colors = { + hifiBlue: "#0e7077" +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82447257fb..0766d45ff3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -137,6 +137,7 @@ #include "ui/Snapshot.h" #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" +#include "ui/AddressBarDialog.h" // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU #if defined(Q_OS_WIN) @@ -209,8 +210,12 @@ public: void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); - + if (!logMessage.isEmpty()) { +#ifdef Q_OS_WIN + OutputDebugStringA(logMessage.toLocal8Bit().constData()); + OutputDebugStringA("\n"); +#endif Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n")); } } @@ -260,6 +265,7 @@ bool setupEssentials(int& argc, char** argv) { #endif auto discoverabilityManager = DependencyManager::set(); auto sceneScriptingInterface = DependencyManager::set(); + auto offscreenUi = DependencyManager::set(); return true; } @@ -316,8 +322,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #ifdef Q_OS_WIN installNativeEventFilter(&MyNativeEventFilter::getInstance()); #endif + _logger = new FileLogger(this); // After setting organization name in order to get correct directory + qInstallMessageHandler(messageHandler); QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf"); @@ -562,8 +570,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); + // The offscreen UI needs to intercept the mouse and keyboard + // events coming from the onscreen window + _glWidget->installEventFilter( + DependencyManager::get().data()); } + void Application::aboutToQuit() { emit beforeAboutToQuit(); @@ -720,10 +733,35 @@ void Application::initializeGL() { // update before the first render update(1.0f / _fps); + + // The UI can't be created until the primary OpenGL + // context is created, because it needs to share + // texture resources + initializeUi(); InfoView::showFirstTime(INFO_HELP_PATH); } +void Application::initializeUi() { + AddressBarDialog::registerType(); + LoginDialog::registerType(); + + auto offscreenUi = DependencyManager::get(); + offscreenUi->create(_glWidget->context()->contextHandle()); + offscreenUi->resize(_glWidget->size()); + offscreenUi->setProxyWindow(_window->windowHandle()); + auto rootQml = PathUtils::resourcesPath() + "qml/Root.qml"; + offscreenUi->loadQml(QUrl::fromLocalFile(rootQml)); + offscreenUi->setMouseTranslator([this](const QPointF& p){ + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p)); + return QPointF(pos.x, pos.y); + } + return QPointF(p); + }); + offscreenUi->resume(); +} + void Application::paintGL() { PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("paintGL"); @@ -818,7 +856,7 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(true); + _applicationOverlay.renderOverlay(); _applicationOverlay.displayOverlayTexture(); } } @@ -863,6 +901,9 @@ void Application::resizeGL(int width, int height) { updateProjectionMatrix(); glLoadIdentity(); + auto offscreenUi = DependencyManager::get(); + offscreenUi->resize(QSize(width, height)); + // update Stats width // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; @@ -911,6 +952,44 @@ bool Application::importSVOFromURL(const QString& urlString) { } bool Application::event(QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + mouseMoveEvent((QMouseEvent*)event); + return true; + case QEvent::MouseButtonPress: + mousePressEvent((QMouseEvent*)event); + return true; + case QEvent::MouseButtonRelease: + mouseReleaseEvent((QMouseEvent*)event); + return true; + case QEvent::KeyPress: + keyPressEvent((QKeyEvent*)event); + return true; + case QEvent::KeyRelease: + keyReleaseEvent((QKeyEvent*)event); + return true; + case QEvent::FocusOut: + focusOutEvent((QFocusEvent*)event); + return true; + case QEvent::TouchBegin: + touchBeginEvent(static_cast(event)); + event->accept(); + return true; + case QEvent::TouchEnd: + touchEndEvent(static_cast(event)); + return true; + case QEvent::TouchUpdate: + touchUpdateEvent(static_cast(event)); + return true; + case QEvent::Wheel: + wheelEvent(static_cast(event)); + return true; + case QEvent::Drop: + dropEvent(static_cast(event)); + return true; + default: + break; + } // handle custom URL if (event->type() == QEvent::FileOpen) { @@ -931,7 +1010,7 @@ bool Application::event(QEvent* event) { if (HFActionEvent::types().contains(event->type())) { _controllerScriptingInterface.handleMetaEvent(static_cast(event)); } - + return QApplication::event(event); } @@ -963,14 +1042,17 @@ void Application::keyPressEvent(QKeyEvent* event) { bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier); bool isMeta = event->modifiers().testFlag(Qt::ControlModifier); bool isOption = event->modifiers().testFlag(Qt::AltModifier); + bool isKeypad = event->modifiers().testFlag(Qt::KeypadModifier); switch (event->key()) { break; case Qt::Key_L: - if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::LodTools); - } else if (isMeta) { + if (isShifted && isMeta) { Menu::getInstance()->triggerOption(MenuOption::Log); - } + } else if (isMeta) { + Menu::getInstance()->triggerOption(MenuOption::AddressBar); + } else if (isShifted) { + Menu::getInstance()->triggerOption(MenuOption::LodTools); + } break; case Qt::Key_E: @@ -1030,11 +1112,6 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; - case Qt::Key_Return: - case Qt::Key_Enter: - Menu::getInstance()->triggerOption(MenuOption::AddressBar); - break; - case Qt::Key_Backslash: Menu::getInstance()->triggerOption(MenuOption::Chat); break; @@ -1494,6 +1571,17 @@ void Application::dropEvent(QDropEvent *event) { } } +void Application::dragEnterEvent(QDragEnterEvent* event) { + const QMimeData* mimeData = event->mimeData(); + foreach(QUrl url, mimeData->urls()) { + auto urlString = url.toString(); + if (canAcceptURL(urlString)) { + event->acceptProposedAction(); + break; + } + } +} + bool Application::acceptSnapshot(const QString& urlString) { QUrl url(urlString); QString snapshotPath = url.toLocalFile(); diff --git a/interface/src/Application.h b/interface/src/Application.h index cf047f02d4..57c6530ad4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,7 @@ public: void setPreviousScriptLocation(const QString& previousScriptLocation); void clearScriptsBeforeRunning(); void initializeGL(); + void initializeUi(); void paintGL(); void resizeGL(int width, int height); @@ -170,6 +172,7 @@ public: void wheelEvent(QWheelEvent* event); void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 12a10681ce..d0c0cb6713 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -82,30 +82,6 @@ void GLCanvas::resizeGL(int width, int height) { Application::getInstance()->resizeGL(width, height); } -void GLCanvas::keyPressEvent(QKeyEvent* event) { - Application::getInstance()->keyPressEvent(event); -} - -void GLCanvas::keyReleaseEvent(QKeyEvent* event) { - Application::getInstance()->keyReleaseEvent(event); -} - -void GLCanvas::focusOutEvent(QFocusEvent* event) { - Application::getInstance()->focusOutEvent(event); -} - -void GLCanvas::mouseMoveEvent(QMouseEvent* event) { - Application::getInstance()->mouseMoveEvent(event); -} - -void GLCanvas::mousePressEvent(QMouseEvent* event) { - Application::getInstance()->mousePressEvent(event); -} - -void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { - Application::getInstance()->mouseReleaseEvent(event); -} - void GLCanvas::activeChanged(Qt::ApplicationState state) { switch (state) { case Qt::ApplicationActive: @@ -151,40 +127,37 @@ void GLCanvas::throttleRender() { int updateTime = 0; bool GLCanvas::event(QEvent* event) { switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: case QEvent::TouchBegin: - Application::getInstance()->touchBeginEvent(static_cast(event)); - event->accept(); - return true; case QEvent::TouchEnd: - Application::getInstance()->touchEndEvent(static_cast(event)); - return true; case QEvent::TouchUpdate: - Application::getInstance()->touchUpdateEvent(static_cast(event)); - return true; + case QEvent::Wheel: + case QEvent::DragEnter: + case QEvent::Drop: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + case QEvent::Paint: + // Ignore paint events that occur after we've decided to quit + if (Application::getInstance()->isAboutToQuit()) { + return true; + } + break; + default: break; } return QGLWidget::event(event); } -void GLCanvas::wheelEvent(QWheelEvent* event) { - Application::getInstance()->wheelEvent(event); -} - -void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { - const QMimeData* mimeData = event->mimeData(); - foreach (QUrl url, mimeData->urls()) { - auto urlString = url.toString(); - if (Application::getInstance()->canAcceptURL(urlString)) { - event->acceptProposedAction(); - break; - } - } -} - -void GLCanvas::dropEvent(QDropEvent* event) { - Application::getInstance()->dropEvent(event); -} // Pressing Alt (and Meta) key alone activates the menubar because its style inherits the // SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 7b86f983e9..6c53a17e04 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -40,23 +40,8 @@ protected: virtual void initializeGL(); virtual void paintGL(); virtual void resizeGL(int width, int height); - - virtual void keyPressEvent(QKeyEvent* event); - virtual void keyReleaseEvent(QKeyEvent* event); - - virtual void focusOutEvent(QFocusEvent* event); - - virtual void mouseMoveEvent(QMouseEvent* event); - virtual void mousePressEvent(QMouseEvent* event); - virtual void mouseReleaseEvent(QMouseEvent* event); - virtual bool event(QEvent* event); - virtual void wheelEvent(QWheelEvent* event); - - virtual void dragEnterEvent(QDragEnterEvent *event); - virtual void dropEvent(QDropEvent* event); - private slots: void activeChanged(Qt::ApplicationState state); void throttleRender(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1cce0b1f56..64e5accb1b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -97,7 +97,7 @@ Menu::Menu() { addActionToQMenuAndActionHash(fileMenu, MenuOption::AddressBar, - Qt::Key_Enter, + Qt::CTRL | Qt::Key_L, dialogsManager.data(), SLOT(toggleAddressBar())); auto addressManager = DependencyManager::get(); @@ -151,7 +151,8 @@ Menu::Menu() { connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); #endif - addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, Qt::Key_Backslash, + addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, + 0, // QML Qt::Key_Backslash, dialogsManager.data(), SLOT(showIRCLink())); addActionToQMenuAndActionHash(toolsMenu, MenuOption::AddRemoveFriends, 0, qApp, SLOT(showFriendsWindow())); @@ -194,7 +195,7 @@ Menu::Menu() { addActionToQMenuAndActionHash(toolsMenu, MenuOption::ResetSensors, - Qt::Key_Apostrophe, + 0, // QML Qt::Key_Apostrophe, qApp, SLOT(resetSensors())); @@ -207,17 +208,17 @@ Menu::Menu() { QMenu* avatarSizeMenu = avatarMenu->addMenu("Size"); addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::IncreaseAvatarSize, - Qt::Key_Plus, + 0, // QML Qt::Key_Plus, avatar, SLOT(increaseSize())); addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::DecreaseAvatarSize, - Qt::Key_Minus, + 0, // QML Qt::Key_Minus, avatar, SLOT(decreaseSize())); addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::ResetAvatarSize, - Qt::Key_Equal, + 0, // QML Qt::Key_Equal, avatar, SLOT(resetSize())); @@ -250,13 +251,17 @@ Menu::Menu() { qApp, SLOT(setFullscreen(bool))); #endif - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true, - qApp,SLOT(cameraMenuChanged())); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false, - qApp, SLOT(cameraMenuChanged())); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, + 0, // QML Qt::Key_P, + true, qApp, SLOT(cameraMenuChanged())); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, + 0, //QML Qt::SHIFT | Qt::Key_H, + true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, + 0, // QML Qt::Key_H, + false, qApp, SLOT(cameraMenuChanged())); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H, + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::CTRL | Qt::SHIFT | Qt::Key_H, false, dialogsManager.data(), SLOT(hmdTools(bool))); @@ -283,8 +288,12 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); - addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, qApp, SLOT(toggleLogDialog())); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, + 0); // QML Qt::Key_Slash); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats); + addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, + Qt::CTRL | Qt::SHIFT | Qt::Key_L, + qApp, SLOT(toggleLogDialog())); addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, dialogsManager.data(), SLOT(bandwidthDetails())); addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, @@ -294,7 +303,9 @@ Menu::Menu() { QMenu* developerMenu = addMenu("Developer"); QMenu* renderOptionsMenu = developerMenu->addMenu("Render"); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, + 0, // QML Qt::SHIFT | Qt::Key_A, + true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DontFadeOnOctreeServerChanges); @@ -346,13 +357,16 @@ Menu::Menu() { resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false)); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, + 0, // QML Qt::Key_Asterisk, + true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true, DependencyManager::get().data(), SLOT(toggleGlowEffect(bool))); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false); - addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, - dialogsManager.data(), SLOT(lodTools())); + addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, + 0, // QML Qt::SHIFT | Qt::Key_L, + dialogsManager.data(), SLOT(lodTools())); QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar"); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d56ece12fb..a309831c14 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -114,8 +114,11 @@ void OculusManager::initSdk() { } void OculusManager::shutdownSdk() { - ovrHmd_Destroy(_ovrHmd); - ovr_Shutdown(); + if (_ovrHmd) { + ovrHmd_Destroy(_ovrHmd); + _ovrHmd = nullptr; + ovr_Shutdown(); + } } void OculusManager::init() { @@ -124,6 +127,12 @@ void OculusManager::init() { #endif } +void OculusManager::deinit() { +#ifdef OVR_DIRECT_MODE + shutdownSdk(); +#endif +} + void OculusManager::connect() { #ifndef OVR_DIRECT_MODE initSdk(); @@ -515,7 +524,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p // We only need to render the overlays to a texture once, then we just render the texture on the hemisphere // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() - applicationOverlay.renderOverlay(true); + applicationOverlay.renderOverlay(); //Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index fe2da31231..4b1bc98fb2 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -51,6 +51,7 @@ class Text3DOverlay; class OculusManager { public: static void init(); + static void deinit(); static void connect(); static void disconnect(); static bool isConnected(); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index f082c6de47..4f6e566d8c 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -103,7 +103,7 @@ void TV3DManager::display(Camera& whichCamera) { // We only need to render the overlays to a texture once, then we just render the texture as a quad // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() - applicationOverlay.renderOverlay(true); + applicationOverlay.renderOverlay(); DependencyManager::get()->prepare(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index b4486ceb2b..7d80b077b8 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -112,6 +112,7 @@ int main(int argc, const char* argv[]) { exitCode = app.exec(); } + OculusManager::deinit(); #ifdef Q_OS_WIN ReleaseMutex(mutex); #endif diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index b414f95240..49158265ba 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -1,148 +1,50 @@ // // AddressBarDialog.cpp -// interface/src/ui // -// Created by Stojce Slavkovski on 9/22/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 "AddressBarDialog.h" + #include -#include - -#include "AddressBarDialog.h" +#include "DependencyManager.h" #include "AddressManager.h" -#include "Application.h" -#include "MainWindow.h" -const QString ADDRESSBAR_GO_BUTTON_ICON = "images/address-bar-submit.svg"; -const QString ADDRESSBAR_GO_BUTTON_ACTIVE_ICON = "images/address-bar-submit-active.svg"; +QML_DIALOG_DEF(AddressBarDialog) -AddressBarDialog::AddressBarDialog(QWidget* parent) : - FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP) -{ - setAttribute(Qt::WA_DeleteOnClose, false); - setupUI(); - +AddressBarDialog::AddressBarDialog(QQuickItem *parent) : QQuickItem(parent) { auto addressManager = DependencyManager::get(); - connect(addressManager.data(), &AddressManager::lookupResultIsOffline, this, &AddressBarDialog::displayAddressOfflineMessage); connect(addressManager.data(), &AddressManager::lookupResultIsNotFound, this, &AddressBarDialog::displayAddressNotFoundMessage); + connect(addressManager.data(), &AddressManager::lookupResultsFinished, this, &AddressBarDialog::hide); } -void AddressBarDialog::setupUI() { - - const QString DIALOG_STYLESHEET = "font-family: Helvetica, Arial, sans-serif;"; - const QString ADDRESSBAR_PLACEHOLDER = "Go to: domain, location, @user, /x,y,z"; - const QString ADDRESSBAR_STYLESHEET = "padding: 5px 10px; font-size: 20px;"; - - const int ADDRESSBAR_MIN_WIDTH = 200; - const int ADDRESSBAR_MAX_WIDTH = 615; - const int ADDRESSBAR_HEIGHT = 42; - const int ADDRESSBAR_STRETCH = 60; - - const int BUTTON_SPACER_SIZE = 5; - const int DEFAULT_SPACER_SIZE = 20; - const int ADDRESS_LAYOUT_RIGHT_MARGIN = 10; - - const int GO_BUTTON_SIZE = 42; - const int CLOSE_BUTTON_SIZE = 16; - const QString CLOSE_BUTTON_ICON = "styles/close.svg"; - - const int DIALOG_HEIGHT = 62; - const int DIALOG_INITIAL_WIDTH = 560; - - QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setSizePolicy(sizePolicy); - setMinimumSize(QSize(DIALOG_INITIAL_WIDTH, DIALOG_HEIGHT)); - setMaximumHeight(DIALOG_HEIGHT); - setStyleSheet(DIALOG_STYLESHEET); - _verticalLayout = new QVBoxLayout(this); - _verticalLayout->setContentsMargins(0, 0, 0, 0); - - _addressLayout = new QHBoxLayout(); - _addressLayout->setContentsMargins(0, 0, ADDRESS_LAYOUT_RIGHT_MARGIN, 0); - - _leftSpacer = new QSpacerItem(DEFAULT_SPACER_SIZE, - DEFAULT_SPACER_SIZE, - QSizePolicy::MinimumExpanding, - QSizePolicy::Minimum); - - _addressLayout->addItem(_leftSpacer); - - _addressLineEdit = new QLineEdit(this); - _addressLineEdit->setAttribute(Qt::WA_MacShowFocusRect, 0); - _addressLineEdit->setPlaceholderText(ADDRESSBAR_PLACEHOLDER); - QSizePolicy sizePolicyLineEdit(QSizePolicy::Preferred, QSizePolicy::Fixed); - sizePolicyLineEdit.setHorizontalStretch(ADDRESSBAR_STRETCH); - _addressLineEdit->setSizePolicy(sizePolicyLineEdit); - _addressLineEdit->setMinimumSize(QSize(ADDRESSBAR_MIN_WIDTH, ADDRESSBAR_HEIGHT)); - _addressLineEdit->setMaximumSize(QSize(ADDRESSBAR_MAX_WIDTH, ADDRESSBAR_HEIGHT)); - _addressLineEdit->setStyleSheet(ADDRESSBAR_STYLESHEET); - _addressLayout->addWidget(_addressLineEdit); - - _buttonSpacer = new QSpacerItem(BUTTON_SPACER_SIZE, BUTTON_SPACER_SIZE, QSizePolicy::Fixed, QSizePolicy::Minimum); - _addressLayout->addItem(_buttonSpacer); - - _goButton = new QPushButton(this); - _goButton->setSizePolicy(sizePolicy); - _goButton->setMinimumSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); - _goButton->setMaximumSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); - _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); - _goButton->setIconSize(QSize(GO_BUTTON_SIZE, GO_BUTTON_SIZE)); - _goButton->setDefault(true); - _goButton->setFlat(true); - _addressLayout->addWidget(_goButton); - - _rightSpacer = new QSpacerItem(DEFAULT_SPACER_SIZE, - DEFAULT_SPACER_SIZE, - QSizePolicy::MinimumExpanding, - QSizePolicy::Minimum); - - _addressLayout->addItem(_rightSpacer); - - _closeButton = new QPushButton(this); - _closeButton->setSizePolicy(sizePolicy); - _closeButton->setMinimumSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); - _closeButton->setMaximumSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); - QIcon icon(PathUtils::resourcesPath() + CLOSE_BUTTON_ICON); - _closeButton->setIcon(icon); - _closeButton->setIconSize(QSize(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)); - _closeButton->setFlat(true); - _addressLayout->addWidget(_closeButton, 0, Qt::AlignRight); - - _verticalLayout->addLayout(_addressLayout); - - connect(_goButton, &QPushButton::clicked, this, &AddressBarDialog::accept); - connect(_closeButton, &QPushButton::clicked, this, &QDialog::close); +void AddressBarDialog::hide() { + setEnabled(false); + setVisible(false); } -void AddressBarDialog::showEvent(QShowEvent* event) { - _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); - _addressLineEdit->setText(QString()); - _addressLineEdit->setFocus(); - FramelessDialog::showEvent(event); -} - -void AddressBarDialog::accept() { - if (!_addressLineEdit->text().isEmpty()) { - _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ACTIVE_ICON)); - auto addressManager = DependencyManager::get(); - connect(addressManager.data(), &AddressManager::lookupResultsFinished, this, &QDialog::hide); - addressManager->handleLookupString(_addressLineEdit->text()); +void AddressBarDialog::loadAddress(const QString & address) { + qDebug() << "Called LoadAddress with address " << address; + if (!address.isEmpty()) { + DependencyManager::get()->handleLookupString(address); } } +// TODO port to a QML based message box void AddressBarDialog::displayAddressOfflineMessage() { - QMessageBox::information(Application::getInstance()->getWindow(), "Address offline", - "That user or place is currently offline."); + QMessageBox::information(nullptr, "Address offline", + "That user or place is currently offline."); } +// TODO port to a QML based message box void AddressBarDialog::displayAddressNotFoundMessage() { - QMessageBox::information(Application::getInstance()->getWindow(), "Address not found", - "There is no address information for that user or place."); -} \ No newline at end of file + QMessageBox::information(nullptr, "Address not found", + "There is no address information for that user or place."); +} diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index dda807d6e2..00e55ceb10 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -1,9 +1,8 @@ // // AddressBarDialog.h -// interface/src/ui // -// Created by Stojce Slavkovski on 9/22/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 @@ -12,36 +11,25 @@ #ifndef hifi_AddressBarDialog_h #define hifi_AddressBarDialog_h -#include "FramelessDialog.h" +#pragma once +#include -#include -#include -#include -#include +#include "OffscreenUi.h" -class AddressBarDialog : public FramelessDialog { +class AddressBarDialog : public QQuickItem +{ Q_OBJECT + QML_DIALOG_DECL public: - AddressBarDialog(QWidget* parent); - -private: - void setupUI(); - void showEvent(QShowEvent* event); - - QVBoxLayout *_verticalLayout; - QHBoxLayout *_addressLayout; - QSpacerItem *_leftSpacer; - QSpacerItem *_rightSpacer; - QSpacerItem *_buttonSpacer; - QPushButton *_goButton; - QPushButton *_closeButton; - QLineEdit *_addressLineEdit; - -private slots: - void accept(); + AddressBarDialog(QQuickItem *parent = 0); + +protected: void displayAddressOfflineMessage(); void displayAddressNotFoundMessage(); + void hide(); + + Q_INVOKABLE void loadAddress(const QString & address); }; -#endif // hifi_AddressBarDialog_h +#endif diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f08df229cc..5583790b13 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "AudioClient.h" #include "audio/AudioIOStatsRenderer.h" @@ -161,13 +162,27 @@ ApplicationOverlay::ApplicationOverlay() : _domainStatusBorder = geometryCache->allocateID(); _magnifierBorder = geometryCache->allocateID(); + // Once we move UI rendering and screen rendering to different + // threads, we need to use a sync object to deteremine when + // the current UI texture is no longer being read from, and only + // then release it back to the UI for re-use + auto offscreenUi = DependencyManager::get(); + connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [&](GLuint textureId) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->lockTexture(textureId); + assert(!glGetError()); + std::swap(_newUiTexture, textureId); + if (textureId) { + offscreenUi->releaseTexture(textureId); + } + }); } ApplicationOverlay::~ApplicationOverlay() { } // Renders the overlays either to a texture or to the screen -void ApplicationOverlay::renderOverlay(bool renderToTexture) { +void ApplicationOverlay::renderOverlay() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); auto glCanvas = Application::getInstance()->getGLWidget(); @@ -183,11 +198,9 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (renderToTexture) { - _overlays.buildFramebufferObject(); - _overlays.bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } + _overlays.buildFramebufferObject(); + _overlays.bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); { const float NEAR_CLIP = -10000; @@ -218,9 +231,25 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glEnable(GL_LIGHTING); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - if (renderToTexture) { - _overlays.release(); + _overlays.release(); +} + +// A quick and dirty solution for compositing the old overlay +// texture with the new one +template +void with_each_texture(GLuint a, GLuint b, F f) { + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + if (a) { + glBindTexture(GL_TEXTURE_2D, a); + f(); } + if (b) { + glBindTexture(GL_TEXTURE_2D, b); + f(); + } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); } // Draws the FBO texture for the screen @@ -229,30 +258,24 @@ void ApplicationOverlay::displayOverlayTexture() { return; } auto glCanvas = Application::getInstance()->getGLWidget(); - - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - _overlays.bindTexture(); - glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0, 1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - - glm::vec2 topLeft(0.0f, 0.0f); - glm::vec2 bottomRight(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); - glm::vec2 texCoordTopLeft(0.0f, 1.0f); - glm::vec2 texCoordBottomRight(1.0f, 0.0f); + if (_alpha < 1.0) { + glEnable(GL_BLEND); + } - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, - glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); - + with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + static const glm::vec2 topLeft(-1, 1); + static const glm::vec2 bottomRight(1, -1); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); + }); } glPopMatrix(); - - glDisable(GL_TEXTURE_2D); } // Draws the FBO texture for Oculus rift. @@ -260,10 +283,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_alpha == 0.0f) { return; } - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - _overlays.bindTexture(); - + glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); @@ -271,8 +291,8 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glDisable(GL_LIGHTING); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.01f); - - + + //Update and draw the magnifiers MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); const glm::quat& orientation = myAvatar->getOrientation(); @@ -303,8 +323,9 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { //Render magnifier, but dont show border for mouse magnifier glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(), _reticlePosition[MOUSE].y())); - - renderMagnifier(projection, _magSizeMult[i], i != MOUSE); + with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + renderMagnifier(projection, _magSizeMult[i], i != MOUSE); + }); } } @@ -319,12 +340,15 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); } - _overlays.render(); + + with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + _overlays.render(); + }); + if (!Application::getInstance()->isMouseHidden()) { renderPointersOculus(myAvatar->getDefaultEyePosition()); } glDepthMask(GL_TRUE); - _overlays.releaseTexture(); glDisable(GL_TEXTURE_2D); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); @@ -341,14 +365,10 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); const glm::vec3& viewMatrixTranslation = qApp->getViewMatrixTranslation(); - glActiveTexture(GL_TEXTURE0); - glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - _overlays.bindTexture(); glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); @@ -382,13 +402,15 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as GLfloat y = -halfQuadHeight; glDisable(GL_DEPTH_TEST); - DependencyManager::get()->renderQuad(glm::vec3(x, y + quadHeight, -distance), + with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + DependencyManager::get()->renderQuad(glm::vec3(x, y + quadHeight, -distance), glm::vec3(x + quadWidth, y + quadHeight, -distance), glm::vec3(x + quadWidth, y, -distance), glm::vec3(x, y, -distance), glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f), glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), overlayColor); + }); auto glCanvas = Application::getInstance()->getGLWidget(); if (_crosshairTexture == 0) { @@ -993,14 +1015,6 @@ void ApplicationOverlay::TexturedHemisphere::release() { _framebufferObject->release(); } -void ApplicationOverlay::TexturedHemisphere::bindTexture() { - glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); -} - -void ApplicationOverlay::TexturedHemisphere::releaseTexture() { - glBindTexture(GL_TEXTURE_2D, 0); -} - void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, const float aspectRatio, const int slices, @@ -1099,14 +1113,14 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { } _framebufferObject = new QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::Depth); - bindTexture(); + glBindTexture(GL_TEXTURE_2D, getTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - releaseTexture(); + glBindTexture(GL_TEXTURE_2D, 0); } //Renders a hemisphere with texture coordinates. @@ -1137,6 +1151,10 @@ void ApplicationOverlay::TexturedHemisphere::render() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +GLuint ApplicationOverlay::TexturedHemisphere::getTexture() { + return _framebufferObject->texture(); +} + glm::vec2 ApplicationOverlay::directionToSpherical(glm::vec3 direction) const { glm::vec2 result; // Compute yaw diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index cc424d0c8f..cc4188e8ef 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -28,7 +28,7 @@ public: ApplicationOverlay(); ~ApplicationOverlay(); - void renderOverlay(bool renderToTexture = false); + void renderOverlay(); void displayOverlayTexture(); void displayOverlayTextureOculus(Camera& whichCamera); void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); @@ -75,8 +75,7 @@ private: void bind(); void release(); - void bindTexture(); - void releaseTexture(); + GLuint getTexture(); void buildFramebufferObject(); void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks); @@ -122,6 +121,9 @@ private: float _trailingAudioLoudness; GLuint _crosshairTexture; + // TODO, move divide up the rendering, displaying and input handling + // facilities of this class + GLuint _newUiTexture{ 0 }; int _reticleQuad; int _magnifierQuad; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 701ceb0189..3c54c26379 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DialogsManager.h" + #include #include @@ -28,14 +30,9 @@ #include "PreferencesDialog.h" #include "ScriptEditorWindow.h" -#include "DialogsManager.h" void DialogsManager::toggleAddressBar() { - maybeCreateDialog(_addressBarDialog); - - if (!_addressBarDialog->isVisible()) { - _addressBarDialog->show(); - } + AddressBarDialog::toggle(); } void DialogsManager::toggleDiskCacheEditor() { @@ -44,13 +41,11 @@ void DialogsManager::toggleDiskCacheEditor() { } void DialogsManager::toggleLoginDialog() { - maybeCreateDialog(_loginDialog); - _loginDialog->toggleQAction(); + LoginDialog::toggleAction(); } void DialogsManager::showLoginDialog() { - maybeCreateDialog(_loginDialog); - _loginDialog->showLoginForCurrentDomain(); + LoginDialog::show(); } void DialogsManager::octreeStatsDetails() { @@ -170,3 +165,4 @@ void DialogsManager::showIRCLink() { _ircInfoBox->raise(); } + diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp deleted file mode 100644 index bae6217083..0000000000 --- a/interface/src/ui/FramelessDialog.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// FramelessDialog.cpp -// interface/src/ui -// -// Created by Stojce Slavkovski on 2/20/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 -#include - -#include - -#include "Application.h" -#include "FramelessDialog.h" -#include "Menu.h" - -const int RESIZE_HANDLE_WIDTH = 7; - -FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags, Position position) : - QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint), - _allowResize(true), - _isResizing(false), - _resizeInitialWidth(0), - _selfHidden(false), - _position(position), - _hideOnBlur(true) { - - setAttribute(Qt::WA_DeleteOnClose); - - // handle rezize and move events - parentWidget()->installEventFilter(this); - - // handle minimize, restore and focus events - Application::getInstance()->installEventFilter(this); -} - -bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) { - switch (event->type()) { - case QEvent::Move: - if (sender == parentWidget()) { - resizeAndPosition(false); - } - break; - case QEvent::Resize: - if (sender == parentWidget()) { - resizeAndPosition(false); - } - break; - case QEvent::WindowStateChange: - if (_hideOnBlur && parentWidget()->isMinimized()) { - if (isVisible()) { - _selfHidden = true; - setHidden(true); - } - } else if (_selfHidden) { - _selfHidden = false; - setHidden(false); - } - break; - case QEvent::ApplicationDeactivate: - // hide on minimize and focus lost - if (_hideOnBlur && isVisible()) { - _selfHidden = true; - setHidden(true); - } - break; - case QEvent::ApplicationActivate: - if (_selfHidden) { - _selfHidden = false; - setHidden(false); - } - break; - default: - break; - } - - return false; -} - -void FramelessDialog::setStyleSheetFile(const QString& fileName) { - QFile globalStyleSheet(PathUtils::resourcesPath() + "styles/global.qss"); - QFile styleSheet(PathUtils::resourcesPath() + fileName); - if (styleSheet.open(QIODevice::ReadOnly) && globalStyleSheet.open(QIODevice::ReadOnly) ) { - QDir::setCurrent(PathUtils::resourcesPath()); - setStyleSheet(globalStyleSheet.readAll() + styleSheet.readAll()); - } -} - -void FramelessDialog::showEvent(QShowEvent* event) { - resizeAndPosition(); - QDialog::showEvent(event); -} - -void FramelessDialog::resizeAndPosition(bool resizeParent) { - QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); - QSize parentSize = parentGeometry.size(); - - // keep full app height or width depending on position - if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { - setFixedHeight(parentSize.height()); - } else { - setFixedWidth(parentSize.width()); - } - - // resize parrent if width is smaller than this dialog - if (resizeParent && parentSize.width() < size().width()) { - parentWidget()->resize(size().width(), parentSize.height()); - } - - if (_position == POSITION_LEFT || _position == POSITION_TOP) { - // move to upper left corner - move(parentGeometry.topLeft()); - } else if (_position == POSITION_RIGHT) { - // move to upper right corner - QPoint pos = parentGeometry.topRight(); - pos.setX(pos.x() - size().width()); - move(pos); - } - repaint(); -} - -void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) { - if (_allowResize && mouseEvent->button() == Qt::LeftButton) { - if (_position == POSITION_LEFT || _position == POSITION_RIGHT) { - bool hitLeft = (_position == POSITION_LEFT) && (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH); - bool hitRight = (_position == POSITION_RIGHT) && (mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH); - if (hitLeft || hitRight) { - _isResizing = true; - _resizeInitialWidth = size().width(); - setCursor(Qt::SizeHorCursor); - } - } else { - bool hitTop = (_position == POSITION_TOP) && (abs(mouseEvent->pos().y() - size().height()) < RESIZE_HANDLE_WIDTH); - if (hitTop) { - _isResizing = true; - _resizeInitialWidth = size().height(); - setCursor(Qt::SizeHorCursor); - } - } - } -} - -void FramelessDialog::mouseReleaseEvent(QMouseEvent* mouseEvent) { - unsetCursor(); - _isResizing = false; -} - -void FramelessDialog::mouseMoveEvent(QMouseEvent* mouseEvent) { - if (_isResizing) { - if (_position == POSITION_LEFT) { - resize(mouseEvent->pos().x(), size().height()); - } else if (_position == POSITION_RIGHT) { - setUpdatesEnabled(false); - resize(_resizeInitialWidth - mouseEvent->pos().x(), size().height()); - resizeAndPosition(); - _resizeInitialWidth = size().width(); - setUpdatesEnabled(true); - } else if (_position == POSITION_TOP) { - resize(size().width(), mouseEvent->pos().y()); - } - } -} diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h deleted file mode 100644 index 32451f746d..0000000000 --- a/interface/src/ui/FramelessDialog.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// FramelessDialog.h -// interface/src/ui -// -// Created by Stojce Slavkovski on 2/20/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_FramelessDialog_h -#define hifi_FramelessDialog_h - -#include - -class FramelessDialog : public QDialog { - Q_OBJECT - -public: - enum Position { POSITION_LEFT, POSITION_RIGHT, POSITION_TOP }; - - FramelessDialog(QWidget* parent, Qt::WindowFlags flags = 0, Position position = POSITION_LEFT); - void setStyleSheetFile(const QString& fileName); - void setAllowResize(bool allowResize) { _allowResize = allowResize; } - bool getAllowResize() { return _allowResize; } - void setHideOnBlur(bool hideOnBlur) { _hideOnBlur = hideOnBlur; } - bool getHideOnBlur() { return _hideOnBlur; } - void resizeAndPosition(bool resizeParent = true); - -protected: - virtual void mouseMoveEvent(QMouseEvent* mouseEvent); - virtual void mousePressEvent(QMouseEvent* mouseEvent); - virtual void mouseReleaseEvent(QMouseEvent* mouseEvent); - virtual void showEvent(QShowEvent* event); - - bool eventFilter(QObject* sender, QEvent* event); - -private: - bool _allowResize; - bool _isResizing; - int _resizeInitialWidth; - bool _selfHidden; ///< true when the dialog itself because of a window event (deactivation or minimization) - Position _position; - bool _hideOnBlur; - -}; - -#endif // hifi_FramelessDialog_h diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b134f7f230..3b164041fa 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -1,120 +1,35 @@ // +// // LoginDialog.cpp -// interface/src/ui // -// Created by Ryan Huffman on 4/23/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 -#include -#include - -#include -#include - -#include "Application.h" -#include "Menu.h" -#include "AccountManager.h" -#include "ui_loginDialog.h" #include "LoginDialog.h" -#include "UIUtil.h" -const QString CREATE_ACCOUNT_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/signup"; -const QString FORGOT_PASSWORD_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/users/password/new"; +#include "DependencyManager.h" +#include "AccountManager.h" +#include "Menu.h" +#include -LoginDialog::LoginDialog(QWidget* parent) : - FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), - _ui(new Ui::LoginDialog) { - - _ui->setupUi(this); - reset(); - - setAttribute(Qt::WA_DeleteOnClose, false); +QML_DIALOG_DEF(LoginDialog) +LoginDialog::LoginDialog(QQuickItem *parent) : QQuickItem(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { connect(&AccountManager::getInstance(), &AccountManager::loginComplete, - this, &LoginDialog::handleLoginCompleted); + this, &LoginDialog::handleLoginCompleted); connect(&AccountManager::getInstance(), &AccountManager::loginFailed, - this, &LoginDialog::handleLoginFailed); - connect(_ui->loginButton, &QPushButton::clicked, - this, &LoginDialog::handleLoginClicked); - connect(_ui->closeButton, &QPushButton::clicked, - this, &LoginDialog::close); - - UIUtil::scaleWidgetFontSizes(this); - _ui->accountLabel->setText(_ui->accountLabel->text().arg(CREATE_ACCOUNT_URL, FORGOT_PASSWORD_URL)); - - // Initialize toggle connection - toggleQAction(); -}; - -LoginDialog::~LoginDialog() { - delete _ui; -}; - -void LoginDialog::reset() { - _ui->errorLabel->hide(); - _ui->emailLineEdit->setFocus(); - _ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg")); - _ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg")); - _ui->closeButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/close.svg")); - _ui->infoLabel->setVisible(false); - _ui->errorLabel->setVisible(false); - - _ui->emailLineEdit->setText(""); - _ui->passwordLineEdit->setText(""); - _ui->loginArea->setDisabled(false); + this, &LoginDialog::handleLoginFailed); } -void LoginDialog::handleLoginCompleted(const QUrl& authURL) { - reset(); - close(); -}; - -void LoginDialog::handleLoginFailed() { - _ui->infoLabel->setVisible(false); - _ui->errorLabel->setVisible(true); - - _ui->errorLabel->show(); - _ui->loginArea->setDisabled(false); - - // Move focus to password and select the entire line - _ui->passwordLineEdit->setFocus(); - _ui->passwordLineEdit->setSelection(0, _ui->emailLineEdit->maxLength()); -}; - -void LoginDialog::handleLoginClicked() { - // If the email or password inputs are empty, move focus to them, otherwise attempt to login. - if (_ui->emailLineEdit->text().isEmpty()) { - _ui->emailLineEdit->setFocus(); - } else if (_ui->passwordLineEdit->text().isEmpty()) { - _ui->passwordLineEdit->setFocus(); - } else { - _ui->infoLabel->setVisible(true); - _ui->errorLabel->setVisible(false); - - _ui->loginArea->setDisabled(true); - AccountManager::getInstance().requestAccessToken(_ui->emailLineEdit->text(), _ui->passwordLineEdit->text()); - } -}; - -void LoginDialog::moveEvent(QMoveEvent* event) { - // Modal dialogs seemed to get repositioned automatically. Combat this by moving the window if needed. - resizeAndPosition(); -}; - - -void LoginDialog::toggleQAction() { +void LoginDialog::toggleAction() { AccountManager& accountManager = AccountManager::getInstance(); QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login); Q_CHECK_PTR(loginAction); - disconnect(loginAction, 0, 0, 0); - + if (accountManager.isLoggedIn()) { // change the menu item to logout loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername()); @@ -122,11 +37,40 @@ void LoginDialog::toggleQAction() { } else { // change the menu item to login loginAction->setText("Login"); - connect(loginAction, &QAction::triggered, this, &LoginDialog::showLoginForCurrentDomain); + connect(loginAction, &QAction::triggered, &LoginDialog::show); } } -void LoginDialog::showLoginForCurrentDomain() { - show(); - resizeAndPosition(false); +void LoginDialog::handleLoginCompleted(const QUrl& authURL) { + setEnabled(false); + setVisible(false); +} + +void LoginDialog::handleLoginFailed() { + setStatusText("Invalid username or password.< / font>"); +} + +void LoginDialog::setStatusText(const QString &a) { + if (a != _statusText) { + _statusText = a; + emit statusTextChanged(); + } +} + +QString LoginDialog::statusText() const { + return _statusText; +} + +QString LoginDialog::rootUrl() const { + return _rootUrl; +} + +void LoginDialog::login(const QString & username, const QString & password) { + qDebug() << "Attempting to login " << username; + setStatusText("Authenticating..."); + AccountManager::getInstance().requestAccessToken(username, password); +} + +void LoginDialog::openUrl(const QString & url) { + qDebug() << url; } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index d5384c4625..3c9a98a9a4 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -1,9 +1,8 @@ // // LoginDialog.h -// interface/src/ui // -// Created by Ryan Huffman on 4/23/14. -// Copyright 2014 High Fidelity, Inc. +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 @@ -12,35 +11,41 @@ #ifndef hifi_LoginDialog_h #define hifi_LoginDialog_h -#include -#include "FramelessDialog.h" +#pragma once +#include -namespace Ui { - class LoginDialog; -} +#include "OffscreenUi.h" -class LoginDialog : public FramelessDialog { +class LoginDialog : public QQuickItem +{ Q_OBJECT + QML_DIALOG_DECL + + Q_PROPERTY(QString statusText READ statusText WRITE setStatusText NOTIFY statusTextChanged) + Q_PROPERTY(QString rootUrl READ rootUrl) public: - LoginDialog(QWidget* parent); - ~LoginDialog(); + static void toggleAction(); -public slots: - void toggleQAction(); - void showLoginForCurrentDomain(); - -protected slots: - void reset(); - void handleLoginClicked(); + LoginDialog(QQuickItem *parent = 0); + + void setStatusText(const QString & a); + QString statusText() const; + + QString rootUrl() const; + +signals: + void statusTextChanged(); + +protected: void handleLoginCompleted(const QUrl& authURL); void handleLoginFailed(); -protected: - void moveEvent(QMoveEvent* event); - + Q_INVOKABLE void login(const QString & username, const QString & password); + Q_INVOKABLE void openUrl(const QString & url); private: - Ui::LoginDialog* _ui = nullptr; + QString _statusText; + const QString _rootUrl; }; #endif // hifi_LoginDialog_h diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index caabff44cf..fd4d447b25 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -6,7 +6,7 @@ AUTOSCRIBE_SHADER_LIB(gpu model) qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Widgets OpenGL Network Script) +setup_hifi_library(Widgets OpenGL Network Qml Quick Script) add_dependency_external_projects(glm) find_package(GLM REQUIRED) diff --git a/libraries/render-utils/src/FboCache.cpp b/libraries/render-utils/src/FboCache.cpp new file mode 100644 index 0000000000..fdd29d20d8 --- /dev/null +++ b/libraries/render-utils/src/FboCache.cpp @@ -0,0 +1,98 @@ +// +// OffscreenGlCanvas.cpp +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// Copyright 2015 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 "FboCache.h" + +#include +#include +#include "ThreadHelpers.h" + +FboCache::FboCache() { + // Why do we even HAVE that lever? +} + +void FboCache::lockTexture(int texture) { + withLock(_lock, [&] { + Q_ASSERT(_fboMap.count(texture)); + if (!_fboLocks.count(texture)) { + Q_ASSERT(_readyFboQueue.front()->texture() == texture); + _readyFboQueue.pop_front(); + _fboLocks[texture] = 1; + } else { + _fboLocks[texture]++; + } + }); +} + +void FboCache::releaseTexture(int texture) { + withLock(_lock, [&] { + Q_ASSERT(_fboMap.count(texture)); + Q_ASSERT(_fboLocks.count(texture)); + int newLockCount = --_fboLocks[texture]; + if (!newLockCount) { + auto fbo = _fboMap[texture].data(); + if (fbo->size() != _size) { + // Move the old FBO to the destruction queue. + // We can't destroy the FBO here because we might + // not be on the right thread or have the context active + _destroyFboQueue.push_back(_fboMap[texture]); + _fboMap.remove(texture); + } else { + _readyFboQueue.push_back(fbo); + } + _fboLocks.remove(texture); + } + }); +} + +QOpenGLFramebufferObject* FboCache::getReadyFbo() { + QOpenGLFramebufferObject* result = nullptr; + withLock(_lock, [&] { + // Delete any FBOs queued for deletion + _destroyFboQueue.clear(); + + if (_readyFboQueue.empty()) { + qDebug() << "Building new offscreen FBO number " << _fboMap.size() + 1; + result = new QOpenGLFramebufferObject(_size, QOpenGLFramebufferObject::CombinedDepthStencil); + _fboMap[result->texture()] = QSharedPointer(result); + _readyFboQueue.push_back(result); + } else { + result = _readyFboQueue.front(); + } + }); + return result; +} + +void FboCache::setSize(const QSize & newSize) { + if (_size == newSize) { + return; + } + _size = newSize; + withLock(_lock, [&] { + // Clear out any fbos with the old id + _readyFboQueue.clear(); + + QSet outdatedFbos; + // FBOs that are locked will be removed as they are unlocked + foreach(int texture, _fboMap.keys()) { + if (!_fboLocks.count(texture)) { + outdatedFbos.insert(texture); + } + } + // Implicitly deletes the FBO via the shared pointer destruction mechanism + foreach(int texture, outdatedFbos) { + _fboMap.remove(texture); + } + }); +} + + diff --git a/libraries/render-utils/src/FboCache.h b/libraries/render-utils/src/FboCache.h new file mode 100644 index 0000000000..bbbb4a943e --- /dev/null +++ b/libraries/render-utils/src/FboCache.h @@ -0,0 +1,50 @@ +// +// OffscreenGlCanvas.h +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// Copyright 2015 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 +// +#pragma once +#ifndef hifi_FboCache_h +#define hifi_FboCache_h + +#include +#include +#include +#include +#include + +class QOpenGLFramebufferObject; + +class FboCache : public QObject { +public: + FboCache(); + + // setSize() and getReadyFbo() must consitently be called from only a single + // thread. Additionally, it is the caller's responsibility to ensure that + // the appropriate OpenGL context is active when doing so. + + // Important.... textures are sharable resources, but FBOs ARE NOT. + void setSize(const QSize & newSize); + QOpenGLFramebufferObject* getReadyFbo(); + + // These operations are thread safe and require no OpenGL context. They manipulate the + // internal locks and pointers but execute no OpenGL opreations. + void lockTexture(int texture); + void releaseTexture(int texture); + +protected: + QMap> _fboMap; + QMap _fboLocks; + QQueue _readyFboQueue; + QQueue> _destroyFboQueue; + QMutex _lock; + QSize _size; + +}; + +#endif // hifi_FboCache_h diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp new file mode 100644 index 0000000000..694fa68a5a --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -0,0 +1,43 @@ +// +// OffscreenGlCanvas.cpp +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// Copyright 2015 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 "OffscreenGlCanvas.h" + +OffscreenGlCanvas::OffscreenGlCanvas() { +} + +void OffscreenGlCanvas::create(QOpenGLContext * sharedContext) { + QSurfaceFormat format; + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setMajorVersion(4); + format.setMinorVersion(1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + + _context.setFormat(format); + if (nullptr != sharedContext) { + _context.setShareContext(sharedContext); + } + _context.create(); + + _offscreenSurface.setFormat(_context.format()); + _offscreenSurface.create(); +} + +bool OffscreenGlCanvas::makeCurrent() { + return _context.makeCurrent(&_offscreenSurface); +} + +void OffscreenGlCanvas::doneCurrent() { + _context.doneCurrent(); +} + diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h new file mode 100644 index 0000000000..1b2f15f690 --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -0,0 +1,31 @@ +// +// OffscreenGlCanvas.h +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// Copyright 2015 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 +// +#pragma once +#ifndef hifi_OffscreenGlCanvas_h +#define hifi_OffscreenGlCanvas_h + +#include +#include + +class OffscreenGlCanvas : public QObject { +public: + OffscreenGlCanvas(); + void create(QOpenGLContext * sharedContext = nullptr); + bool makeCurrent(); + void doneCurrent(); + +protected: + QOpenGLContext _context; + QOffscreenSurface _offscreenSurface; + +}; + +#endif // hifi_OffscreenGlCanvas_h diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp new file mode 100644 index 0000000000..cb57d86412 --- /dev/null +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -0,0 +1,325 @@ +#include "OffscreenUi.h" +#include +#include +#include + +OffscreenUi::OffscreenUi() { +} + +OffscreenUi::~OffscreenUi() { + // Make sure the context is current while doing cleanup. Note that we use the + // offscreen surface here because passing 'this' at this point is not safe: the + // underlying platform window may already be destroyed. To avoid all the trouble, use + // another surface that is valid for sure. + makeCurrent(); + + // Delete the render control first since it will free the scenegraph resources. + // Destroy the QQuickWindow only afterwards. + delete _renderControl; + + delete _qmlComponent; + delete _quickWindow; + delete _qmlEngine; + + doneCurrent(); +} + +void OffscreenUi::create(QOpenGLContext * shareContext) { + OffscreenGlCanvas::create(shareContext); + + makeCurrent(); + + // Create a QQuickWindow that is associated with out render control. Note that this + // window never gets created or shown, meaning that it will never get an underlying + // native (platform) window. + QQuickWindow::setDefaultAlphaBuffer(true); + _quickWindow = new QQuickWindow(_renderControl); + _quickWindow->setColor(QColor(255, 255, 255, 0)); + _quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground)); + // Create a QML engine. + _qmlEngine = new QQmlEngine; + if (!_qmlEngine->incubationController()) + _qmlEngine->setIncubationController(_quickWindow->incubationController()); + + // When Quick says there is a need to render, we will not render immediately. Instead, + // a timer with a small interval is used to get better performance. + _updateTimer.setSingleShot(true); + _updateTimer.setInterval(5); + connect(&_updateTimer, &QTimer::timeout, this, &OffscreenUi::updateQuick); + + // Now hook up the signals. For simplicy we don't differentiate between + // renderRequested (only render is needed, no sync) and sceneChanged (polish and sync + // is needed too). + connect(_renderControl, &QQuickRenderControl::renderRequested, this, &OffscreenUi::requestRender); + connect(_renderControl, &QQuickRenderControl::sceneChanged, this, &OffscreenUi::requestUpdate); + connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, [this](QObject *object){ + OffscreenUi * p = this; + qDebug() << "Focus changed to " << object; + }); + _quickWindow->focusObject(); + + _qmlComponent = new QQmlComponent(_qmlEngine); + + // Initialize the render control and our OpenGL resources. + makeCurrent(); + _renderControl->initialize(&_context); +} + +void OffscreenUi::resize(const QSize & newSize) { + makeCurrent(); + + // Clear out any fbos with the old size + _fboCache.setSize(newSize); + + // Update our members + if (_rootItem) { + _rootItem->setSize(newSize); + } + + if (_quickWindow) { + _quickWindow->setGeometry(QRect(QPoint(), newSize)); + } + + doneCurrent(); +} + +QQmlContext * OffscreenUi::qmlContext() { + if (nullptr == _rootItem) { + return _qmlComponent->creationContext(); + } + return QQmlEngine::contextForObject(_rootItem); +} + +void OffscreenUi::loadQml(const QUrl & qmlSource, std::function f) { + _qmlComponent->loadUrl(qmlSource); + if (_qmlComponent->isLoading()) + connect(_qmlComponent, &QQmlComponent::statusChanged, this, &OffscreenUi::finishQmlLoad); + else + finishQmlLoad(); +} + +void OffscreenUi::requestUpdate() { + _polish = true; + if (!_updateTimer.isActive()) + _updateTimer.start(); +} + +void OffscreenUi::requestRender() { + if (!_updateTimer.isActive()) + _updateTimer.start(); +} + +void OffscreenUi::finishQmlLoad() { + disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, &OffscreenUi::finishQmlLoad); + if (_qmlComponent->isError()) { + QList errorList = _qmlComponent->errors(); + foreach(const QQmlError &error, errorList) { + qWarning() << error.url() << error.line() << error; + } + return; + } + + QObject *rootObject = _qmlComponent->create(); + if (_qmlComponent->isError()) { + QList errorList = _qmlComponent->errors(); + foreach(const QQmlError &error, errorList) + qWarning() << error.url() << error.line() << error; + qFatal("Unable to finish loading QML"); + return; + } + + _rootItem = qobject_cast(rootObject); + if (!_rootItem) { + qWarning("run: Not a QQuickItem"); + delete rootObject; + qFatal("Unable to find root QQuickItem"); + return; + } + + // Make sure we can assign focus to the root item (critical for + // supporting keyboard shortcuts) + _rootItem->setFlag(QQuickItem::ItemIsFocusScope, true); + // The root item is ready. Associate it with the window. + _rootItem->setParentItem(_quickWindow->contentItem()); + _rootItem->setSize(_quickWindow->renderTargetSize()); + qDebug() << "Finished setting up QML provider"; +} + + +void OffscreenUi::updateQuick() { + if (_paused) { + return; + } + if (!makeCurrent()) + return; + + // Polish, synchronize and render the next frame (into our fbo). In this example + // everything happens on the same thread and therefore all three steps are performed + // in succession from here. In a threaded setup the render() call would happen on a + // separate thread. + if (_polish) { + _renderControl->polishItems(); + _renderControl->sync(); + _polish = false; + } + + QOpenGLFramebufferObject* fbo = _fboCache.getReadyFbo(); + + _quickWindow->setRenderTarget(fbo); + fbo->bind(); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + _renderControl->render(); + + Q_ASSERT(!glGetError()); + + _quickWindow->resetOpenGLState(); + + QOpenGLFramebufferObject::bindDefault(); + // Force completion of all the operations before we emit the texture as being ready for use + glFinish(); + + emit textureUpdated(fbo->texture()); +} + +QPointF OffscreenUi::mapWindowToUi(const QPointF & p, QObject * dest) { + vec2 sourceSize; + if (dynamic_cast(dest)) { + sourceSize = toGlm(((QWidget*)dest)->size()); + } else if (dynamic_cast(dest)) { + sourceSize = toGlm(((QWindow*)dest)->size()); + } + vec2 pos = toGlm(p); + pos /= sourceSize; + pos *= vec2(toGlm(_quickWindow->renderTargetSize())); + return QPointF(pos.x, pos.y); +} + +/////////////////////////////////////////////////////// +// +// Event handling customization +// + +bool OffscreenUi::eventFilter(QObject * dest, QEvent * e) { + // Only intercept events while we're in an active state + if (_paused) { + return false; + } + + // Don't intercept our own events, or we enter an infinite recursion + if (dest == _quickWindow) { + return false; + } + + switch (e->type()) { + case QEvent::Resize: + { + QResizeEvent * re = (QResizeEvent *)e; + QGLWidget * widget = dynamic_cast(dest); + if (widget) { + this->resize(re->size()); + } + return false; + } + + case QEvent::KeyPress: + case QEvent::KeyRelease: + { + e->ignore(); + if (QApplication::sendEvent(_quickWindow, e)) { + return e->isAccepted(); + } + } + break; + + case QEvent::Wheel: + { + QWheelEvent * we = (QWheelEvent*)e; + QWheelEvent mappedEvent(mapWindowToUi(we->pos(), dest), we->delta(), we->buttons(), we->modifiers(), we->orientation()); + QCoreApplication::sendEvent(_quickWindow, &mappedEvent); + return true; + } + break; + + // Fall through + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + { + QMouseEvent * me = (QMouseEvent *)e; + QPointF originalPos = me->localPos(); + QPointF transformedPos = _mouseTranslator(originalPos); + QMouseEvent mappedEvent(e->type(), mapWindowToUi(transformedPos, dest), me->screenPos(), me->button(), me->buttons(), me->modifiers()); + QCoreApplication::sendEvent(_quickWindow, &mappedEvent); + return QObject::event(e); + } + + default: break; + } + + return false; +} + +void OffscreenUi::lockTexture(int texture) { + _fboCache.lockTexture(texture); +} + +void OffscreenUi::releaseTexture(int texture) { + _fboCache.releaseTexture(texture); +} + +void OffscreenUi::pause() { + _paused = true; +} + +void OffscreenUi::resume() { + _paused = false; + requestRender(); +} + +bool OffscreenUi::isPaused() const { + return _paused; +} + +void OffscreenUi::setProxyWindow(QWindow * window) { + _renderControl->_renderWindow = window; +} + +void OffscreenUi::show(const QUrl & url, const QString & name) { + QQuickItem * item = _rootItem->findChild(name); + if (nullptr != item) { + item->setEnabled(true); + item->setVisible(true); + } else { + load(url); + } +} + +void OffscreenUi::toggle(const QUrl & url, const QString & name) { + QQuickItem * item = _rootItem->findChild(name); + // First load? + if (nullptr == item) { + load(url); + return; + } + + // Toggle the visibity AND the enabled flag (otherwise invisible + // dialogs can still swallow keyboard input) + bool newFlag = !item->isVisible(); + item->setVisible(newFlag); + item->setEnabled(newFlag); +} + + +void OffscreenUi::load(const QUrl & url) { + QVariant returnedValue; + QVariant msg = url; + QMetaObject::invokeMethod(_rootItem, "loadChild", + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, msg)); + qDebug() << "QML function returned:" << returnedValue.toString(); +} + diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h new file mode 100644 index 0000000000..2e8206f466 --- /dev/null +++ b/libraries/render-utils/src/OffscreenUi.h @@ -0,0 +1,136 @@ +// +// OffscreenUi.h +// interface/src/entities +// +// Created by Bradley Austin Davis on 2015-04-04 +// Copyright 2015 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 +// +#pragma once +#ifndef hifi_OffscreenUi_h +#define hifi_OffscreenUi_h + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FboCache.h" +#include "OffscreenGlCanvas.h" + +#define QML_DIALOG_DECL \ +private: \ + static const QString NAME; \ + static const QUrl QML; \ +public: \ + static void registerType(); \ + static void show(); \ + static void toggle(); \ +private: + +#define QML_DIALOG_DEF(x) \ + const QUrl x::QML = #x ".qml"; \ + const QString x::NAME = #x; \ + \ + void x::registerType() { \ + qmlRegisterType("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \ + } \ + \ + void x::show() { \ + auto offscreenUi = DependencyManager::get(); \ + offscreenUi->show(QML, NAME); \ + } \ + \ + void x::toggle() { \ + auto offscreenUi = DependencyManager::get(); \ + offscreenUi->toggle(QML, NAME); \ + } + + +class OffscreenUi : public OffscreenGlCanvas, public Dependency { + Q_OBJECT + + class QMyQuickRenderControl : public QQuickRenderControl { + protected: + QWindow * renderWindow(QPoint * offset) Q_DECL_OVERRIDE{ + if (nullptr == _renderWindow) { + return QQuickRenderControl::renderWindow(offset); + } + if (nullptr != offset) { + offset->rx() = offset->ry() = 0; + } + return _renderWindow; + } + + private: + QWindow * _renderWindow{ nullptr }; + friend class OffscreenUi; + }; + +public: + using MouseTranslator = std::function < QPointF(const QPointF &) > ; + OffscreenUi(); + virtual ~OffscreenUi(); + void create(QOpenGLContext * context); + void resize(const QSize & size); + void loadQml(const QUrl & qmlSource, std::function f = [](QQmlContext*) {}); + void load(const QUrl & url); + void show(const QUrl & url, const QString & name); + void toggle(const QUrl & url, const QString & name); + + QQmlContext * qmlContext(); + + void pause(); + void resume(); + bool isPaused() const; + void setProxyWindow(QWindow * window); + QPointF mapWindowToUi(const QPointF & p, QObject * dest); + virtual bool eventFilter(QObject * dest, QEvent * e); + void setMouseTranslator(MouseTranslator mt) { + _mouseTranslator = mt; + } + +protected: + +private slots: + void updateQuick(); + void finishQmlLoad(); + +public slots: + void requestUpdate(); + void requestRender(); + void lockTexture(int texture); + void releaseTexture(int texture); + +signals: + void textureUpdated(GLuint texture); + +private: + QMyQuickRenderControl *_renderControl{ new QMyQuickRenderControl }; + QQuickWindow *_quickWindow{ nullptr }; + QQmlEngine *_qmlEngine{ nullptr }; + QQmlComponent *_qmlComponent{ nullptr }; + QQuickItem * _rootItem{ nullptr }; + QTimer _updateTimer; + FboCache _fboCache; + bool _polish{ true }; + bool _paused{ true }; + MouseTranslator _mouseTranslator{ [](const QPointF & p) { return p; } }; +}; + +#endif \ No newline at end of file diff --git a/libraries/render-utils/src/RenderUtil.h b/libraries/render-utils/src/RenderUtil.h index b2f244733a..74d6c23791 100644 --- a/libraries/render-utils/src/RenderUtil.h +++ b/libraries/render-utils/src/RenderUtil.h @@ -15,4 +15,54 @@ /// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, tMin) to (sMax, tMax). void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f, float tMin = 0.0f, float tMax = 1.0f); +template +void withMatrixPush(F f) { + glMatrixMode(matrix); + glPushMatrix(); + f(); + glPopMatrix(); +} + +template +void withProjectionPush(F f) { + withMatrixPush(f); +} + +template +void withProjectionIdentity(F f) { + withProjectionPush([&] { + glLoadIdentity(); + f(); + }); +} + +template +void withProjectionMatrix(GLfloat * matrix, F f) { + withProjectionPush([&] { + glLoadMatrixf(matrix); + f(); + }); +} + +template +void withModelviewPush(F f) { + withMatrixPush(f); +} + +template +void withModelviewIdentity(F f) { + withModelviewPush([&] { + glLoadIdentity(); + f(); + }); +} + +template +void withModelviewMatrix(GLfloat * matrix, F f) { + withModelviewPush([&] { + glLoadMatrixf(matrix); + f(); + }); +} + #endif // hifi_RenderUtil_h diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 50393b7f5f..e5d22d67dc 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -17,6 +17,17 @@ #include #include +// Bring the most commonly used GLM types into the default namespace +using glm::ivec3; +using glm::ivec2; +using glm::uvec2; +using glm::mat3; +using glm::mat4; +using glm::vec2; +using glm::vec3; +using glm::vec4; +using glm::quat; + #include #include #include diff --git a/libraries/shared/src/ThreadHelpers.h b/libraries/shared/src/ThreadHelpers.h new file mode 100644 index 0000000000..862f7bf673 --- /dev/null +++ b/libraries/shared/src/ThreadHelpers.h @@ -0,0 +1,13 @@ +#pragma once +#include + +template +void withLock(L lock, F function) { + throw std::exception(); +} + +template +void withLock(QMutex & lock, F function) { + QMutexLocker locker(&lock); + function(); +} diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index b62ab68c22..304d6f1a07 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -10,6 +10,7 @@ #include "TextRenderer.h" #include "MatrixStack.h" +#include "OffscreenUi.h" #include #include @@ -21,9 +22,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -66,99 +69,143 @@ public: }; // Create a simple OpenGL window that renders text in various ways -class QTestWindow: public QWindow { +class QTestWindow : public QWindow { Q_OBJECT - QOpenGLContext * _context; + + QOpenGLContext * _context{ nullptr }; QSize _size; TextRenderer* _textRenderer[4]; RateCounter fps; + OffscreenUi _offscreenUi; + int testQmlTexture{ 0 }; + //ProgramPtr _planeProgam; + //ShapeWrapperPtr _planeShape; protected: - void resizeEvent(QResizeEvent * ev) override { - QWindow::resizeEvent(ev); - _size = ev->size(); - resizeGl(); - } - void resizeGl() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, _size.width(), _size.height(), 0, 1, -1); - glMatrixMode(GL_MODELVIEW); - glViewport(0, 0, _size.width(), _size.height()); + void renderText(); + void renderQml(); + +private: + void resizeWindow(const QSize & size) { + _size = size; + _offscreenUi.resize(_size); } public: - QTestWindow(); - virtual ~QTestWindow() { + QTestWindow() { + setSurfaceType(QSurface::OpenGLSurface); + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 5); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + format.setOption(QSurfaceFormat::DebugContext); + + setFormat(format); + + _context = new QOpenGLContext; + _context->setFormat(format); + _context->create(); + + show(); + makeCurrent(); + + { + QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this); + logger->initialize(); // initializes in the current context, i.e. ctx + logger->enableMessages(); + connect(logger, &QOpenGLDebugLogger::messageLogged, this, [&](const QOpenGLDebugMessage & debugMessage) { + qDebug() << debugMessage; + }); + // logger->startLogging(QOpenGLDebugLogger::SynchronousLogging); + } + qDebug() << (const char*)glGetString(GL_VERSION); + +#ifdef WIN32 + glewExperimental = true; + GLenum err = glewInit(); + if (GLEW_OK != err) { + /* Problem: glewInit failed, something is seriously wrong. */ + const GLubyte * errStr = glewGetErrorString(err); + qDebug("Error: %s\n", errStr); + } + qDebug("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); + + if (wglewGetExtension("WGL_EXT_swap_control")) { + int swapInterval = wglGetSwapIntervalEXT(); + qDebug("V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); + } + glGetError(); +#endif + + _textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false); + _textRenderer[1] = TextRenderer::getInstance(SERIF_FONT_FAMILY, 12, false, + TextRenderer::SHADOW_EFFECT); + _textRenderer[2] = TextRenderer::getInstance(MONO_FONT_FAMILY, 48, -1, + false, TextRenderer::OUTLINE_EFFECT); + _textRenderer[3] = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, 24); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClearColor(0.2f, 0.2f, 0.2f, 1); + glDisable(GL_DEPTH_TEST); + + _offscreenUi.create(_context); + // FIXME, need to switch to a QWindow for mouse and keyboard input to work + _offscreenUi.setProxyWindow(this); + // "#0e7077" + setFramePosition(QPoint(-1000, 0)); + resize(QSize(800, 600)); + + static const QString f("/Users/bdavis/Git/hifi/interface/resources/qml/Root.qml"); + _offscreenUi.loadQml(QUrl::fromLocalFile(f)); + connect(&_offscreenUi, &OffscreenUi::textureUpdated, this, [&](int textureId) { + _offscreenUi.lockTexture(textureId); + assert(!glGetError()); + GLuint oldTexture = testQmlTexture; + testQmlTexture = textureId; + if (oldTexture) { + _offscreenUi.releaseTexture(oldTexture); + } + }); + installEventFilter(&_offscreenUi); + _offscreenUi.resume(); } + + virtual ~QTestWindow() { + } + + void draw(); void makeCurrent() { _context->makeCurrent(this); } - void draw(); +protected: + + void resizeEvent(QResizeEvent * ev) override { + resizeWindow(ev->size()); + } + + + void keyPressEvent(QKeyEvent *event) { + switch (event->key()) { + case Qt::Key_Slash: + qDebug() << "Foo"; + _offscreenUi.load(QString("Login.qml")); + break; + } + QWindow::keyPressEvent(event); + } + }; #ifndef SERIF_FONT_FAMILY #define SERIF_FONT_FAMILY "Times New Roman" #endif -QTestWindow::QTestWindow() { - setSurfaceType(QSurface::OpenGLSurface); - - QSurfaceFormat format; - // Qt Quick may need a depth and stencil buffer. Always make sure these are available. - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setVersion(3, 2); - format.setProfile( - QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - setFormat(format); - - _context = new QOpenGLContext; - _context->setFormat(format); - _context->create(); - - show(); - makeCurrent(); - qDebug() << (const char*) glGetString(GL_VERSION); - -#ifdef WIN32 - glewExperimental = true; - GLenum err = glewInit(); - if (GLEW_OK != err) { - /* Problem: glewInit failed, something is seriously wrong. */ - const GLubyte * errStr = glewGetErrorString(err); - qDebug("Error: %s\n", errStr); - } - qDebug("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); - - if (wglewGetExtension("WGL_EXT_swap_control")) { - int swapInterval = wglGetSwapIntervalEXT(); - qDebug("V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); - } - glGetError(); -#endif - - setFramePosition(QPoint(100, -900)); - resize(QSize(800, 600)); - _size = QSize(800, 600); - - _textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false); - _textRenderer[1] = TextRenderer::getInstance(SERIF_FONT_FAMILY, 12, false, - TextRenderer::SHADOW_EFFECT); - _textRenderer[2] = TextRenderer::getInstance(MONO_FONT_FAMILY, 48, -1, - false, TextRenderer::OUTLINE_EFFECT); - _textRenderer[3] = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, 24); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glClearColor(0.2f, 0.2f, 0.2f, 1); - glDisable(GL_DEPTH_TEST); - resizeGl(); -} - static const wchar_t * EXAMPLE_TEXT = L"Hello"; //static const wchar_t * EXAMPLE_TEXT = L"\xC1y Hello 1.0\ny\xC1 line 2\n\xC1y"; static const glm::uvec2 QUAD_OFFSET(10, 10); @@ -166,14 +213,21 @@ static const glm::uvec2 QUAD_OFFSET(10, 10); static const glm::vec3 COLORS[4] = { { 1.0, 1.0, 1.0 }, { 0.5, 1.0, 0.5 }, { 1.0, 0.5, 0.5 }, { 0.5, 0.5, 1.0 } }; -void QTestWindow::draw() { - makeCurrent(); - glClear(GL_COLOR_BUFFER_BIT); +void QTestWindow::renderText() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, _size.width(), _size.height(), 0, 1, -1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); const glm::uvec2 size = glm::uvec2(_size.width() / 2, _size.height() / 2); - const glm::uvec2 offsets[4] = { { QUAD_OFFSET.x, QUAD_OFFSET.y }, { size.x - + QUAD_OFFSET.x, QUAD_OFFSET.y }, { size.x + QUAD_OFFSET.x, size.y - + QUAD_OFFSET.y }, { QUAD_OFFSET.x, size.y + QUAD_OFFSET.y }, }; + + const glm::uvec2 offsets[4] = { + { QUAD_OFFSET.x, QUAD_OFFSET.y }, + { size.x + QUAD_OFFSET.x, QUAD_OFFSET.y }, + { size.x + QUAD_OFFSET.x, size.y + QUAD_OFFSET.y }, + { QUAD_OFFSET.x, size.y + QUAD_OFFSET.y }, + }; QString str = QString::fromWCharArray(EXAMPLE_TEXT); for (int i = 0; i < 4; ++i) { @@ -200,17 +254,57 @@ void QTestWindow::draw() { glm::vec4(COLORS[i], 1.0f)); } } +} + +void QTestWindow::renderQml() { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + if (testQmlTexture > 0) { + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, testQmlTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + glBegin(GL_QUADS); + { + + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(0, 1); + glVertex2f(-1, 1); + glTexCoord2f(1, 1); + glVertex2f(1, 1); + glTexCoord2f(1, 0); + glVertex2f(1, -1); + } + glEnd(); +} + +void QTestWindow::draw() { + makeCurrent(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, _size.width(), _size.height()); + + renderText(); + //renderQml(); + _context->swapBuffers(this); glFinish(); + fps.increment(); if (fps.elapsed() >= 2.0f) { - qDebug() << "FPS: " << fps.rate(); + //qDebug() << "FPS: " << fps.rate(); fps.reset(); } } int main(int argc, char** argv) { QApplication app(argc, argv); + //QLoggingCategory::setFilterRules("qt.quick.mouse.debug = true"); QTestWindow window; QTimer timer; timer.setInterval(1); From aba2b395a6769bd91df352506e63fd47391e240c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Apr 2015 12:35:30 -0700 Subject: [PATCH 02/74] Working on testing the QML ui --- interface/resources/qml/Palettes.qml | 236 +++++++++++++++++++++ interface/resources/qml/TestDialog.qml | 112 ++++++++++ interface/resources/qml/TestRoot.qml | 26 +++ interface/src/ui/ApplicationOverlay.h | 3 +- libraries/render-utils/src/OffscreenUi.cpp | 5 +- tests/render-utils/src/main.cpp | 11 +- 6 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 interface/resources/qml/Palettes.qml create mode 100644 interface/resources/qml/TestDialog.qml create mode 100644 interface/resources/qml/TestRoot.qml diff --git a/interface/resources/qml/Palettes.qml b/interface/resources/qml/Palettes.qml new file mode 100644 index 0000000000..c4b0953df7 --- /dev/null +++ b/interface/resources/qml/Palettes.qml @@ -0,0 +1,236 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.3 + +Rectangle { + color: "teal" + height: 512 + width: 192 + SystemPalette { id: sp; colorGroup: SystemPalette.Active } + SystemPalette { id: spi; colorGroup: SystemPalette.Inactive } + SystemPalette { id: spd; colorGroup: SystemPalette.Disabled } + + Column { + anchors.margins: 8 + anchors.fill: parent + spacing: 8 + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "base" } + Rectangle { height: parent.height; width: 16; color: sp.base } + Rectangle { height: parent.height; width: 16; color: spi.base } + Rectangle { height: parent.height; width: 16; color: spd.base } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "alternateBase" } + Rectangle { height: parent.height; width: 16; color: sp.alternateBase } + Rectangle { height: parent.height; width: 16; color: spi.alternateBase } + Rectangle { height: parent.height; width: 16; color: spd.alternateBase } + } + Item { + height: 16 + width:parent.width + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "dark" } + Rectangle { height: parent.height; width: 16; color: sp.dark } + Rectangle { height: parent.height; width: 16; color: spi.dark } + Rectangle { height: parent.height; width: 16; color: spd.dark } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "mid" } + Rectangle { height: parent.height; width: 16; color: sp.mid } + Rectangle { height: parent.height; width: 16; color: spi.mid } + Rectangle { height: parent.height; width: 16; color: spd.mid } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "mid light" } + Rectangle { height: parent.height; width: 16; color: sp.midlight } + Rectangle { height: parent.height; width: 16; color: spi.midlight } + Rectangle { height: parent.height; width: 16; color: spd.midlight } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "light" } + Rectangle { height: parent.height; width: 16; color: sp.light} + Rectangle { height: parent.height; width: 16; color: spi.light} + Rectangle { height: parent.height; width: 16; color: spd.light} + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "shadow" } + Rectangle { height: parent.height; width: 16; color: sp.shadow} + Rectangle { height: parent.height; width: 16; color: spi.shadow} + Rectangle { height: parent.height; width: 16; color: spd.shadow} + } + Item { + height: 16 + width:parent.width + } + + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "text" } + Rectangle { height: parent.height; width: 16; color: sp.text } + Rectangle { height: parent.height; width: 16; color: spi.text } + Rectangle { height: parent.height; width: 16; color: spd.text } + } + Item { + height: 16 + width:parent.width + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "window" } + Rectangle { height: parent.height; width: 16; color: sp.window } + Rectangle { height: parent.height; width: 16; color: spi.window } + Rectangle { height: parent.height; width: 16; color: spd.window } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "window text" } + Rectangle { height: parent.height; width: 16; color: sp.windowText } + Rectangle { height: parent.height; width: 16; color: spi.windowText } + Rectangle { height: parent.height; width: 16; color: spd.windowText } + } + Item { + height: 16 + width:parent.width + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "button" } + Rectangle { height: parent.height; width: 16; color: sp.button } + Rectangle { height: parent.height; width: 16; color: spi.button } + Rectangle { height: parent.height; width: 16; color: spd.button } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "buttonText" } + Rectangle { height: parent.height; width: 16; color: sp.buttonText } + Rectangle { height: parent.height; width: 16; color: spi.buttonText } + Rectangle { height: parent.height; width: 16; color: spd.buttonText } + } + Item { + height: 16 + width:parent.width + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "highlight" } + Rectangle { height: parent.height; width: 16; color: sp.highlight } + Rectangle { height: parent.height; width: 16; color: spi.highlight } + Rectangle { height: parent.height; width: 16; color: spd.highlight } + } + Row { + width: parent.width + height: 16 + Text { height: parent.height; width: 128; text: "highlighted text" } + Rectangle { height: parent.height; width: 16; color: sp.highlightedText} + Rectangle { height: parent.height; width: 16; color: spi.highlightedText} + Rectangle { height: parent.height; width: 16; color: spd.highlightedText} + } + } + + +/* + CustomDialog { + title: "Test Dlg" + anchors.fill: parent + + Rectangle { + property int d: 100 + id: square + objectName: "testRect" + width: d + height: d + anchors.centerIn: parent + color: "red" + NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; } + } + + + CustomTextEdit { + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + clip: true + text: "test edit" + anchors.top: parent.top + anchors.topMargin: parent.titleSize + 12 + } + + CustomButton { + x: 128 + y: 192 + anchors.bottom: parent.bottom + anchors.bottomMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + onClicked: { + console.log("Click"); + if (square.visible) { + square.visible = false + } else { + square.visible = true + } + } + } + + CustomButton { + id: customButton2 + y: 192 + text: "Close" + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.bottom: parent.bottom + anchors.bottomMargin: 12 + onClicked: { + onClicked: testDialog.x == 0 ? testDialog.x = 200 : testDialog.x = 0 + } + } + + Keys.onPressed: { + console.log("Key " + event.key); + switch (event.key) { + case Qt.Key_Q: + if (Qt.ControlModifier == event.modifiers) { + event.accepted = true; + break; + } + } + } + } +*/ + +} + + +/* + +// This is the behavior, and it applies a NumberAnimation to any attempt to set the x property + +MouseArea { + anchors.fill: parent +} +*/ diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml new file mode 100644 index 0000000000..9c8bcccd75 --- /dev/null +++ b/interface/resources/qml/TestDialog.qml @@ -0,0 +1,112 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.3 + +Item { + objectName: "TestDialog" + id: testDialog + width: 384 + height: 384 + scale: 0.0 + + onEnabledChanged: { + scale = enabled ? 1.0 : 0.0 + } + onScaleChanged: { + visible = (scale != 0.0); + } + Component.onCompleted: { + scale = 1.0 + } + Behavior on scale { + NumberAnimation { + //This specifies how long the animation takes + duration: 400 + //This selects an easing curve to interpolate with, the default is Easing.Linear + easing.type: Easing.InOutBounce + } + } + + CustomDialog { + title: "Test Dlg" + anchors.fill: parent + + Rectangle { + property int d: 100 + id: square + objectName: "testRect" + width: d + height: d + anchors.centerIn: parent + color: "red" + NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; } + } + + + CustomTextEdit { + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + clip: true + text: "test edit" + anchors.top: parent.top + anchors.topMargin: parent.titleSize + 12 + } + + CustomButton { + x: 128 + y: 192 + anchors.bottom: parent.bottom + anchors.bottomMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + onClicked: { + console.log("Click"); + if (square.visible) { + square.visible = false + } else { + square.visible = true + } + } + } + + CustomButton { + id: customButton2 + y: 192 + text: "Close" + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.bottom: parent.bottom + anchors.bottomMargin: 12 + onClicked: { + onClicked: testDialog.x == 0 ? testDialog.x = 200 : testDialog.x = 0 + } + } + + Keys.onPressed: { + console.log("Key " + event.key); + switch (event.key) { + case Qt.Key_Q: + if (Qt.ControlModifier == event.modifiers) { + event.accepted = true; + break; + } + } + } + } + + +} + + +/* + +// This is the behavior, and it applies a NumberAnimation to any attempt to set the x property + +MouseArea { + anchors.fill: parent +} +*/ diff --git a/interface/resources/qml/TestRoot.qml b/interface/resources/qml/TestRoot.qml new file mode 100644 index 0000000000..a3ef5f8fe9 --- /dev/null +++ b/interface/resources/qml/TestRoot.qml @@ -0,0 +1,26 @@ +import QtQuick 2.3 +import "componentCreation.js" as Creator + + +Item { + id: root + width: 1280 + height: 720 + + function loadChild(url) { + Creator.createObject(root, url) + } + + + CustomButton { + anchors.right: parent.right + anchors.rightMargin: 24 + anchors.bottom: parent.bottom + anchors.bottomMargin: 24 + text: "Test" + onClicked: { + loadChild("TestDialog.qml"); + } + } +} + diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index cc4188e8ef..e6c7526c5d 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -23,7 +23,8 @@ const float MAGNIFY_MULT = 2.0f; const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; // Handles the drawing of the overlays to the screen -class ApplicationOverlay { +class ApplicationOverlay : public QObject { + Q_OBJECT public: ApplicationOverlay(); ~ApplicationOverlay(); diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index cb57d86412..718a70f4e1 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -308,9 +308,10 @@ void OffscreenUi::toggle(const QUrl & url, const QString & name) { // Toggle the visibity AND the enabled flag (otherwise invisible // dialogs can still swallow keyboard input) - bool newFlag = !item->isVisible(); - item->setVisible(newFlag); + bool newFlag = !item->isEnabled(); item->setEnabled(newFlag); + // item->setVisible(newFlag); + } diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 304d6f1a07..dd413a9f57 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -160,7 +160,7 @@ public: setFramePosition(QPoint(-1000, 0)); resize(QSize(800, 600)); - static const QString f("/Users/bdavis/Git/hifi/interface/resources/qml/Root.qml"); + static const QString f("/Users/bdavis/Git/hifi/interface/resources/qml/TestRoot.qml"); _offscreenUi.loadQml(QUrl::fromLocalFile(f)); connect(&_offscreenUi, &OffscreenUi::textureUpdated, this, [&](int textureId) { _offscreenUi.lockTexture(textureId); @@ -193,8 +193,7 @@ protected: void keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Slash: - qDebug() << "Foo"; - _offscreenUi.load(QString("Login.qml")); + _offscreenUi.toggle(QString("TestDialog.qml"), "TestDialog"); break; } QWindow::keyPressEvent(event); @@ -289,15 +288,15 @@ void QTestWindow::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, _size.width(), _size.height()); - renderText(); - //renderQml(); + //renderText(); + renderQml(); _context->swapBuffers(this); glFinish(); fps.increment(); if (fps.elapsed() >= 2.0f) { - //qDebug() << "FPS: " << fps.rate(); + qDebug() << "FPS: " << fps.rate(); fps.reset(); } } From f700607a65c7cfe9087e360cef921964092d9078 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 15 Apr 2015 23:00:10 -0700 Subject: [PATCH 03/74] Working on OSX functionality --- interface/resources/qml/CustomDialog.qml | 1 - interface/src/Application.cpp | 1 + libraries/render-utils/src/FboCache.h | 1 + .../render-utils/src/OffscreenGlCanvas.cpp | 18 ++++++++++-------- libraries/render-utils/src/OffscreenUi.h | 2 +- tests/render-utils/src/main.cpp | 9 +++++++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/CustomDialog.qml b/interface/resources/qml/CustomDialog.qml index 71f36b4108..828cd80231 100644 --- a/interface/resources/qml/CustomDialog.qml +++ b/interface/resources/qml/CustomDialog.qml @@ -11,7 +11,6 @@ Item { id: dialog width: 256 height: 256 - property rect clientArea: clientBorder property int topMargin: dialog.height - clientBorder.height + 8 property int margins: 8 property string title diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0f75de9696..36b4eaec91 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -650,6 +650,7 @@ Application::~Application() { // stop the glWidget frame timer so it doesn't call paintGL _glWidget->stopFrameTimer(); + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); diff --git a/libraries/render-utils/src/FboCache.h b/libraries/render-utils/src/FboCache.h index bbbb4a943e..975d602278 100644 --- a/libraries/render-utils/src/FboCache.h +++ b/libraries/render-utils/src/FboCache.h @@ -17,6 +17,7 @@ #include #include #include +#include class QOpenGLFramebufferObject; diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index 694fa68a5a..d6b268d4e9 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -16,16 +16,18 @@ OffscreenGlCanvas::OffscreenGlCanvas() { } void OffscreenGlCanvas::create(QOpenGLContext * sharedContext) { - QSurfaceFormat format; - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setMajorVersion(4); - format.setMinorVersion(1); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - - _context.setFormat(format); if (nullptr != sharedContext) { + sharedContext->doneCurrent(); + _context.setFormat(sharedContext->format()); _context.setShareContext(sharedContext); + } else { + QSurfaceFormat format; + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setMajorVersion(4); + format.setMinorVersion(1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + _context.setFormat(format); } _context.create(); diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index 2e8206f466..60302d9860 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -44,7 +44,7 @@ public: \ private: #define QML_DIALOG_DEF(x) \ - const QUrl x::QML = #x ".qml"; \ + const QUrl x::QML = QUrl(#x ".qml"); \ const QString x::NAME = #x; \ \ void x::registerType() { \ diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index dd413a9f57..62c1fcf1c5 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -31,6 +31,7 @@ #include #include #include +#include class RateCounter { std::vector times; @@ -159,8 +160,12 @@ public: // "#0e7077" setFramePosition(QPoint(-1000, 0)); resize(QSize(800, 600)); - - static const QString f("/Users/bdavis/Git/hifi/interface/resources/qml/TestRoot.qml"); + + QApplication::applicationDirPath(); + QDir path(__FILE__); + path.cdUp(); + static const QString f(path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/TestRoot.qml"))); + _offscreenUi.loadQml(QUrl::fromLocalFile(f)); connect(&_offscreenUi, &OffscreenUi::textureUpdated, this, [&](int textureId) { _offscreenUi.lockTexture(textureId); From 36ca9132cc97ed13f4af50b2401b58104a3361ea Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 16 Apr 2015 01:02:13 -0700 Subject: [PATCH 04/74] More build failure fixes --- libraries/render-utils/src/OffscreenUi.cpp | 10 ++++++++++ libraries/shared/src/ThreadHelpers.h | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index 718a70f4e1..d0e54b08a9 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -1,3 +1,13 @@ +// +// OffscreenUi.cpp +// interface/src/render-utils +// +// Created by Bradley Austin Davis on 2015-04-04 +// Copyright 2015 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 "OffscreenUi.h" #include #include diff --git a/libraries/shared/src/ThreadHelpers.h b/libraries/shared/src/ThreadHelpers.h index 862f7bf673..8a64691da7 100644 --- a/libraries/shared/src/ThreadHelpers.h +++ b/libraries/shared/src/ThreadHelpers.h @@ -1,5 +1,19 @@ +// +// ThreadHelpers.h +// +// Created by Bradley Austin Davis on 2015-04-04 +// Copyright 2015 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 +// #pragma once +#ifndef hifi_ThreadHelpers_h +#define hifi_ThreadHelpers_h + #include +#include +#include template void withLock(L lock, F function) { @@ -11,3 +25,5 @@ void withLock(QMutex & lock, F function) { QMutexLocker locker(&lock); function(); } + +#endif \ No newline at end of file From a624ff43c4c891b179be56e6b159b3d3a2f421f7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 16 Apr 2015 14:10:29 -0700 Subject: [PATCH 05/74] Nothing to see here, move along --- interface/src/Menu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index aa24c8ca2c..5d02cf9094 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -251,7 +251,6 @@ Menu::Menu() { qApp, SLOT(setFullscreen(bool))); #endif -<<<<<<< HEAD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, 0, // QML Qt::Key_P, true, qApp, SLOT(cameraMenuChanged())); From 759acfa17539865d6b34ebc517951637af39c7d7 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 16 Apr 2015 19:07:21 -0700 Subject: [PATCH 06/74] Working on getting the offscreen UI working on retina --- interface/src/Application.cpp | 12 +++++++++++- libraries/render-utils/src/OffscreenUi.cpp | 18 ++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 930e244136..d0ae13ce21 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -764,6 +764,16 @@ void Application::initializeUi() { return QPointF(p); }); offscreenUi->resume(); + connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect & r){ + static qreal oldDevicePixelRatio = 0; + qreal devicePixelRatio = _glWidget->devicePixelRatio(); + if (devicePixelRatio != oldDevicePixelRatio) { + oldDevicePixelRatio = devicePixelRatio; + qDebug() << "Device pixel ratio changed, triggering GL resize"; + resizeGL(_glWidget->width(), + _glWidget->height()); + } + }); } void Application::paintGL() { @@ -906,7 +916,7 @@ void Application::resizeGL(int width, int height) { glLoadIdentity(); auto offscreenUi = DependencyManager::get(); - offscreenUi->resize(QSize(width, height)); + offscreenUi->resize(_glWidget->size()); // update Stats width // let's set horizontal offset to give stats some margin to mirror diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index d0e54b08a9..d2d314bf96 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -79,7 +79,8 @@ void OffscreenUi::resize(const QSize & newSize) { makeCurrent(); // Clear out any fbos with the old size - _fboCache.setSize(newSize); + qreal pixelRatio = _renderControl->_renderWindow ? _renderControl->_renderWindow->devicePixelRatio() : 1.0; + _fboCache.setSize(newSize * pixelRatio); // Update our members if (_rootItem) { @@ -203,7 +204,7 @@ QPointF OffscreenUi::mapWindowToUi(const QPointF & p, QObject * dest) { } vec2 pos = toGlm(p); pos /= sourceSize; - pos *= vec2(toGlm(_quickWindow->renderTargetSize())); + pos *= vec2(toGlm(_quickWindow->size())); return QPointF(pos.x, pos.y); } @@ -300,11 +301,13 @@ void OffscreenUi::setProxyWindow(QWindow * window) { void OffscreenUi::show(const QUrl & url, const QString & name) { QQuickItem * item = _rootItem->findChild(name); + if (nullptr == item) { + load(url); + item = _rootItem->findChild(name); + } + if (nullptr != item) { item->setEnabled(true); - item->setVisible(true); - } else { - load(url); } } @@ -312,7 +315,7 @@ void OffscreenUi::toggle(const QUrl & url, const QString & name) { QQuickItem * item = _rootItem->findChild(name); // First load? if (nullptr == item) { - load(url); + show(url, name); return; } @@ -320,12 +323,11 @@ void OffscreenUi::toggle(const QUrl & url, const QString & name) { // dialogs can still swallow keyboard input) bool newFlag = !item->isEnabled(); item->setEnabled(newFlag); - // item->setVisible(newFlag); - } void OffscreenUi::load(const QUrl & url) { + qDebug() << "Loading from url: " << url; QVariant returnedValue; QVariant msg = url; QMetaObject::invokeMethod(_rootItem, "loadChild", From fd0c130dc2ea6d302d8eeea7c93f1ab9a6286f77 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 16 Apr 2015 22:20:49 -0700 Subject: [PATCH 07/74] Working on simplifying new dialog creation --- interface/resources/qml/AddressBarDialog.qml | 85 +++--- interface/resources/qml/CustomDialog.qml | 35 ++- interface/resources/qml/LoginDialog.qml | 286 +++++++++--------- interface/src/ui/AddressBarDialog.cpp | 6 +- interface/src/ui/AddressBarDialog.h | 8 +- interface/src/ui/LoginDialog.cpp | 5 +- interface/src/ui/LoginDialog.h | 8 +- .../render-utils/src/OffscreenQmlDialog.cpp | 18 ++ .../render-utils/src/OffscreenQmlDialog.h | 56 ++++ libraries/render-utils/src/OffscreenUi.h | 30 +- 10 files changed, 290 insertions(+), 247 deletions(-) create mode 100644 libraries/render-utils/src/OffscreenQmlDialog.cpp create mode 100644 libraries/render-utils/src/OffscreenQmlDialog.h diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index df06fabbe6..9508481309 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -4,8 +4,9 @@ import QtQuick.Controls 1.2 import QtQuick.Window 2.2 import QtQuick.Controls.Styles 1.3 -AddressBarDialog { - id: addressBarDialog +CustomDialog { + id: dialog + title: "Go to..." objectName: "AddressBarDialog" SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } height: 128 @@ -14,70 +15,56 @@ AddressBarDialog { onVisibleChanged: { if (!visible) { reset(); - } else { - addressLine.focus = true - addressLine.forceActiveFocus() } } - Component.onCompleted: { - addressLine.focus = true - addressLine.forceActiveFocus() - } - function reset() { addressLine.text = "" goButton.source = "../images/address-bar-submit.svg" } - CustomDialog { - id: dialog - anchors.fill: parent - title: "Go to..." + AddressBarDialog { + id: addressBarDialog // The client area - Item { - id: item1 - anchors.fill: parent - anchors.margins: parent.margins - anchors.topMargin: parent.topMargin + anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin - CustomBorder { - height: 64 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.right: goButton.left - anchors.rightMargin: 8 - anchors.verticalCenter: parent.verticalCenter - CustomTextInput { - id: addressLine - anchors.fill: parent - helperText: "domain, location, @user, /x,y,z" - anchors.margins: 8 - onAccepted: { - addressBarDialog.loadAddress(addressLine.text) - } + CustomBorder { + height: 64 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.right: goButton.left + anchors.rightMargin: 8 + anchors.verticalCenter: parent.verticalCenter + CustomTextInput { + id: addressLine + anchors.fill: parent + helperText: "domain, location, @user, /x,y,z" + anchors.margins: 8 + onAccepted: { + addressBarDialog.loadAddress(addressLine.text) } } + } - Image { - id: goButton - width: 32 - height: 32 - anchors.right: parent.right - anchors.rightMargin: 8 - source: "../images/address-bar-submit.svg" - anchors.verticalCenter: parent.verticalCenter + Image { + id: goButton + width: 32 + height: 32 + anchors.right: parent.right + anchors.rightMargin: 8 + source: "../images/address-bar-submit.svg" + anchors.verticalCenter: parent.verticalCenter - MouseArea { - anchors.fill: parent - onClicked: { - parent.source = "../images/address-bar-submit-active.svg" - addressBarDialog.loadAddress(addressLine.text) - } + MouseArea { + anchors.fill: parent + onClicked: { + parent.source = "../images/address-bar-submit-active.svg" + addressBarDialog.loadAddress(addressLine.text) } } - } } } diff --git a/interface/resources/qml/CustomDialog.qml b/interface/resources/qml/CustomDialog.qml index 828cd80231..a681612f2c 100644 --- a/interface/resources/qml/CustomDialog.qml +++ b/interface/resources/qml/CustomDialog.qml @@ -7,10 +7,34 @@ import "hifiConstants.js" as HifiConstants Item { SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } - id: dialog width: 256 height: 256 + scale: 0.0 + enabled: false + visible: false + + onEnabledChanged: { + scale = enabled ? 1.0 : 0.0 + } + + onScaleChanged: { + visible = (scale != 0.0); + } + + Component.onCompleted: { + scale = 1.0 + } + + Behavior on scale { + NumberAnimation { + //This specifies how long the animation takes + duration: 400 + //This selects an easing curve to interpolate with, the default is Easing.Linear + easing.type: Easing.InOutBounce + } + } + property int topMargin: dialog.height - clientBorder.height + 8 property int margins: 8 property string title @@ -54,11 +78,11 @@ Item { anchors.top: parent.top anchors.rightMargin: 4 drag { - target: dialog.parent + target: dialog minimumX: 0 minimumY: 0 - maximumX: dialog.parent.parent.width - dialog.parent.width - maximumY: dialog.parent.parent.height - dialog.parent.height + maximumX: dialog.parent.width - dialog.width + maximumY: dialog.parent.height - dialog.height } } Image { @@ -73,11 +97,10 @@ Item { MouseArea { anchors.fill: parent onClicked: { - dialog.parent.destroy() + dialog.destroy() } } } - } // header border CustomBorder { diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index c306f4ed7e..e96309f625 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -5,9 +5,9 @@ import QtQuick.Window 2.2 import QtQuick.Controls.Styles 1.3 import "hifiConstants.js" as HifiConstants -LoginDialog { +CustomDialog { + title: "Login" SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } - id: loginDialog objectName: "LoginDialog" height: 512 width: 384 @@ -15,8 +15,6 @@ LoginDialog { onVisibleChanged: { if (!visible) { reset() - } else { - username.forceActiveFocus() } } @@ -26,163 +24,159 @@ LoginDialog { loginDialog.statusText = "" } - CustomDialog { + LoginDialog { + id: loginDialog anchors.fill: parent - title: "Login" - Item { - id: item1 - anchors.fill: parent - anchors.margins: parent.margins - anchors.topMargin: parent.topMargin - Column { - anchors.topMargin: 8 - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.top: parent.top - spacing: 8 + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin + Column { + anchors.topMargin: 8 + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.top: parent.top + spacing: 8 - Image { - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - width: 64 - source: "../images/hifi-logo.svg" - } + Image { + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + width: 64 + source: "../images/hifi-logo.svg" + } - CustomBorder { - width: 304 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - CustomTextInput { - id: username - anchors.fill: parent - helperText: "Username or Email" - anchors.margins: 8 - KeyNavigation.tab: password - KeyNavigation.backtab: password - onAccepted: { - password.forceActiveFocus() - } + CustomBorder { + width: 304 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + CustomTextInput { + id: username + anchors.fill: parent + helperText: "Username or Email" + anchors.margins: 8 + KeyNavigation.tab: password + KeyNavigation.backtab: password + onAccepted: { + password.forceActiveFocus() } } - - CustomBorder { - width: 304 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - CustomTextInput { - id: password - anchors.fill: parent - echoMode: TextInput.Password - helperText: "Password" - anchors.margins: 8 - KeyNavigation.tab: username - KeyNavigation.backtab: username - onAccepted: { - if (username.text == "") { - username.forceActiveFocus() - } else { - loginDialog.login(username.text, password.text) - } - } - onFocusChanged: { - if (password.focus) { - password.selectAll() - } - } - } - } - - CustomText { - anchors.horizontalCenter: parent.horizontalCenter - textFormat: Text.StyledText - width: parent.width - height: 96 - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: loginDialog.statusText - } } - Column { - anchors.bottomMargin: 5 - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.bottom: parent.bottom - - Rectangle { - width: 192 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - color: HifiConstants.color - border.width: 0 - radius: 10 - - MouseArea { - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - anchors.top: parent.top - anchors.right: parent.right - anchors.left: parent.left - onClicked: { + CustomBorder { + width: 304 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + CustomTextInput { + id: password + anchors.fill: parent + echoMode: TextInput.Password + helperText: "Password" + anchors.margins: 8 + KeyNavigation.tab: username + KeyNavigation.backtab: username + onAccepted: { + if (username.text == "") { + username.forceActiveFocus() + } else { loginDialog.login(username.text, password.text) } } - - Row { - anchors.centerIn: parent - anchors.verticalCenter: parent.verticalCenter - spacing: 8 - Image { - id: loginIcon - height: 32 - width: 32 - source: "../images/login.svg" - } - CustomText { - text: "Login" - color: "white" - width: 64 - height: parent.height - } - } - - } - - CustomText { - width: parent.width - height: 24 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text:"Create Account" - font.pointSize: 12 - font.bold: true - color: HifiConstants.color - - MouseArea { - anchors.fill: parent - onClicked: { - loginDialog.openUrl(loginDialog.rootUrl + "/signup") + onFocusChanged: { + if (password.focus) { + password.selectAll() } } } + } - CustomText { - width: parent.width - height: 24 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pointSize: 12 - text: "Recover Password" - color: HifiConstants.color + CustomText { + anchors.horizontalCenter: parent.horizontalCenter + textFormat: Text.StyledText + width: parent.width + height: 96 + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: loginDialog.statusText + } + } - MouseArea { - anchors.fill: parent - onClicked: { - loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") - } + Column { + anchors.bottomMargin: 5 + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.bottom: parent.bottom + + Rectangle { + width: 192 + height: 64 + anchors.horizontalCenter: parent.horizontalCenter + color: HifiConstants.color + border.width: 0 + radius: 10 + + MouseArea { + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + onClicked: { + loginDialog.login(username.text, password.text) + } + } + + Row { + anchors.centerIn: parent + anchors.verticalCenter: parent.verticalCenter + spacing: 8 + Image { + id: loginIcon + height: 32 + width: 32 + source: "../images/login.svg" + } + CustomText { + text: "Login" + color: "white" + width: 64 + height: parent.height + } + } + + } + + CustomText { + width: parent.width + height: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text:"Create Account" + font.pointSize: 12 + font.bold: true + color: HifiConstants.color + + MouseArea { + anchors.fill: parent + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/signup") + } + } + } + + CustomText { + width: parent.width + height: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pointSize: 12 + text: "Recover Password" + color: HifiConstants.color + + MouseArea { + anchors.fill: parent + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") } } } diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 49158265ba..befeb40cce 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -17,17 +17,15 @@ QML_DIALOG_DEF(AddressBarDialog) -AddressBarDialog::AddressBarDialog(QQuickItem *parent) : QQuickItem(parent) { +AddressBarDialog::AddressBarDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { auto addressManager = DependencyManager::get(); connect(addressManager.data(), &AddressManager::lookupResultIsOffline, this, &AddressBarDialog::displayAddressOfflineMessage); connect(addressManager.data(), &AddressManager::lookupResultIsNotFound, this, &AddressBarDialog::displayAddressNotFoundMessage); connect(addressManager.data(), &AddressManager::lookupResultsFinished, this, &AddressBarDialog::hide); } - void AddressBarDialog::hide() { - setEnabled(false); - setVisible(false); + ((QQuickItem *)parent())->setEnabled(false); } void AddressBarDialog::loadAddress(const QString & address) { diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index 00e55ceb10..b4f4c44e0f 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -8,15 +8,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#pragma once #ifndef hifi_AddressBarDialog_h #define hifi_AddressBarDialog_h -#pragma once -#include +#include -#include "OffscreenUi.h" - -class AddressBarDialog : public QQuickItem +class AddressBarDialog : public OffscreenQmlDialog { Q_OBJECT QML_DIALOG_DECL diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 3b164041fa..3637d824fb 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -17,7 +17,7 @@ QML_DIALOG_DEF(LoginDialog) -LoginDialog::LoginDialog(QQuickItem *parent) : QQuickItem(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { +LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { connect(&AccountManager::getInstance(), &AccountManager::loginComplete, this, &LoginDialog::handleLoginCompleted); connect(&AccountManager::getInstance(), &AccountManager::loginFailed, @@ -42,8 +42,7 @@ void LoginDialog::toggleAction() { } void LoginDialog::handleLoginCompleted(const QUrl& authURL) { - setEnabled(false); - setVisible(false); + hide(); } void LoginDialog::handleLoginFailed() { diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 3c9a98a9a4..d3f54981a5 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -8,15 +8,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#pragma once #ifndef hifi_LoginDialog_h #define hifi_LoginDialog_h -#pragma once -#include +#include -#include "OffscreenUi.h" - -class LoginDialog : public QQuickItem +class LoginDialog : public OffscreenQmlDialog { Q_OBJECT QML_DIALOG_DECL diff --git a/libraries/render-utils/src/OffscreenQmlDialog.cpp b/libraries/render-utils/src/OffscreenQmlDialog.cpp new file mode 100644 index 0000000000..d6cfc9951b --- /dev/null +++ b/libraries/render-utils/src/OffscreenQmlDialog.cpp @@ -0,0 +1,18 @@ +// +// OffscreenQmlDialog.cpp +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 "OffscreenQmlDialog.h" + +OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem *parent) + : QQuickItem(parent) { } + +void OffscreenQmlDialog::hide() { + ((QQuickItem *)parent())->setEnabled(false); +} diff --git a/libraries/render-utils/src/OffscreenQmlDialog.h b/libraries/render-utils/src/OffscreenQmlDialog.h new file mode 100644 index 0000000000..6e94587fd2 --- /dev/null +++ b/libraries/render-utils/src/OffscreenQmlDialog.h @@ -0,0 +1,56 @@ +// +// OffscreenQmlDialog.h +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 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 +// + +#pragma once +#ifndef hifi_OffscreenQmlDialog_h +#define hifi_OffscreenQmlDialog_h + +#include +#include "OffscreenUi.h" + +#define QML_DIALOG_DECL \ +private: \ + static const QString NAME; \ + static const QUrl QML; \ +public: \ + static void registerType(); \ + static void show(); \ + static void toggle(); \ +private: + +#define QML_DIALOG_DEF(x) \ + const QUrl x::QML = QUrl(#x ".qml"); \ + const QString x::NAME = #x; \ + \ + void x::registerType() { \ + qmlRegisterType("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \ + } \ + \ + void x::show() { \ + auto offscreenUi = DependencyManager::get(); \ + offscreenUi->show(QML, NAME); \ + } \ + \ + void x::toggle() { \ + auto offscreenUi = DependencyManager::get(); \ + offscreenUi->toggle(QML, NAME); \ + } + +class OffscreenQmlDialog : public QQuickItem +{ + Q_OBJECT +public: + OffscreenQmlDialog(QQuickItem *parent = 0); + +protected: + void hide(); +}; + +#endif diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index 60302d9860..b9cf5d2226 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -33,34 +33,6 @@ #include "FboCache.h" #include "OffscreenGlCanvas.h" -#define QML_DIALOG_DECL \ -private: \ - static const QString NAME; \ - static const QUrl QML; \ -public: \ - static void registerType(); \ - static void show(); \ - static void toggle(); \ -private: - -#define QML_DIALOG_DEF(x) \ - const QUrl x::QML = QUrl(#x ".qml"); \ - const QString x::NAME = #x; \ - \ - void x::registerType() { \ - qmlRegisterType("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \ - } \ - \ - void x::show() { \ - auto offscreenUi = DependencyManager::get(); \ - offscreenUi->show(QML, NAME); \ - } \ - \ - void x::toggle() { \ - auto offscreenUi = DependencyManager::get(); \ - offscreenUi->toggle(QML, NAME); \ - } - class OffscreenUi : public OffscreenGlCanvas, public Dependency { Q_OBJECT @@ -133,4 +105,4 @@ private: MouseTranslator _mouseTranslator{ [](const QPointF & p) { return p; } }; }; -#endif \ No newline at end of file +#endif From 781abdd0473048c007be81e6cab4c2c92e7eafab Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 17 Apr 2015 09:53:40 -0700 Subject: [PATCH 08/74] Tweaking test dialog and adding browser test --- interface/resources/qml/Browser.qml | 45 ++++++++++++++++++++++++++ interface/resources/qml/TestDialog.qml | 40 ++++++++--------------- 2 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 interface/resources/qml/Browser.qml diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml new file mode 100644 index 0000000000..d7e08fbd97 --- /dev/null +++ b/interface/resources/qml/Browser.qml @@ -0,0 +1,45 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.3 +import QtWebKit 3.0 + +CustomDialog { + title: "Test Dlg" + id: testDialog + objectName: "Browser" + width: 1280 + height: 720 + + Item { + id: clientArea + // The client area + anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin + + + ScrollView { + anchors.fill: parent + WebView { + id: webview + url: "http://slashdot.org" + anchors.fill: parent + } + } + + } + + +} + + +/* + +// This is the behavior, and it applies a NumberAnimation to any attempt to set the x property + +MouseArea { + anchors.fill: parent +} +*/ diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml index 9c8bcccd75..8ce68413b6 100644 --- a/interface/resources/qml/TestDialog.qml +++ b/interface/resources/qml/TestDialog.qml @@ -4,34 +4,20 @@ import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Controls.Styles 1.3 -Item { - objectName: "TestDialog" +CustomDialog { + title: "Test Dlg" id: testDialog - width: 384 - height: 384 + objectName: "TestDialog" + width: 512 + height: 512 scale: 0.0 - onEnabledChanged: { - scale = enabled ? 1.0 : 0.0 - } - onScaleChanged: { - visible = (scale != 0.0); - } - Component.onCompleted: { - scale = 1.0 - } - Behavior on scale { - NumberAnimation { - //This specifies how long the animation takes - duration: 400 - //This selects an easing curve to interpolate with, the default is Easing.Linear - easing.type: Easing.InOutBounce - } - } - - CustomDialog { - title: "Test Dlg" + Item { + id: clientArea + // The client area anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin Rectangle { property int d: 100 @@ -55,16 +41,18 @@ Item { anchors.top: parent.top anchors.topMargin: parent.titleSize + 12 } - + CustomButton { x: 128 y: 192 + text: "Test" anchors.bottom: parent.bottom anchors.bottomMargin: 12 anchors.right: parent.right anchors.rightMargin: 12 onClicked: { console.log("Click"); + if (square.visible) { square.visible = false } else { @@ -76,7 +64,7 @@ Item { CustomButton { id: customButton2 y: 192 - text: "Close" + text: "Move" anchors.left: parent.left anchors.leftMargin: 12 anchors.bottom: parent.bottom From ad585f75595f323507d1314d4ea13dccf4f47d24 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 17 Apr 2015 10:05:54 -0700 Subject: [PATCH 09/74] Fixing NaN reference in test dialog --- interface/resources/qml/TestDialog.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml index 8ce68413b6..69aad4cdc8 100644 --- a/interface/resources/qml/TestDialog.qml +++ b/interface/resources/qml/TestDialog.qml @@ -10,7 +10,6 @@ CustomDialog { objectName: "TestDialog" width: 512 height: 512 - scale: 0.0 Item { id: clientArea @@ -39,7 +38,7 @@ CustomDialog { clip: true text: "test edit" anchors.top: parent.top - anchors.topMargin: parent.titleSize + 12 + anchors.topMargin: 12 } CustomButton { @@ -86,7 +85,6 @@ CustomDialog { } } - } From 4b73481604890e76f0df7ee57618839b995ed8c8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 17 Apr 2015 10:19:31 -0700 Subject: [PATCH 10/74] Respond to changes in the device pixel ratio in the test window --- libraries/render-utils/src/OffscreenUi.cpp | 1 + tests/render-utils/src/main.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index d2d314bf96..68bb3eeacd 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -80,6 +80,7 @@ void OffscreenUi::resize(const QSize & newSize) { // Clear out any fbos with the old size qreal pixelRatio = _renderControl->_renderWindow ? _renderControl->_renderWindow->devicePixelRatio() : 1.0; + qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio; _fboCache.setSize(newSize * pixelRatio); // Update our members diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 62c1fcf1c5..556fef0561 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -203,7 +203,16 @@ protected: } QWindow::keyPressEvent(event); } - + + void moveEvent(QMoveEvent *event) { + static qreal oldPixelRatio = 0.0; + if (devicePixelRatio() != oldPixelRatio) { + oldPixelRatio = devicePixelRatio(); + resizeWindow(size()); + } + + QWindow::moveEvent(event); + } }; #ifndef SERIF_FONT_FAMILY @@ -291,7 +300,7 @@ void QTestWindow::renderQml() { void QTestWindow::draw() { makeCurrent(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, _size.width(), _size.height()); + glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio()); //renderText(); renderQml(); From 16efa2a46fc850772b1723e502421afa1924954a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 17 Apr 2015 16:58:29 -0700 Subject: [PATCH 11/74] Improving toggle visibility and loading behavior --- interface/resources/qml/AddressBarDialog.qml | 9 +- interface/resources/qml/CustomDialog.qml | 26 +++- interface/resources/qml/LoginDialog.qml | 6 + interface/resources/qml/Root.qml | 9 +- interface/resources/qml/TestDialog.qml | 10 +- interface/resources/qml/TestRoot.qml | 25 ++-- interface/resources/qml/componentCreation.js | 4 +- interface/src/Application.cpp | 4 +- interface/src/ui/AddressBarDialog.cpp | 7 +- libraries/render-utils/src/OffscreenUi.cpp | 133 +++++++++++++------ libraries/render-utils/src/OffscreenUi.h | 50 +++++-- tests/render-utils/src/main.cpp | 46 ++++--- 12 files changed, 231 insertions(+), 98 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 9508481309..ec1480928a 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -5,16 +5,21 @@ import QtQuick.Window 2.2 import QtQuick.Controls.Styles 1.3 CustomDialog { - id: dialog title: "Go to..." objectName: "AddressBarDialog" - SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } height: 128 width: 512 + destroyOnCloseButton: false onVisibleChanged: { if (!visible) { reset(); + } + } + + onEnabledChanged: { + if (enabled) { + addressLine.forceActiveFocus(); } } diff --git a/interface/resources/qml/CustomDialog.qml b/interface/resources/qml/CustomDialog.qml index a681612f2c..dd051566e3 100644 --- a/interface/resources/qml/CustomDialog.qml +++ b/interface/resources/qml/CustomDialog.qml @@ -12,7 +12,9 @@ Item { height: 256 scale: 0.0 enabled: false - visible: false + property int animationDuration: 400 + property bool destroyOnInvisible: false + property bool destroyOnCloseButton: true onEnabledChanged: { scale = enabled ? 1.0 : 0.0 @@ -22,14 +24,24 @@ Item { visible = (scale != 0.0); } - Component.onCompleted: { - scale = 1.0 + onVisibleChanged: { + if (!visible && destroyOnInvisible) { + console.log("Destroying closed component"); + destroy(); + } + } + + function close() { + if (destroyOnCloseButton) { + destroyOnInvisible = true + } + enabled = false; } Behavior on scale { NumberAnimation { //This specifies how long the animation takes - duration: 400 + duration: dialog.animationDuration //This selects an easing curve to interpolate with, the default is Easing.Linear easing.type: Easing.InOutBounce } @@ -81,8 +93,8 @@ Item { target: dialog minimumX: 0 minimumY: 0 - maximumX: dialog.parent.width - dialog.width - maximumY: dialog.parent.height - dialog.height + maximumX: dialog.parent ? dialog.parent.width - dialog.width : 0 + maximumY: dialog.parent ? dialog.parent.height - dialog.height : 0 } } Image { @@ -97,7 +109,7 @@ Item { MouseArea { anchors.fill: parent onClicked: { - dialog.destroy() + dialog.close(); } } } diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index e96309f625..be69b65ef7 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -18,6 +18,12 @@ CustomDialog { } } + onEnabledChanged: { + if (enabled) { + username.forceActiveFocus(); + } + } + function reset() { username.text = "" password.text = "" diff --git a/interface/resources/qml/Root.qml b/interface/resources/qml/Root.qml index f290a8b5ca..9422ef123d 100644 --- a/interface/resources/qml/Root.qml +++ b/interface/resources/qml/Root.qml @@ -1,14 +1,9 @@ +import Hifi 1.0 import QtQuick 2.3 -import "componentCreation.js" as Creator - -Item { +Root { id: root width: 1280 height: 720 - - function loadChild(url) { - Creator.createObject(root, url) - } } diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml index 69aad4cdc8..1fe8676bc6 100644 --- a/interface/resources/qml/TestDialog.qml +++ b/interface/resources/qml/TestDialog.qml @@ -5,12 +5,19 @@ import QtQuick.Dialogs 1.2 import QtQuick.Controls.Styles 1.3 CustomDialog { - title: "Test Dlg" + title: "Test Dialog" id: testDialog objectName: "TestDialog" width: 512 height: 512 + animationDuration: 200 + onEnabledChanged: { + if (enabled) { + edit.forceActiveFocus(); + } + } + Item { id: clientArea // The client area @@ -31,6 +38,7 @@ CustomDialog { CustomTextEdit { + id: edit anchors.left: parent.left anchors.leftMargin: 12 anchors.right: parent.right diff --git a/interface/resources/qml/TestRoot.qml b/interface/resources/qml/TestRoot.qml index a3ef5f8fe9..158c0b7a54 100644 --- a/interface/resources/qml/TestRoot.qml +++ b/interface/resources/qml/TestRoot.qml @@ -1,25 +1,34 @@ +import Hifi 1.0 import QtQuick 2.3 -import "componentCreation.js" as Creator - -Item { +Root { id: root width: 1280 height: 720 - function loadChild(url) { - Creator.createObject(root, url) + CustomButton { + id: messageBox + anchors.right: createDialog.left + anchors.rightMargin: 24 + anchors.bottom: parent.bottom + anchors.bottomMargin: 24 + text: "Message" + onClicked: { + console.log("Foo") + root.information("a") + console.log("Bar") + } } - CustomButton { + id: createDialog anchors.right: parent.right anchors.rightMargin: 24 anchors.bottom: parent.bottom anchors.bottomMargin: 24 - text: "Test" + text: "Create" onClicked: { - loadChild("TestDialog.qml"); + root.loadChild("TestDialog.qml"); } } } diff --git a/interface/resources/qml/componentCreation.js b/interface/resources/qml/componentCreation.js index 6e6469adfb..15a828d6f8 100644 --- a/interface/resources/qml/componentCreation.js +++ b/interface/resources/qml/componentCreation.js @@ -18,10 +18,12 @@ function finishCreation() { // Error Handling console.log("Error creating object"); } else { - instance.focus = true; + instance.enabled = true } } else if (component.status == Component.Error) { // Error Handling console.log("Error loading component:", component.errorString()); + } else { + console.log("Unknown component status: " + component.status); } } \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d0ae13ce21..18a325080c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -754,8 +754,8 @@ void Application::initializeUi() { offscreenUi->create(_glWidget->context()->contextHandle()); offscreenUi->resize(_glWidget->size()); offscreenUi->setProxyWindow(_window->windowHandle()); - auto rootQml = PathUtils::resourcesPath() + "qml/Root.qml"; - offscreenUi->loadQml(QUrl::fromLocalFile(rootQml)); + offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); + offscreenUi->load("Root.qml"); offscreenUi->setMouseTranslator([this](const QPointF& p){ if (OculusManager::isConnected()) { glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p)); diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index befeb40cce..5ef9b930ac 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -35,14 +35,13 @@ void AddressBarDialog::loadAddress(const QString & address) { } } -// TODO port to a QML based message box void AddressBarDialog::displayAddressOfflineMessage() { - QMessageBox::information(nullptr, "Address offline", + OffscreenUi::information("Address offline", "That user or place is currently offline."); } -// TODO port to a QML based message box void AddressBarDialog::displayAddressNotFoundMessage() { - QMessageBox::information(nullptr, "Address not found", + OffscreenUi::information("Address not found", "There is no address information for that user or place."); } + diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index 68bb3eeacd..d9dd030758 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -12,8 +12,29 @@ #include #include #include +#include + +class OffscreenUiRoot : public QQuickItem { + Q_OBJECT +public: + + OffscreenUiRoot(QQuickItem *parent = 0); + Q_INVOKABLE void information(const QString & title, const QString & text); + Q_INVOKABLE void loadChild(const QUrl & url) { + DependencyManager::get()->load(url); + } +}; + + +OffscreenUiRoot::OffscreenUiRoot(QQuickItem *parent) : QQuickItem(parent) { +} + +void OffscreenUiRoot::information(const QString & title, const QString & text = "foo") { + OffscreenUi::information(title, text); +} OffscreenUi::OffscreenUi() { + ::qmlRegisterType("Hifi", 1, 0, "Root"); } OffscreenUi::~OffscreenUi() { @@ -62,19 +83,18 @@ void OffscreenUi::create(QOpenGLContext * shareContext) { // is needed too). connect(_renderControl, &QQuickRenderControl::renderRequested, this, &OffscreenUi::requestRender); connect(_renderControl, &QQuickRenderControl::sceneChanged, this, &OffscreenUi::requestUpdate); - connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, [this](QObject *object){ - OffscreenUi * p = this; - qDebug() << "Focus changed to " << object; - }); _quickWindow->focusObject(); _qmlComponent = new QQmlComponent(_qmlEngine); - // Initialize the render control and our OpenGL resources. makeCurrent(); _renderControl->initialize(&_context); } +void OffscreenUi::addImportPath(const QString & path) { + _qmlEngine->addImportPath(path); +} + void OffscreenUi::resize(const QSize & newSize) { makeCurrent(); @@ -102,10 +122,15 @@ QQmlContext * OffscreenUi::qmlContext() { return QQmlEngine::contextForObject(_rootItem); } -void OffscreenUi::loadQml(const QUrl & qmlSource, std::function f) { +void OffscreenUi::setBaseUrl(const QUrl & baseUrl) { + _qmlEngine->setBaseUrl(baseUrl); +} + +void OffscreenUi::load(const QUrl & qmlSource, std::function f) { + qDebug() << "Loading QML from URL " << qmlSource; _qmlComponent->loadUrl(qmlSource); if (_qmlComponent->isLoading()) - connect(_qmlComponent, &QQmlComponent::statusChanged, this, &OffscreenUi::finishQmlLoad); + connect(_qmlComponent, &QQmlComponent::statusChanged, this, [] {}); else finishQmlLoad(); } @@ -131,30 +156,43 @@ void OffscreenUi::finishQmlLoad() { return; } - QObject *rootObject = _qmlComponent->create(); + QObject *newObject = _qmlComponent->create(); if (_qmlComponent->isError()) { QList errorList = _qmlComponent->errors(); foreach(const QQmlError &error, errorList) qWarning() << error.url() << error.line() << error; - qFatal("Unable to finish loading QML"); + if (!_rootItem) { + qFatal("Unable to finish loading QML root"); + } return; } - _rootItem = qobject_cast(rootObject); - if (!_rootItem) { + QQuickItem * newItem = qobject_cast(newObject); + if (!newItem) { qWarning("run: Not a QQuickItem"); - delete rootObject; - qFatal("Unable to find root QQuickItem"); + delete newObject; + if (!_rootItem) { + qFatal("Unable to find root QQuickItem"); + } return; } - // Make sure we can assign focus to the root item (critical for + // Make sure we make items focusable (critical for // supporting keyboard shortcuts) - _rootItem->setFlag(QQuickItem::ItemIsFocusScope, true); - // The root item is ready. Associate it with the window. - _rootItem->setParentItem(_quickWindow->contentItem()); - _rootItem->setSize(_quickWindow->renderTargetSize()); - qDebug() << "Finished setting up QML provider"; + newItem->setFlag(QQuickItem::ItemIsFocusScope, true); + + if (!_rootItem) { + // The root item is ready. Associate it with the window. + _rootItem = newItem; + _rootItem->setParentItem(_quickWindow->contentItem()); + _rootItem->setSize(_quickWindow->renderTargetSize()); + } else { + // Allow child windows to be destroyed from JS + QQmlEngine::setObjectOwnership(newItem, QQmlEngine::JavaScriptOwnership); + newItem->setParent(_rootItem); + newItem->setParentItem(_rootItem); + newItem->setEnabled(true); + } } @@ -240,7 +278,7 @@ bool OffscreenUi::eventFilter(QObject * dest, QEvent * e) { case QEvent::KeyRelease: { e->ignore(); - if (QApplication::sendEvent(_quickWindow, e)) { + if (QCoreApplication::sendEvent(_quickWindow, e)) { return e->isAccepted(); } } @@ -302,38 +340,55 @@ void OffscreenUi::setProxyWindow(QWindow * window) { void OffscreenUi::show(const QUrl & url, const QString & name) { QQuickItem * item = _rootItem->findChild(name); + // First load? if (nullptr == item) { load(url); - item = _rootItem->findChild(name); - } - - if (nullptr != item) { - item->setEnabled(true); + return; } + item->setEnabled(true); } void OffscreenUi::toggle(const QUrl & url, const QString & name) { QQuickItem * item = _rootItem->findChild(name); // First load? if (nullptr == item) { - show(url, name); + load(url); return; } + item->setEnabled(!item->isEnabled()); +} - // Toggle the visibity AND the enabled flag (otherwise invisible - // dialogs can still swallow keyboard input) - bool newFlag = !item->isEnabled(); - item->setEnabled(newFlag); +void OffscreenUi::messageBox(const QString &title, const QString &text, + QMessageBox::Icon icon, + QMessageBox::StandardButtons buttons, + ButtonCallback f) { +} + +void OffscreenUi::information(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + ButtonCallback callback) { + callback(QMessageBox::information(nullptr, title, text, buttons)); +} + +void OffscreenUi::question(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + ButtonCallback callback) { + callback(QMessageBox::question(nullptr, title, text, buttons)); +} + +void OffscreenUi::warning(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + ButtonCallback callback) { + callback(QMessageBox::warning(nullptr, title, text, buttons)); +} + +void OffscreenUi::critical(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + ButtonCallback callback) { + callback(QMessageBox::critical(nullptr, title, text, buttons)); } -void OffscreenUi::load(const QUrl & url) { - qDebug() << "Loading from url: " << url; - QVariant returnedValue; - QVariant msg = url; - QMetaObject::invokeMethod(_rootItem, "loadChild", - Q_RETURN_ARG(QVariant, returnedValue), - Q_ARG(QVariant, msg)); - qDebug() << "QML function returned:" << returnedValue.toString(); -} +OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {}; +#include "OffscreenUi.moc" \ No newline at end of file diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index b9cf5d2226..73c022e4be 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -12,26 +12,25 @@ #ifndef hifi_OffscreenUi_h #define hifi_OffscreenUi_h - -#include -#include #include #include #include #include #include #include -#include -#include -#include #include -#include +#include + #include #include + +#include +#include #include -#include "FboCache.h" #include "OffscreenGlCanvas.h" +#include "FboCache.h" +#include class OffscreenUi : public OffscreenGlCanvas, public Dependency { @@ -60,11 +59,14 @@ public: virtual ~OffscreenUi(); void create(QOpenGLContext * context); void resize(const QSize & size); - void loadQml(const QUrl & qmlSource, std::function f = [](QQmlContext*) {}); - void load(const QUrl & url); + void load(const QUrl & qmlSource, std::function f = [](QQmlContext*) {}); + void load(const QString & qmlSourceFile, std::function f = [](QQmlContext*) {}) { + load(QUrl(qmlSourceFile), f); + } void show(const QUrl & url, const QString & name); void toggle(const QUrl & url, const QString & name); - + void setBaseUrl(const QUrl & baseUrl); + void addImportPath(const QString & path); QQmlContext * qmlContext(); void pause(); @@ -77,6 +79,32 @@ public: _mouseTranslator = mt; } + + // Messagebox replacement functions + using ButtonCallback = std::function < void(QMessageBox::StandardButton) >; + static ButtonCallback NO_OP_CALLBACK; + + static void messageBox(const QString &title, const QString &text, + QMessageBox::Icon icon, + QMessageBox::StandardButtons buttons, + ButtonCallback f); + + static void information(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + ButtonCallback callback = NO_OP_CALLBACK); + + static void question(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), + ButtonCallback callback = [](QMessageBox::StandardButton) {}); + + static void warning(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + ButtonCallback callback = [](QMessageBox::StandardButton) {}); + + static void critical(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + ButtonCallback callback = [](QMessageBox::StandardButton) {}); + protected: private slots: diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 556fef0561..eb61fd1f72 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -69,6 +69,17 @@ public: } }; + +const QString & getQmlDir() { + static QString dir; + if (dir.isEmpty()) { + QDir path(__FILE__); + path.cdUp(); + dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/")) + "/"; + qDebug() << "Qml Path: " << dir; + } + return dir; +} // Create a simple OpenGL window that renders text in various ways class QTestWindow : public QWindow { Q_OBJECT @@ -77,7 +88,6 @@ class QTestWindow : public QWindow { QSize _size; TextRenderer* _textRenderer[4]; RateCounter fps; - OffscreenUi _offscreenUi; int testQmlTexture{ 0 }; //ProgramPtr _planeProgam; //ShapeWrapperPtr _planeShape; @@ -90,11 +100,12 @@ protected: private: void resizeWindow(const QSize & size) { _size = size; - _offscreenUi.resize(_size); + DependencyManager::get()->resize(_size); } public: QTestWindow() { + DependencyManager::set(); setSurfaceType(QSurface::OpenGLSurface); QSurfaceFormat format; @@ -154,30 +165,30 @@ public: glClearColor(0.2f, 0.2f, 0.2f, 1); glDisable(GL_DEPTH_TEST); - _offscreenUi.create(_context); + auto offscreenUi = DependencyManager::get(); + offscreenUi->create(_context); // FIXME, need to switch to a QWindow for mouse and keyboard input to work - _offscreenUi.setProxyWindow(this); + offscreenUi->setProxyWindow(this); // "#0e7077" setFramePosition(QPoint(-1000, 0)); resize(QSize(800, 600)); - QApplication::applicationDirPath(); - QDir path(__FILE__); - path.cdUp(); - static const QString f(path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/TestRoot.qml"))); + offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir())); + offscreenUi->load(QUrl("TestRoot.qml")); + offscreenUi->addImportPath(getQmlDir()); + offscreenUi->addImportPath("."); - _offscreenUi.loadQml(QUrl::fromLocalFile(f)); - connect(&_offscreenUi, &OffscreenUi::textureUpdated, this, [&](int textureId) { - _offscreenUi.lockTexture(textureId); + connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [this, offscreenUi](int textureId) { + offscreenUi->lockTexture(textureId); assert(!glGetError()); GLuint oldTexture = testQmlTexture; testQmlTexture = textureId; if (oldTexture) { - _offscreenUi.releaseTexture(oldTexture); + offscreenUi->releaseTexture(oldTexture); } }); - installEventFilter(&_offscreenUi); - _offscreenUi.resume(); + installEventFilter(offscreenUi.data()); + offscreenUi->resume(); } virtual ~QTestWindow() { @@ -197,8 +208,10 @@ protected: void keyPressEvent(QKeyEvent *event) { switch (event->key()) { - case Qt::Key_Slash: - _offscreenUi.toggle(QString("TestDialog.qml"), "TestDialog"); + case Qt::Key_L: + if (event->modifiers() & Qt::CTRL) { + DependencyManager::get()->toggle(QString("TestDialog.qml"), "TestDialog"); + } break; } QWindow::keyPressEvent(event); @@ -319,6 +332,7 @@ int main(int argc, char** argv) { QApplication app(argc, argv); //QLoggingCategory::setFilterRules("qt.quick.mouse.debug = true"); QTestWindow window; + QTimer timer; timer.setInterval(1); app.connect(&timer, &QTimer::timeout, &app, [&] { From 8d23bf874f325cdcd375e5fe6e86d62a26f36858 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 17 Apr 2015 17:43:54 -0700 Subject: [PATCH 12/74] Enable resizable dialogs --- interface/resources/qml/CustomDialog.qml | 34 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/CustomDialog.qml b/interface/resources/qml/CustomDialog.qml index dd051566e3..1e0351af4f 100644 --- a/interface/resources/qml/CustomDialog.qml +++ b/interface/resources/qml/CustomDialog.qml @@ -15,6 +15,10 @@ Item { property int animationDuration: 400 property bool destroyOnInvisible: false property bool destroyOnCloseButton: true + property bool resizable: false + property int minX: 256 + property int minY: 256 + clip: true onEnabledChanged: { scale = enabled ? 1.0 : 0.0 @@ -37,6 +41,11 @@ Item { } enabled = false; } + + function deltaSize(dx, dy) { + width = Math.max(width + dx, minX) + height = Math.max(height + dy, minY) + } Behavior on scale { NumberAnimation { @@ -82,8 +91,6 @@ Item { MouseArea { id: titleDrag - property int startX - property int startY anchors.right: closeButton.left anchors.bottom: parent.bottom anchors.left: parent.left @@ -127,6 +134,29 @@ Item { anchors.rightMargin: 0 anchors.left: parent.left anchors.leftMargin: 0 + clip: true } // client border } // window border + + MouseArea { + id: sizeDrag + property int startX + property int startY + anchors.right: parent.right + anchors.bottom: parent.bottom + width: 16 + height: 16 + hoverEnabled: true + onPressed: { + startX = mouseX + startY = mouseY + } + onPositionChanged: { + if (pressed && dialog.resizable) { + dialog.deltaSize((mouseX - startX), (mouseY - startY)) + startX = mouseX + startY = mouseY + } + } + } } From 8268dc95ac58e1429167ef367232f02e20b71a0a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Apr 2015 10:28:17 -0700 Subject: [PATCH 13/74] Include DDE reset in sensors reset --- interface/src/Application.cpp | 1 - interface/src/Menu.cpp | 5 ----- interface/src/Menu.h | 1 - interface/src/devices/DdeFaceTracker.cpp | 6 +++++- interface/src/devices/DdeFaceTracker.h | 3 +-- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0227003cb1..7741faad68 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1750,7 +1750,6 @@ void Application::setActiveFaceTracker() { #ifdef HAVE_DDE bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); Menu::getInstance()->getActionForOption(MenuOption::DDEFiltering)->setVisible(isUsingDDE); - Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); DependencyManager::get()->setEnabled(isUsingDDE); #endif #ifdef HAVE_VISAGE diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b07d122aee..c6dceb2ee5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -388,11 +388,6 @@ Menu::Menu() { faceTrackingMenu->addSeparator(); QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFiltering, 0, true); ddeFiltering->setVisible(false); - QAction* ddeFaceTrackerReset = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::ResetDDETracking, - Qt::CTRL | Qt::Key_Apostrophe, - DependencyManager::get().data(), SLOT(resetTracking())); - ddeFaceTrackerReset->setVisible(false); - faceTrackingMenu->addAction(ddeFaceTrackerReset); #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3d10d20f1b..58efc1b4da 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -223,7 +223,6 @@ namespace MenuOption { const QString RenderAmbientLight8 = "CAMPUS_SUNSET"; const QString RenderAmbientLight9 = "FUNSTON_BEACH_SUNSET"; const QString ResetAvatarSize = "Reset Avatar Size"; - const QString ResetDDETracking = "Reset DDE Tracking"; const QString ResetSensors = "Reset Sensors"; const QString RunningScripts = "Running Scripts"; const QString RunTimingTests = "Run Timing Tests"; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 50601421c2..c4f22a31a9 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -222,10 +222,14 @@ void DdeFaceTracker::processFinished(int exitCode, QProcess::ExitStatus exitStat } } -void DdeFaceTracker::resetTracking() { +void DdeFaceTracker::reset() { + _reset = true; + qDebug() << "[Info] Reset DDE Tracking"; const char* DDE_RESET_COMMAND = "reset"; _udpSocket.writeDatagram(DDE_RESET_COMMAND, DDE_SERVER_ADDR, _controlPort); + + _reset = true; } bool DdeFaceTracker::isActive() const { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index aa3e9f3b81..506e2974b6 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -28,7 +28,7 @@ class DdeFaceTracker : public FaceTracker, public Dependency { SINGLETON_DEPENDENCY public: - virtual void reset() { _reset = true; } + virtual void reset(); virtual bool isActive() const; virtual bool isTracking() const { return isActive(); } @@ -50,7 +50,6 @@ public: public slots: void setEnabled(bool enabled); - void resetTracking(); private slots: void processFinished(int exitCode, QProcess::ExitStatus exitStatus); From 766087c032e0e35287d6349109d391946e7f3700 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Apr 2015 10:29:53 -0700 Subject: [PATCH 14/74] Run DDE "readonly" Try to fix some people having to run Interface in admin mode on Windows --- interface/src/devices/DdeFaceTracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c4f22a31a9..938cee729f 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -200,7 +200,7 @@ void DdeFaceTracker::setEnabled(bool enabled) { qDebug() << "[Info] DDE Face Tracker Starting"; _ddeProcess = new QProcess(qApp); connect(_ddeProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); - _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS); + _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS, QIODevice::ReadOnly); } if (!enabled && _ddeProcess) { From a9c2a6e0486c2dde52ec59ad42cce456c9f4bc28 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 20 Apr 2015 18:17:21 -0700 Subject: [PATCH 15/74] another attempt at zones starting from box --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 +++- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityTypes.cpp | 5 +++-- libraries/entities/src/EntityTypes.h | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index da972b3843..132feff7e3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -30,9 +30,10 @@ #include "RenderableBoxEntityItem.h" #include "RenderableLightEntityItem.h" #include "RenderableModelEntityItem.h" +#include "RenderableParticleEffectEntityItem.h" #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" -#include "RenderableParticleEffectEntityItem.h" +#include "RenderableZoneEntityItem.h" #include "EntitiesRendererLogging.h" @@ -56,6 +57,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory) _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 7de0fc0e8b..0bc0bcedc7 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -137,6 +137,7 @@ class EntityItemProperties { friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods friend class TextEntityItem; // TODO: consider removing this friend relationship and use public methods friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods + friend class ZoneEntityItem; // TODO: consider removing this friend relationship and use public methods public: EntityItemProperties(); virtual ~EntityItemProperties(); diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 55e9512f53..f0baa3da93 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -21,9 +21,10 @@ #include "BoxEntityItem.h" #include "LightEntityItem.h" #include "ModelEntityItem.h" +#include "ParticleEffectEntityItem.h" #include "SphereEntityItem.h" #include "TextEntityItem.h" -#include "ParticleEffectEntityItem.h" +#include "ZoneEntityItem.h" QMap EntityTypes::_typeToNameMap; QMap EntityTypes::_nameToTypeMap; @@ -39,7 +40,7 @@ REGISTER_ENTITY_TYPE(Sphere) REGISTER_ENTITY_TYPE(Light) REGISTER_ENTITY_TYPE(Text) REGISTER_ENTITY_TYPE(ParticleEffect) - +REGISTER_ENTITY_TYPE(Zone) const QString& EntityTypes::getEntityTypeName(EntityType entityType) { QMap::iterator matchedTypeName = _typeToNameMap.find(entityType); diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index e1f8e876bb..28cfe2278b 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -36,7 +36,8 @@ public: Light, Text, ParticleEffect, - LAST = ParticleEffect + Zone, + LAST = Zone } EntityType; static const QString& getEntityTypeName(EntityType entityType); From 8ce4cb628a9c74015bc559e6915f1e966d1f5859 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 20 Apr 2015 18:18:01 -0700 Subject: [PATCH 16/74] another attempt at zones starting from box --- .../src/RenderableZoneEntityItem.cpp | 50 +++++++ .../src/RenderableZoneEntityItem.h | 29 +++++ libraries/entities/src/ZoneEntityItem.cpp | 122 ++++++++++++++++++ libraries/entities/src/ZoneEntityItem.h | 62 +++++++++ 4 files changed, 263 insertions(+) create mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.cpp create mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.h create mode 100644 libraries/entities/src/ZoneEntityItem.cpp create mode 100644 libraries/entities/src/ZoneEntityItem.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp new file mode 100644 index 0000000000..6a16404f89 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -0,0 +1,50 @@ +// +// RenderableZoneEntityItem.cpp +// interface/src +// +// Created by Brad Hefta-Gaub on 8/6/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 + +#include + +#include +#include + +#include "RenderableZoneEntityItem.h" + +EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + return new RenderableZoneEntityItem(entityID, properties); +} + +void RenderableZoneEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableZoneEntityItem::render"); + assert(getType() == EntityTypes::Zone); + glm::vec3 position = getPosition(); + glm::vec3 center = getCenter(); + glm::vec3 dimensions = getDimensions(); + glm::quat rotation = getRotation(); + + const float MAX_COLOR = 255.0f; + + glm::vec4 cubeColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, + getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + DependencyManager::get()->renderWireCube(1.0f, cubeColor); + glPopMatrix(); + glPopMatrix(); + +}; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h new file mode 100644 index 0000000000..b05fd0e3f8 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -0,0 +1,29 @@ +// +// RenderableZoneEntityItem.h +// interface/src/entities +// +// Created by Brad Hefta-Gaub on 8/6/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_RenderableZoneEntityItem_h +#define hifi_RenderableZoneEntityItem_h + +#include + +class RenderableZoneEntityItem : public ZoneEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + ZoneEntityItem(entityItemID, properties) + { } + + virtual void render(RenderArgs* args); +}; + + +#endif // hifi_RenderableZoneEntityItem_h diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp new file mode 100644 index 0000000000..a22c22ce5d --- /dev/null +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -0,0 +1,122 @@ +// +// ZoneEntityItem.cpp +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 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 + +#include + +#include "ZoneEntityItem.h" +#include "EntityTree.h" +#include "EntitiesLogging.h" +#include "EntityTreeElement.h" + +/* +bool ZoneEntityItem::_zonesArePickable = false; + +const xColor ZoneEntityItem::DEFAULT_SUN_sunColor = { 255, 255, 255 }; +const float ZoneEntityItem::DEFAULT_SUN_INTENSITY = 0.1f; +const float ZoneEntityItem::DEFAULT_SUN_AMBIENT_INTENSITY = 0.0f; +const bool ZoneEntityItem::DEFAULT_SUN_USE_EARTH_MODEL = true; +const float ZoneEntityItem::DEFAULT_SUN_APPARENT_LATITUDE = 37.777f; +const float ZoneEntityItem::DEFAULT_SUN_APPARENT_LONGITUDE = 122.407f; +const float ZoneEntityItem::DEFAULT_SUN_APPARENT_ALTITUDE = 0.03f; +const quint16 ZoneEntityItem::DEFAULT_SUN_APPARENT_DAY = 60; +const float ZoneEntityItem::DEFAULT_SUN_APPARENT_HOUR = 12.0f; +const glm::vec3 ZoneEntityItem::DEFAULT_SUN_DIRECTION = { 0.0f, -1.0f, 0.0f }; +*/ + +EntityItem* ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + EntityItem* result = new ZoneEntityItem(entityID, properties); + return result; +} + +ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + EntityItem(entityItemID) +{ + _type = EntityTypes::Zone; + _created = properties.getCreated(); + setProperties(properties); +} + +EntityItemProperties ZoneEntityItem::getProperties() const { + EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class + + properties._color = getXColor(); + properties._colorChanged = false; + + properties._glowLevel = getGlowLevel(); + properties._glowLevelChanged = false; + + return properties; +} + +bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qCDebug(entities) << "ZoneEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties._lastEdited); + } + return somethingChanged; +} + +int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _sunColor); + + return bytesRead; +} + + +// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + requestedProperties += PROP_COLOR; + return requestedProperties; +} + +void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); +} + +void ZoneEntityItem::debugDump() const { + quint64 now = usecTimestampNow(); + qCDebug(entities) << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qCDebug(entities) << " color:" << _sunColor[0] << "," << _sunColor[1] << "," << _sunColor[2]; + qCDebug(entities) << " position:" << debugTreeVector(_position); + qCDebug(entities) << " dimensions:" << debugTreeVector(_dimensions); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); +} + diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h new file mode 100644 index 0000000000..4b0b960697 --- /dev/null +++ b/libraries/entities/src/ZoneEntityItem.h @@ -0,0 +1,62 @@ +// +// ZoneEntityItem.h +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 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_ZoneEntityItem_h +#define hifi_ZoneEntityItem_h + +#include "EntityItem.h" + +class ZoneEntityItem : public EntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); + + ALLOW_INSTANTIATION // This class can be instantiated + + // methods for getting/setting all properties of an entity + virtual EntityItemProperties getProperties() const; + virtual bool setProperties(const EntityItemProperties& properties); + + // TODO: eventually only include properties changed since the params.lastViewFrustumSent time + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + const rgbColor& getColor() const { return _sunColor; } + xColor getXColor() const { xColor color = { _sunColor[RED_INDEX], _sunColor[GREEN_INDEX], _sunColor[BLUE_INDEX] }; return color; } + + void setColor(const rgbColor& value) { memcpy(_sunColor, value, sizeof(_sunColor)); } + void setColor(const xColor& value) { + _sunColor[RED_INDEX] = value.red; + _sunColor[GREEN_INDEX] = value.green; + _sunColor[BLUE_INDEX] = value.blue; + } + + virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } + + virtual void debugDump() const; + +protected: + rgbColor _sunColor; +}; + +#endif // hifi_ZoneEntityItem_h From 4e2bcc069098704db2f424ace1c756557860db03 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Apr 2015 12:47:11 -0700 Subject: [PATCH 17/74] Add zone properties to entity property panel --- examples/html/entityProperties.html | 124 ++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index dd5bced393..649b9164ed 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -182,6 +182,23 @@ var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green"); var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue"); + var elZoneSections = document.querySelectorAll(".zone-section"); + var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled"); + var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red"); + var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green"); + var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue"); + var elZoneKeyLightIntensity = document.getElementById("property-zone-key-color-intensity"); + var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-color-ambient-intensity"); + var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); + var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); + var elZoneKeyLightDirectionZ = document.getElementById("property-zone-key-light-direction-z"); + + var elZoneStageLatitude = document.getElementById("property-zone-stage-latitude"); + var elZoneStageLongitude = document.getElementById("property-zone-stage-longitude"); + var elZoneStageAltitude = document.getElementById("property-zone-stage-altitude"); + var elZoneStageDay = document.getElementById("property-zone-stage-day"); + var elZoneStageHour = document.getElementById("property-zone-stage-hour"); + if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); @@ -356,6 +373,32 @@ elLightCutoff.value = properties.cutoff; } + if (properties.type != "Zone") { + for (var i = 0; i < elZoneSections.length; i++) { + elZoneSections[i].style.display = 'none'; + } + } else { + for (var i = 0; i < elZoneSections.length; i++) { + elZoneSections[i].style.display = 'block'; + } + + elZoneStageSunModelEnabled.checked = properties.stageSunModelEnabled; + elZoneKeyLightColorRed.value = properties.keyLightColor.red; + elZoneKeyLightColorGreen.value = properties.keyLightColor.green; + elZoneKeyLightColorBlue.value = properties.keyLightColor.blue; + elZoneKeyLightIntensity.value = properties.keyLightIntensity; + elZoneKeyLightAmbientIntensity.value = properties.keyLightAmbientIntensity; + elZoneKeyLightDirectionX.value = properties.keyLightDirection.x.toFixed(2); + elZoneKeyLightDirectionY.value = properties.keyLightDirection.y.toFixed(2); + elZoneKeyLightDirectionZ.value = properties.keyLightDirection.z.toFixed(2); + + elZoneStageLatitude.value = properties.stageLatitude.toFixed(2); + elZoneStageLongitude.value = properties.stageLongitude.toFixed(2); + elZoneStageAltitude.value = properties.stageAltitude.toFixed(2); + elZoneStageDay.value = properties.stageDay; + elZoneStageHour.value = properties.stageHour; + } + if (selected) { activeElement.focus(); activeElement.select(); @@ -468,6 +511,26 @@ elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + elZoneStageSunModelEnabled.addEventListener('change', createEmitCheckedPropertyUpdateFunction('stageSunModelEnabled')); + var zoneKeyLightColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'keyLightColor', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); + elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('keyLightIntensity')); + elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('keyLightAmbientIntensity')); + var zoneKeyLightDirectionChangeFunction = createEmitVec3PropertyUpdateFunction( + 'keyLightDirection', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY, elZoneKeyLightDirectionZ); + elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); + elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); + elZoneKeyLightDirectionZ.addEventListener('change', zoneKeyLightDirectionChangeFunction); + + elZoneStageLatitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageLatitude')); + elZoneStageLongitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageLongitude')); + elZoneStageAltitude.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageAltitude')); + elZoneStageDay.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageDay')); + elZoneStageHour.addEventListener('change', createEmitNumberPropertyUpdateFunction('stageHour')); + elMoveSelectionToGrid.addEventListener("click", function() { EventBridge.emitWebEvent(JSON.stringify({ type: "action", @@ -833,6 +896,67 @@ + +
+ Stage Sun Model Enabled + + + +
+ +
+
Key Color
+
+
R
+
G
+
B
+
+
+
+
Key Intensity
+
+ +
+
+
+
Key Direction
+
+
Pitch
+
Yaw
+
Roll
+
+
+ +
+
Stage Latitude
+
+ +
+
+
+
Stage Longitude
+
+ +
+
+
+
Stage Altitude
+
+ +
+
+
+
Stage Day
+
+ +
+
+
+
Stage Hour
+
+ +
+
From 3dfbd70d41e5e1ca9badbaa2e26e651590d0fe1f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Apr 2015 13:16:55 -0700 Subject: [PATCH 18/74] Add new zone button --- examples/edit.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/examples/edit.js b/examples/edit.js index 2b32769337..480b87d416 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -135,6 +135,7 @@ var toolBar = (function () { newSphereButton, newLightButton, newTextButton, + newZoneButton, browseMarketplaceButton; function initialize() { @@ -201,6 +202,14 @@ var toolBar = (function () { alpha: 0.9, visible: false }); + newZoneButton = toolBar.addTool({ + imageURL: toolIconUrl + "zonecube3.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH + 208, width: 256, height: 256 }, + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: false + }); that.setActive(false); } @@ -241,6 +250,7 @@ var toolBar = (function () { toolBar.showTool(newSphereButton, doShow); toolBar.showTool(newLightButton, doShow); toolBar.showTool(newTextButton, doShow); + toolBar.showTool(newZoneButton, doShow); }; var RESIZE_INTERVAL = 50; @@ -412,6 +422,21 @@ var toolBar = (function () { return true; } + if (newZoneButton === toolBar.clicked(clickedOverlay)) { + var position = getPositionToCreateEntity(); + + if (position.x > 0 && position.y > 0 && position.z > 0) { + placingEntityID = Entities.addEntity({ + type: "Zone", + position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), + dimensions: { x: 10, y: 10, z: 10 }, + }); + } else { + print("Can't create box: Text would be out of bounds."); + } + return true; + } + return false; }; From e68f149aac64f4197ef891ced260e33af66e4d11 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 21 Apr 2015 13:18:53 -0700 Subject: [PATCH 19/74] Fixing bad merge --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 84c810ac0d..259b71afc2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -245,7 +245,7 @@ Menu::Menu() { false, qApp, SLOT(setFullscreen(bool))); -#endif + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, 0, // QML Qt::Key_P, true, qApp, SLOT(cameraMenuChanged())); From e436c9521206336b842152ce32783fbf913bff09 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Apr 2015 14:36:13 -0700 Subject: [PATCH 20/74] first cut at reworking zones --- .../src/EntityTreeRenderer.cpp | 114 ++++++++++++++++- .../src/EntityTreeRenderer.h | 28 ++++- .../src/RenderableZoneEntityItem.cpp | 6 +- .../entities/src/EntityItemProperties.cpp | 85 ++++++++++++- libraries/entities/src/EntityItemProperties.h | 39 +++++- .../entities/src/EntityItemPropertiesMacros.h | 9 ++ libraries/entities/src/ZoneEntityItem.cpp | 117 ++++++++++++++---- libraries/entities/src/ZoneEntityItem.h | 69 +++++++++-- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 3 +- 10 files changed, 421 insertions(+), 51 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 132feff7e3..adf7fb4e29 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "EntityTreeRenderer.h" @@ -35,7 +36,7 @@ #include "RenderableTextEntityItem.h" #include "RenderableZoneEntityItem.h" #include "EntitiesRendererLogging.h" - +#include "ZoneEntityItem.h" EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, AbstractScriptingServicesInterface* scriptingServices) : @@ -395,10 +396,106 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _tree->lockForRead(); - _tree->recurseTreeWithOperation(renderOperation, &args); -// Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE - // ? RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; + // Implement some kind of a stack/union mechanism here... + // + // * As you enter a zone (A), you use it's properties + // * if already in a zone, and you enter the union of that zone and a new zone (A + B) + // you use the settings of the new zone (B) you entered.. but remember that you were previously + // in zone A + // * if you enter a new zone and are in the union of 3 zones (A+B+C) then use zone C and remember + // you were most recently in B + _lastZones = _currentZones; + _currentZones.clear(); + _tree->recurseTreeWithOperation(renderOperation, &args); + const ZoneEntityItem* bestZone = NULL; + + if (_currentZones.empty()) { + // if we're not in any current zone, then we can completely erase our zoneHistory + _zoneHistory.clear(); + } else { + // we're in some zone... check to see if we've changed zones.. + QSet newZones = _currentZones - _lastZones; + + if (!newZones.empty()) { + // we just entered a new zone, so we want to make a shift + EntityItemID theNewZone = *(newZones.begin()); // random we don't care, if it's one, then this works. + _zoneHistory << _currentZone; // remember the single zone we used to be in. + _currentZone = theNewZone; // change to our new zone + + // do something to remove any item of _zoneHistory that is not in _currentZones + QStack newHistory; + QStack::iterator i = _zoneHistory.begin(); + while(i != _zoneHistory.end()) { + EntityItemID zoneID = *i; + if (_currentZones.contains(zoneID)) { + newHistory << zoneID; + } + ++i; + } + + _zoneHistory = newHistory; + bestZone = dynamic_cast( + static_cast(_tree)->findEntityByEntityItemID(_currentZone)); + } else { + + if (_currentZones.contains(_currentZone)) { + // No change in zone, keep the current zone + bestZone = dynamic_cast( + static_cast(_tree)->findEntityByEntityItemID(_currentZone)); + } else { + if (!_zoneHistory.empty()) { + _currentZone = _zoneHistory.pop(); + bestZone = dynamic_cast( + static_cast(_tree)->findEntityByEntityItemID(_currentZone)); + } + + } + + } + } + + QSharedPointer scene = DependencyManager::get(); + + if (bestZone) { + if (!_hasPreviousZone) { + _previousKeyLightColor = scene->getKeyLightColor(); + _previousKeyLightIntensity = scene->getKeyLightIntensity(); + _previousKeyLightAmbientIntensity = scene->getKeyLightAmbientIntensity(); + _previousKeyLightDirection = scene->getKeyLightDirection(); + _previousUseEarthModel = scene->isStageEarthSunModelEnabled(); + _previousStageLongitude = scene->getStageLocationLongitude(); + _previousStageLatitude = scene->getStageLocationLatitude(); + _previousStageAltitude = scene->getStageLocationAltitude(); + _previousStageHour = scene->getStageDayTime(); + _previousStageDay = scene->getStageYearTime(); + _hasPreviousZone = true; + } + scene->setKeyLightColor(bestZone->getKeyLightColorVec3()); + scene->setKeyLightIntensity(bestZone->getKeyLightIntensity()); + scene->setKeyLightAmbientIntensity(bestZone->getKeyLightAmbientIntensity()); + scene->setKeyLightDirection(bestZone->getKeyLightDirection()); + scene->setStageEarthSunModelEnable(bestZone->getUseEarthModel()); + scene->setStageLocation(bestZone->getStageLongitude(), bestZone->getStageLatitude(), + bestZone->getStageAltitude()); + scene->setStageDayTime(bestZone->getStageHour()); + scene->setStageYearTime(bestZone->getStageDay()); + + } else { + _currentZone = EntityItemID(); // clear out current zone + if (_hasPreviousZone) { + scene->setKeyLightColor(_previousKeyLightColor); + scene->setKeyLightIntensity(_previousKeyLightIntensity); + scene->setKeyLightAmbientIntensity(_previousKeyLightAmbientIntensity); + scene->setKeyLightDirection(_previousKeyLightDirection); + scene->setStageEarthKeyLightModelEnable(_previousUseEarthModel); + scene->setStageLocation(_previousStageLongitude, _previousStageLatitude, + _previousStageAltitude); + scene->setStageDayTime(_previousStageHour); + scene->setStageYearTime(_previousStageDay); + _hasPreviousZone = false; + } + } // we must call endScene while we still have the tree locked so that no one deletes a model // on us while rendering the scene @@ -598,6 +695,15 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) EntityItem* entityItem = entityItems[i]; if (entityItem->isVisible()) { + + // Zone Entities are a special case we handle here... + if (entityItem->getType() == EntityTypes::Zone) { + if (entityItem->contains(args->_viewFrustum->getPosition())) { + _currentZones << entityItem->getEntityItemID(); + } + } + // NOTE: we might not want to render zones here... + // render entityItem AABox entityBox = entityItem->getAABox(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index e8d70c9df9..fd979fc9f9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -12,18 +12,20 @@ #ifndef hifi_EntityTreeRenderer_h #define hifi_EntityTreeRenderer_h +#include +#include + #include #include // for RayToEntityIntersectionResult #include #include #include +class AbstractScriptingServicesInterface; +class AbstractViewStateInterface; class Model; class ScriptEngine; -class AbstractViewStateInterface; -class AbstractScriptingServicesInterface; - -class ScriptEngine; +class ZoneEntityItem; class EntityScriptDetails { public: @@ -164,6 +166,24 @@ private: bool _shuttingDown = false; QMultiMap _waitingOnPreload; + + QSet _lastZones; + QSet _currentZones; + QStack _zoneHistory; + EntityItemID _currentZone; + + bool _hasPreviousZone = false; + + glm::vec3 _previousKeyLightColor; + float _previousKeyLightIntensity; + float _previousKeyLightAmbientIntensity; + glm::vec3 _previousKeyLightDirection; + bool _previousStageSunModelEnabled; + float _previousStageLongitude; + float _previousStageLatitude; + float _previousStageAltitude; + float _previousStageHour; + int _previousStageDay; }; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 6a16404f89..d13fa37681 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -32,8 +32,8 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { const float MAX_COLOR = 255.0f; - glm::vec4 cubeColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, - getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + glm::vec4 cubeColor(_keyLightColor[RED_INDEX] / MAX_COLOR, _keyLightColor[GREEN_INDEX] / MAX_COLOR, + _keyLightColor[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); glPushMatrix(); glTranslatef(position.x, position.y, position.z); @@ -47,4 +47,6 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { glPopMatrix(); glPopMatrix(); + //debugDump(); + }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8a25d59f26..50856f53db 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -18,14 +18,14 @@ #include #include +#include "EntitiesLogging.h" #include "EntityItem.h" #include "EntityItemProperties.h" #include "EntityItemPropertiesDefaults.h" #include "ModelEntityItem.h" -#include "TextEntityItem.h" -#include "EntitiesLogging.h" #include "ParticleEffectEntityItem.h" - +#include "TextEntityItem.h" +#include "ZoneEntityItem.h" EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1); @@ -76,6 +76,16 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), + CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR), + CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY), + CONSTRUCT_PROPERTY(keyLightAmbientIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY), + CONSTRUCT_PROPERTY(keyLightDirection, ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION), + CONSTRUCT_PROPERTY(stageSunModelEnabled, ZoneEntityItem::DEFAULT_STAGE_SUN_MODEL_ENABLED), + CONSTRUCT_PROPERTY(stageLatitude, ZoneEntityItem::DEFAULT_STAGE_LATITUDE), + CONSTRUCT_PROPERTY(stageLongitude, ZoneEntityItem::DEFAULT_STAGE_LONGITUDE), + CONSTRUCT_PROPERTY(stageAltitude, ZoneEntityItem::DEFAULT_STAGE_ALTITUDE), + CONSTRUCT_PROPERTY(stageDay, ZoneEntityItem::DEFAULT_STAGE_DAY), + CONSTRUCT_PROPERTY(stageHour, ZoneEntityItem::DEFAULT_STAGE_HOUR), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -268,6 +278,16 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, keyLightColor); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, keyLightIntensity); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_AMBIENT_INTENSITY, keyLightAmbientIntensity); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, keyLightDirection); + CHECK_PROPERTY_CHANGE(PROP_STAGE_SUN_MODEL_ENABLED, stageSunModelEnabled); + CHECK_PROPERTY_CHANGE(PROP_STAGE_LATITUDE, stageLatitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_LONGITUDE, stageLongitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, stageAltitude); + CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, stageDay); + CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, stageHour); return changedProperties; } @@ -334,6 +354,17 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); + COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(keyLightColor); + COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity); + COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity); + COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(keyLightDirection); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageSunModelEnabled); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageLatitude); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageLongitude); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageAltitude); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageDay); + COPY_PROPERTY_TO_QSCRIPTVALUE(stageHour); + // Sitting properties support QScriptValue sittingPoints = engine->newObject(); for (int i = 0; i < _sittingPoints.size(); ++i) { @@ -418,6 +449,17 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(marketplaceID, setMarketplaceID); + COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(keyLightColor, setKeyLightColor); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightIntensity, setKeyLightIntensity); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightAmbientIntensity, setKeyLightAmbientIntensity); + COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(keyLightDirection, setKeyLightDirection); + COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(stageSunModelEnabled, setStageSunModelEnabled); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageLatitude, setStageLatitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageLongitude, setStageLongitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageAltitude, setStageAltitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(stageDay, setStageDay); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageHour, setStageHour); + _lastEdited = usecTimestampNow(); } @@ -603,6 +645,19 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, properties.getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius()); } + + if (properties.getType() == EntityTypes::Zone) { + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, appendColor, properties.getKeyLightColor()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, properties.getKeyLightIntensity()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, properties.getKeyLightAmbientIntensity()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, properties.getKeyLightDirection()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, properties.getStageSunModelEnabled()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, properties.getStageLatitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, properties.getStageLongitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, properties.getStageAltitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, properties.getStageDay()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, properties.getStageHour()); + } APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID()); } @@ -836,6 +891,19 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } + + if (properties.getType() == EntityTypes::Zone) { + READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_KEYLIGHT_COLOR, setKeyLightColor); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_SUN_MODEL_ENABLED, bool, setStageSunModelEnabled); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_LATITUDE, float, setStageLatitude); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_LONGITUDE, float, setStageLongitude); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_ALTITUDE, float, setStageAltitude); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_DAY, quint16, setStageDay); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour); + } READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID); @@ -923,6 +991,17 @@ void EntityItemProperties::markAllChanged() { _particleRadiusChanged = true; _marketplaceIDChanged = true; + + _keyLightColorChanged = true; + _keyLightIntensityChanged = true; + _keyLightAmbientIntensityChanged = true; + _keyLightDirectionChanged = true; + _stageSunModelEnabledChanged = true; + _stageLatitudeChanged = true; + _stageLongitudeChanged = true; + _stageAltitudeChanged = true; + _stageDayChanged = true; + _stageHourChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 0bc0bcedc7..9a68abd73e 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -97,6 +97,17 @@ enum EntityPropertyList { PROP_MARKETPLACE_ID, PROP_ACCELERATION, PROP_SIMULATOR_ID, + + PROP_KEYLIGHT_COLOR, + PROP_KEYLIGHT_INTENSITY, + PROP_KEYLIGHT_AMBIENT_INTENSITY, + PROP_KEYLIGHT_DIRECTION, + PROP_STAGE_SUN_MODEL_ENABLED, + PROP_STAGE_LATITUDE, + PROP_STAGE_LONGITUDE, + PROP_STAGE_ALTITUDE, + PROP_STAGE_DAY, + PROP_STAGE_HOUR, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties ABOVE this line @@ -113,7 +124,22 @@ enum EntityPropertyList { PROP_TEXT = PROP_MODEL_URL, PROP_LINE_HEIGHT = PROP_ANIMATION_URL, PROP_BACKGROUND_COLOR = PROP_ANIMATION_FPS, - PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1 + PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1, + + // Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for + // other properties + /* + PROP_KEYLIGHT_COLOR = PROP_COLOR, + PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY, + PROP_KEYLIGHT_AMBIENT_INTENSITY = PROP_CUTOFF, + PROP_KEYLIGHT_DIRECTION = PROP_EXPONENT, + PROP_STAGE_SUN_MODEL_ENABLED = PROP_IS_SPOTLIGHT, + PROP_STAGE_LATITUDE = PROP_DIFFUSE_COLOR_UNUSED, + PROP_STAGE_LONGITUDE = PROP_AMBIENT_COLOR_UNUSED, + PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED, + PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED, + PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED, + */ // WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above }; @@ -215,6 +241,17 @@ public: DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); + DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); + DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); + DEFINE_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float); + DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); + DEFINE_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, StageSunModelEnabled, stageSunModelEnabled, bool); + DEFINE_PROPERTY(PROP_STAGE_LATITUDE, StageLatitude, stageLatitude, float); + DEFINE_PROPERTY(PROP_STAGE_LONGITUDE, StageLongitude, stageLongitude, float); + DEFINE_PROPERTY(PROP_STAGE_ALTITUDE, StageAltitude, stageAltitude, float); + DEFINE_PROPERTY(PROP_STAGE_DAY, StageDay, stageDay, quint16); + DEFINE_PROPERTY(PROP_STAGE_HOUR, StageHour, stageHour, float); + public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index e3e54f5bc8..753ac793ac 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -189,6 +189,15 @@ } \ } +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_INT(P, S) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + int newValue = P.toVariant().toInt(); \ + if (_defaultSettings || newValue != _##P) { \ + S(newValue); \ + } \ + } + #define COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index a22c22ce5d..e0fe238c57 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -19,20 +19,18 @@ #include "EntitiesLogging.h" #include "EntityTreeElement.h" -/* bool ZoneEntityItem::_zonesArePickable = false; -const xColor ZoneEntityItem::DEFAULT_SUN_sunColor = { 255, 255, 255 }; -const float ZoneEntityItem::DEFAULT_SUN_INTENSITY = 0.1f; -const float ZoneEntityItem::DEFAULT_SUN_AMBIENT_INTENSITY = 0.0f; -const bool ZoneEntityItem::DEFAULT_SUN_USE_EARTH_MODEL = true; -const float ZoneEntityItem::DEFAULT_SUN_APPARENT_LATITUDE = 37.777f; -const float ZoneEntityItem::DEFAULT_SUN_APPARENT_LONGITUDE = 122.407f; -const float ZoneEntityItem::DEFAULT_SUN_APPARENT_ALTITUDE = 0.03f; -const quint16 ZoneEntityItem::DEFAULT_SUN_APPARENT_DAY = 60; -const float ZoneEntityItem::DEFAULT_SUN_APPARENT_HOUR = 12.0f; -const glm::vec3 ZoneEntityItem::DEFAULT_SUN_DIRECTION = { 0.0f, -1.0f, 0.0f }; -*/ +const xColor ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR = { 255, 255, 255 }; +const float ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY = 1.0f; +const float ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f; +const glm::vec3 ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f }; +const bool ZoneEntityItem::DEFAULT_STAGE_SUN_MODEL_ENABLED = false; +const float ZoneEntityItem::DEFAULT_STAGE_LATITUDE = 37.777f; +const float ZoneEntityItem::DEFAULT_STAGE_LONGITUDE = 122.407f; +const float ZoneEntityItem::DEFAULT_STAGE_ALTITUDE = 0.03f; +const quint16 ZoneEntityItem::DEFAULT_STAGE_DAY = 60; +const float ZoneEntityItem::DEFAULT_STAGE_HOUR = 12.0f; EntityItem* ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItem* result = new ZoneEntityItem(entityID, properties); @@ -44,17 +42,37 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte { _type = EntityTypes::Zone; _created = properties.getCreated(); + + _keyLightColor[RED_INDEX] = DEFAULT_KEYLIGHT_COLOR.red; + _keyLightColor[GREEN_INDEX] = DEFAULT_KEYLIGHT_COLOR.green; + _keyLightColor[BLUE_INDEX] = DEFAULT_KEYLIGHT_COLOR.blue; + + _keyLightIntensity = DEFAULT_KEYLIGHT_INTENSITY; + _keyLightAmbientIntensity = DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; + _keyLightDirection = DEFAULT_KEYLIGHT_DIRECTION; + _stageSunModelEnabled = DEFAULT_STAGE_SUN_MODEL_ENABLED; + _stageLatitude = DEFAULT_STAGE_LATITUDE; + _stageLongitude = DEFAULT_STAGE_LONGITUDE; + _stageAltitude = DEFAULT_STAGE_ALTITUDE; + _stageDay = DEFAULT_STAGE_DAY; + _stageHour = DEFAULT_STAGE_HOUR; + setProperties(properties); } EntityItemProperties ZoneEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class - properties._color = getXColor(); - properties._colorChanged = false; - - properties._glowLevel = getGlowLevel(); - properties._glowLevelChanged = false; + COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightColor, getKeyLightColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightIntensity, getKeyLightIntensity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightAmbientIntensity, getKeyLightAmbientIntensity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightDirection, getKeyLightDirection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageSunModelEnabled, getStageSunModelEnabled); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageLatitude, getStageLatitude); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageLongitude, getStageLongitude); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageAltitude, getStageAltitude); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageDay, getStageDay); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageHour, getStageHour); return properties; } @@ -63,7 +81,16 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightColor, setKeyLightColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightIntensity, setKeyLightIntensity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightAmbientIntensity, setKeyLightAmbientIntensity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightDirection, setKeyLightDirection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageSunModelEnabled, setStageSunModelEnabled); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageLatitude, setStageLatitude); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageLongitude, setStageLongitude); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageAltitude, setStageAltitude); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageDay, setStageDay); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageHour, setStageHour); if (somethingChanged) { bool wantDebug = false; @@ -85,7 +112,16 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _sunColor); + READ_ENTITY_PROPERTY_COLOR(PROP_KEYLIGHT_COLOR, _keyLightColor); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, _keyLightIntensity); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, _keyLightAmbientIntensity); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, _keyLightDirection); + READ_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, bool, _stageSunModelEnabled); + READ_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, float, _stageLatitude); + READ_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, float, _stageLongitude); + READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _stageAltitude); + READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay); + READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour); return bytesRead; } @@ -94,7 +130,18 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, // TODO: eventually only include properties changed since the params.lastViewFrustumSent time EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - requestedProperties += PROP_COLOR; + + requestedProperties += PROP_KEYLIGHT_COLOR; + requestedProperties += PROP_KEYLIGHT_INTENSITY; + requestedProperties += PROP_KEYLIGHT_AMBIENT_INTENSITY; + requestedProperties += PROP_KEYLIGHT_DIRECTION; + requestedProperties += PROP_STAGE_SUN_MODEL_ENABLED; + requestedProperties += PROP_STAGE_LATITUDE; + requestedProperties += PROP_STAGE_LONGITUDE; + requestedProperties += PROP_STAGE_ALTITUDE; + requestedProperties += PROP_STAGE_DAY; + requestedProperties += PROP_STAGE_HOUR; + return requestedProperties; } @@ -108,15 +155,33 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, appendColor, _keyLightColor); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, appendValue, getKeyLightIntensity()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, appendValue, getKeyLightAmbientIntensity()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, appendValue, getKeyLightDirection()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_SUN_MODEL_ENABLED, appendValue, getStageSunModelEnabled()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LATITUDE, appendValue, getStageLatitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_LONGITUDE, appendValue, getStageLongitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getStageAltitude()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getStageDay()); + APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getStageHour()); } void ZoneEntityItem::debugDump() const { quint64 now = usecTimestampNow(); - qCDebug(entities) << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------"; - qCDebug(entities) << " color:" << _sunColor[0] << "," << _sunColor[1] << "," << _sunColor[2]; - qCDebug(entities) << " position:" << debugTreeVector(_position); - qCDebug(entities) << " dimensions:" << debugTreeVector(_dimensions); - qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << " ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qCDebug(entities) << " keyLightColor:" << _keyLightColor[0] << "," << _keyLightColor[1] << "," << _keyLightColor[2]; + qCDebug(entities) << " position:" << debugTreeVector(_position); + qCDebug(entities) << " dimensions:" << debugTreeVector(_dimensions); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << " _keyLightIntensity:" << _keyLightIntensity; + qCDebug(entities) << " _keyLightAmbientIntensity:" << _keyLightAmbientIntensity; + qCDebug(entities) << " _keyLightDirection:" << _keyLightDirection; + qCDebug(entities) << " _stageSunModelEnabled:" << _stageSunModelEnabled; + qCDebug(entities) << " _stageLatitude:" << _stageLatitude; + qCDebug(entities) << " _stageLongitude:" << _stageLongitude; + qCDebug(entities) << " _stageAltitude:" << _stageAltitude; + qCDebug(entities) << " _stageDay:" << _stageDay; + qCDebug(entities) << " _stageHour:" << _stageHour; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 4b0b960697..5d22b2d8bd 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -41,22 +41,73 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - const rgbColor& getColor() const { return _sunColor; } - xColor getXColor() const { xColor color = { _sunColor[RED_INDEX], _sunColor[GREEN_INDEX], _sunColor[BLUE_INDEX] }; return color; } + virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } - void setColor(const rgbColor& value) { memcpy(_sunColor, value, sizeof(_sunColor)); } - void setColor(const xColor& value) { - _sunColor[RED_INDEX] = value.red; - _sunColor[GREEN_INDEX] = value.green; - _sunColor[BLUE_INDEX] = value.blue; + xColor getKeyLightColor() const { xColor color = { _keyLightColor[RED_INDEX], _keyLightColor[GREEN_INDEX], _keyLightColor[BLUE_INDEX] }; return color; } + void setKeyLightColor(const xColor& value) { + _keyLightColor[RED_INDEX] = value.red; + _keyLightColor[GREEN_INDEX] = value.green; + _keyLightColor[BLUE_INDEX] = value.blue; } - virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } + float getKeyLightIntensity() const { return _keyLightIntensity; } + void setKeyLightIntensity(float value) { _keyLightIntensity = value; } + + float getKeyLightAmbientIntensity() const { return _keyLightAmbientIntensity; } + void setKeyLightAmbientIntensity(float value) { _keyLightAmbientIntensity = value; } + + const glm::vec3& getKeyLightDirection() const { return _keyLightDirection; } + void setKeyLightDirection(const glm::vec3& value) { _keyLightDirection = value; } + + bool getStageSunModelEnabled() const { return _stageSunModelEnabled; } + void setStageSunModelEnabled(bool value) { _stageSunModelEnabled = value; } + + float getStageLatitude() const { return _stageLatitude; } + void setStageLatitude(float value) { _stageLatitude = value; } + + float getStageLongitude() const { return _stageLongitude; } + void setStageLongitude(float value) { _stageLongitude = value; } + + float getStageAltitude() const { return _stageAltitude; } + void setStageAltitude(float value) { _stageAltitude = value; } + + uint16_t getStageDay() const { return _stageDay; } + void setStageDay(uint16_t value) { _stageDay = value; } + + float getStageHour() const { return _stageHour; } + void setStageHour(float value) { _stageHour = value; } + + static bool getZonesArePickable() { return _zonesArePickable; } + static void setZonesArePickable(bool value) { _zonesArePickable = value; } + virtual void debugDump() const; + static const xColor DEFAULT_KEYLIGHT_COLOR; + static const float DEFAULT_KEYLIGHT_INTENSITY; + static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; + static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION; + static const bool DEFAULT_STAGE_SUN_MODEL_ENABLED; + static const float DEFAULT_STAGE_LATITUDE; + static const float DEFAULT_STAGE_LONGITUDE; + static const float DEFAULT_STAGE_ALTITUDE; + static const quint16 DEFAULT_STAGE_DAY; + static const float DEFAULT_STAGE_HOUR; + protected: - rgbColor _sunColor; + // properties of the "sun" in the zone + rgbColor _keyLightColor; + float _keyLightIntensity; + float _keyLightAmbientIntensity; + glm::vec3 _keyLightDirection; + bool _stageSunModelEnabled; + float _stageLatitude; + float _stageLongitude; + float _stageAltitude; + uint16_t _stageDay; + float _stageHour; + + static bool _zonesArePickable; }; #endif // hifi_ZoneEntityItem_h diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 52153f9e83..8f0cee10cf 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_HAVE_ACCELERATION; + return VERSION_ENTITIES_ZONE_ENTITIES_EXIST; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 9fb14854aa..0f89aa9423 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -119,6 +119,7 @@ PacketType packetTypeForPacket(const char* packet); int arithmeticCodingValueFromBuffer(const char* checkValue); int numBytesArithmeticCodingFromBuffer(const char* checkValue); +const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; const PacketVersion VERSION_ENTITIES_HAVE_ANIMATION = 1; const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2; const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3; @@ -135,6 +136,6 @@ const PacketVersion VERSION_ENTITIES_HAS_COLLISION_MODEL = 12; const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED = 13; const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14; const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15; -const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; +const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 16; #endif // hifi_PacketHeaders_h From 4ce451f9845856186f081773d355b6b61755e504 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Apr 2015 14:55:45 -0700 Subject: [PATCH 21/74] wire up zone rendering again --- .../entities-renderer/src/EntityTreeRenderer.cpp | 6 +++--- libraries/entities/src/ZoneEntityItem.h | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index adf7fb4e29..59f7aa0f5c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -463,7 +463,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _previousKeyLightIntensity = scene->getKeyLightIntensity(); _previousKeyLightAmbientIntensity = scene->getKeyLightAmbientIntensity(); _previousKeyLightDirection = scene->getKeyLightDirection(); - _previousUseEarthModel = scene->isStageEarthSunModelEnabled(); + _previousStageSunModelEnabled = scene->isStageSunModelEnabled(); _previousStageLongitude = scene->getStageLocationLongitude(); _previousStageLatitude = scene->getStageLocationLatitude(); _previousStageAltitude = scene->getStageLocationAltitude(); @@ -475,7 +475,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R scene->setKeyLightIntensity(bestZone->getKeyLightIntensity()); scene->setKeyLightAmbientIntensity(bestZone->getKeyLightAmbientIntensity()); scene->setKeyLightDirection(bestZone->getKeyLightDirection()); - scene->setStageEarthSunModelEnable(bestZone->getUseEarthModel()); + scene->setStageSunModelEnable(bestZone->getStageSunModelEnabled()); scene->setStageLocation(bestZone->getStageLongitude(), bestZone->getStageLatitude(), bestZone->getStageAltitude()); scene->setStageDayTime(bestZone->getStageHour()); @@ -488,7 +488,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R scene->setKeyLightIntensity(_previousKeyLightIntensity); scene->setKeyLightAmbientIntensity(_previousKeyLightAmbientIntensity); scene->setKeyLightDirection(_previousKeyLightDirection); - scene->setStageEarthKeyLightModelEnable(_previousUseEarthModel); + scene->setStageSunModelEnable(_previousStageSunModelEnabled); scene->setStageLocation(_previousStageLongitude, _previousStageLatitude, _previousStageAltitude); scene->setStageDayTime(_previousStageHour); diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 5d22b2d8bd..8f1b15d174 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -41,7 +41,10 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } + // NOTE: Apparently if you begin to return a shape type, then the physics system will prevent an avatar + // from penetrating the walls of the entity. This fact will likely be important to Clement as he works + // on better defining the shape/volume of a zone. + //virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } xColor getKeyLightColor() const { xColor color = { _keyLightColor[RED_INDEX], _keyLightColor[GREEN_INDEX], _keyLightColor[BLUE_INDEX] }; return color; } void setKeyLightColor(const xColor& value) { @@ -49,6 +52,15 @@ public: _keyLightColor[GREEN_INDEX] = value.green; _keyLightColor[BLUE_INDEX] = value.blue; } + + glm::vec3 getKeyLightColorVec3() const { + const quint8 MAX_COLOR = 255; + glm::vec3 color = { _keyLightColor[RED_INDEX] / MAX_COLOR, + _keyLightColor[GREEN_INDEX] / MAX_COLOR, + _keyLightColor[BLUE_INDEX] / MAX_COLOR }; + return color; + } + float getKeyLightIntensity() const { return _keyLightIntensity; } void setKeyLightIntensity(float value) { _keyLightIntensity = value; } From 8366dd02a0f1c0f3bdad779dae359c5a607c0645 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Apr 2015 15:03:04 -0700 Subject: [PATCH 22/74] remove RenderableZoneEntityItem class since zones don't render like other entities --- .../src/EntityTreeRenderer.cpp | 52 +++++++++---------- .../src/RenderableZoneEntityItem.cpp | 52 ------------------- .../src/RenderableZoneEntityItem.h | 29 ----------- 3 files changed, 25 insertions(+), 108 deletions(-) delete mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.cpp delete mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 59f7aa0f5c..c14a821a38 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -34,7 +34,6 @@ #include "RenderableParticleEffectEntityItem.h" #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" -#include "RenderableZoneEntityItem.h" #include "EntitiesRendererLogging.h" #include "ZoneEntityItem.h" @@ -58,7 +57,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) - REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory) _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID @@ -696,42 +694,42 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) if (entityItem->isVisible()) { - // Zone Entities are a special case we handle here... + // NOTE: Zone Entities are a special case we handle here... Zones don't render + // like other entity types. So we will skip the normal rendering tests if (entityItem->getType() == EntityTypes::Zone) { if (entityItem->contains(args->_viewFrustum->getPosition())) { _currentZones << entityItem->getEntityItemID(); } - } - // NOTE: we might not want to render zones here... - - // render entityItem - AABox entityBox = entityItem->getAABox(); + } else { + // render entityItem + AABox entityBox = entityItem->getAABox(); - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); + // TODO: some entity types (like lights) might want to be rendered even + // when they are outside of the view frustum... + float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); - bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; - if (!outOfView) { - bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); + bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; + if (!outOfView) { + bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); - if (bigEnoughToRender) { - renderProxies(entityItem, args); + if (bigEnoughToRender) { + renderProxies(entityItem, args); - Glower* glower = NULL; - if (entityItem->getGlowLevel() > 0.0f) { - glower = new Glower(entityItem->getGlowLevel()); - } - entityItem->render(args); - args->_itemsRendered++; - if (glower) { - delete glower; + Glower* glower = NULL; + if (entityItem->getGlowLevel() > 0.0f) { + glower = new Glower(entityItem->getGlowLevel()); + } + entityItem->render(args); + args->_itemsRendered++; + if (glower) { + delete glower; + } + } else { + args->_itemsTooSmall++; } } else { - args->_itemsTooSmall++; + args->_itemsOutOfView++; } - } else { - args->_itemsOutOfView++; } } } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp deleted file mode 100644 index d13fa37681..0000000000 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// RenderableZoneEntityItem.cpp -// interface/src -// -// Created by Brad Hefta-Gaub on 8/6/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 - -#include - -#include -#include - -#include "RenderableZoneEntityItem.h" - -EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new RenderableZoneEntityItem(entityID, properties); -} - -void RenderableZoneEntityItem::render(RenderArgs* args) { - PerformanceTimer perfTimer("RenderableZoneEntityItem::render"); - assert(getType() == EntityTypes::Zone); - glm::vec3 position = getPosition(); - glm::vec3 center = getCenter(); - glm::vec3 dimensions = getDimensions(); - glm::quat rotation = getRotation(); - - const float MAX_COLOR = 255.0f; - - glm::vec4 cubeColor(_keyLightColor[RED_INDEX] / MAX_COLOR, _keyLightColor[GREEN_INDEX] / MAX_COLOR, - _keyLightColor[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); - - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - DependencyManager::get()->renderWireCube(1.0f, cubeColor); - glPopMatrix(); - glPopMatrix(); - - //debugDump(); - -}; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h deleted file mode 100644 index b05fd0e3f8..0000000000 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// RenderableZoneEntityItem.h -// interface/src/entities -// -// Created by Brad Hefta-Gaub on 8/6/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_RenderableZoneEntityItem_h -#define hifi_RenderableZoneEntityItem_h - -#include - -class RenderableZoneEntityItem : public ZoneEntityItem { -public: - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); - - RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - ZoneEntityItem(entityItemID, properties) - { } - - virtual void render(RenderArgs* args); -}; - - -#endif // hifi_RenderableZoneEntityItem_h From 486ab044a0b6065136b63d1509092e8ac8d99f4f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Apr 2015 15:16:46 -0700 Subject: [PATCH 23/74] use piggyback properties to save on property bit space --- libraries/entities/src/EntityItemProperties.h | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9a68abd73e..27b9adbc1b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -98,23 +98,11 @@ enum EntityPropertyList { PROP_ACCELERATION, PROP_SIMULATOR_ID, - PROP_KEYLIGHT_COLOR, - PROP_KEYLIGHT_INTENSITY, - PROP_KEYLIGHT_AMBIENT_INTENSITY, - PROP_KEYLIGHT_DIRECTION, - PROP_STAGE_SUN_MODEL_ENABLED, - PROP_STAGE_LATITUDE, - PROP_STAGE_LONGITUDE, - PROP_STAGE_ALTITUDE, - PROP_STAGE_DAY, - PROP_STAGE_HOUR, - //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties ABOVE this line PROP_AFTER_LAST_ITEM, //////////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////////// // WARNING! Do not add props here unless you intentionally mean to reuse PROP_ indexes // @@ -127,8 +115,8 @@ enum EntityPropertyList { PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1, // Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for - // other properties - /* + // other properties which will never overlap with each other. We do this so that we don't have to expand + // the size of the properties bitflags mask PROP_KEYLIGHT_COLOR = PROP_COLOR, PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY, PROP_KEYLIGHT_AMBIENT_INTENSITY = PROP_CUTOFF, @@ -139,7 +127,7 @@ enum EntityPropertyList { PROP_STAGE_ALTITUDE = PROP_SPECULAR_COLOR_UNUSED, PROP_STAGE_DAY = PROP_LINEAR_ATTENUATION_UNUSED, PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED, - */ + // WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above }; From ac81e3e84781d5717ff983380f1f5136ed0f3a9a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 22 Apr 2015 11:27:35 -0700 Subject: [PATCH 24/74] added example script --- .../example/entities/zoneEntityExample.js | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 examples/example/entities/zoneEntityExample.js diff --git a/examples/example/entities/zoneEntityExample.js b/examples/example/entities/zoneEntityExample.js new file mode 100644 index 0000000000..84d87d1370 --- /dev/null +++ b/examples/example/entities/zoneEntityExample.js @@ -0,0 +1,69 @@ +// +// zoneEntityExample.js +// examples +// +// Created by Brad Hefta-Gaub on 4/16/15. +// Copyright 2015 High Fidelity, Inc. +// +// This is an example script that demonstrates creating and editing a entity +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +var count = 0; +var stopAfter = 1000; + +var zoneEntityA = Entities.addEntity({ + type: "Zone", + position: { x: 5, y: 5, z: 5 }, + dimensions: { x: 10, y: 10, z: 10 }, + keyLightColor: { red: 255, green: 0, blue: 0 }, + stageSunModelEnabled: false, + keyLightDirection: { x: 0, y: -1.0, z: 0 } +}); + +print("zoneEntityA:" + zoneEntityA); + +var zoneEntityB = Entities.addEntity({ + type: "Zone", + position: { x: 1, y: 1, z: 21 }, + dimensions: { x: 2, y: 2, z: 2 }, + keyLightColor: { red: 0, green: 255, blue: 0 }, + keyLightIntensity: 0.9, + stageLatitude: 37.777, + stageLongitude: 122.407, + stageAltitude: 0.03, + stageDay: 60, + stageHour: 12, + stageSunModelEnabled: true +}); + +print("zoneEntityB:" + zoneEntityB); + + +var zoneEntityC = Entities.addEntity({ + type: "Zone", + position: { x: 5, y: 5, z: 15 }, + dimensions: { x: 10, y: 10, z: 10 }, + keyLightColor: { red: 0, green: 0, blue: 255 }, + keyLightIntensity: 0.75, + keyLightDirection: { x: 0, y: 0, z: -1 }, + stageSunModelEnabled: false +}); + +print("zoneEntityC:" + zoneEntityC); + + +// register the call back so it fires before each data send +Script.update.connect(function(deltaTime) { + // stop it... + if (count >= stopAfter) { + print("calling Script.stop()"); + Script.stop(); + } + count++; +}); + From dbf40afa4722689768cca3175e2a4b8e967bc0b6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 17 Apr 2015 18:25:20 +0200 Subject: [PATCH 25/74] Remove deprecated "*InDomainUnit" getter/setter --- libraries/entities/src/EntityItem.cpp | 6 ------ libraries/entities/src/EntityItem.h | 15 --------------- libraries/entities/src/TextEntityItem.cpp | 5 ----- libraries/entities/src/TextEntityItem.h | 1 - 4 files changed, 27 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 12fb1ba99d..0e6976c730 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1033,12 +1033,6 @@ AABox EntityItem::getAABox() const { return AABox(rotatedExtentsRelativeToRegistrationPoint); } -AABox EntityItem::getAABoxInDomainUnits() const { - AABox box = getAABox(); - box.scale(1.0f / (float)TREE_SCALE); - return box; -} - // NOTE: This should only be used in cases of old bitstreams which only contain radius data // 0,0,0 --> maxDimension,maxDimension,maxDimension // ... has a corner to corner distance of glm::length(maxDimension,maxDimension,maxDimension) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad856698a2..4e1578510d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -145,25 +145,16 @@ public: // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } - glm::vec3 getPositionInDomainUnits() const { return _position / (float)TREE_SCALE; } /// get position in domain scale units (0.0 - 1.0) const glm::vec3& getPosition() const { return _position; } /// get position in meters - /// set position in domain scale units (0.0 - 1.0) - void setPositionInDomainUnits(const glm::vec3& value) - { setPosition(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); } void setPosition(const glm::vec3& value) { _position = value; } - glm::vec3 getCenterInDomainUnits() const { return getCenter() / (float) TREE_SCALE; } glm::vec3 getCenter() const; - glm::vec3 getDimensionsInDomainUnits() const { return _dimensions / (float)TREE_SCALE; } /// get dimensions in domain scale units (0.0 - 1.0) const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in meters - /// set dimensions in domain scale units (0.0 - 1.0) - virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = glm::abs(value) * (float)TREE_SCALE; } - /// set dimensions in meter units (0.0 - TREE_SCALE) virtual void setDimensions(const glm::vec3& value) { _dimensions = glm::abs(value); } @@ -182,15 +173,11 @@ public: float getDensity() const { return _density; } - glm::vec3 getVelocityInDomainUnits() const { return _velocity / (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second const glm::vec3 getVelocity() const { return _velocity; } /// get velocity in meters - void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value * (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second void setVelocity(const glm::vec3& value) { _velocity = value; } /// velocity in meters bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; } - glm::vec3 getGravityInDomainUnits() const { return _gravity / (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters - void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value * (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } @@ -220,7 +207,6 @@ public: AACube getMaximumAACube() const; AACube getMinimumAACube() const; AABox getAABox() const; /// axis aligned bounding box in world-frame (meters) - AABox getAABoxInDomainUnits() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) const QString& getScript() const { return _script; } void setScript(const QString& value) { _script = value; } @@ -268,7 +254,6 @@ public: float getRadius() const; virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } - virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); } virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 39a4d48d96..34d0ce051c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -48,11 +48,6 @@ void TextEntityItem::setDimensions(const glm::vec3& value) { _dimensions = glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH); } -void TextEntityItem::setDimensionsInDomainUnits(const glm::vec3& value) { - // NOTE: Text Entities always have a "depth" of 1cm. - _dimensions = glm::vec3(value.x * (float)TREE_SCALE, value.y * (float)TREE_SCALE, TEXT_ENTITY_ITEM_FIXED_DEPTH); -} - EntityItemProperties TextEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 044975bdc8..d57b5442d6 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -24,7 +24,6 @@ public: /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately virtual void setDimensions(const glm::vec3& value); - virtual void setDimensionsInDomainUnits(const glm::vec3& value); virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity From 8db9f80779b73e5280548cfe1044327ee32ce5e9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 20 Apr 2015 17:13:59 +0200 Subject: [PATCH 26/74] Reimplements "contains" for sphere and particles --- libraries/entities/src/ParticleEffectEntityItem.cpp | 8 ++++++++ libraries/entities/src/ParticleEffectEntityItem.h | 2 ++ libraries/entities/src/SphereEntityItem.cpp | 8 ++++++++ libraries/entities/src/SphereEntityItem.h | 3 +-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 45312f465b..f12259d057 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -236,6 +236,14 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius()); } +bool ParticleEffectEntityItem::contains(const glm::vec3& point) const { + // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. + glm::vec3 transformedPoint = (point - getPosition()) / (getDimensions() / 2.0f); + + // Return whether said point is inside the sphere. + return glm::length(transformedPoint) <= 1.0f; +} + bool ParticleEffectEntityItem::isAnimatingSomething() const { return getAnimationIsPlaying() && getAnimationFPS() != 0.0f; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index b00eb94685..b563274fa1 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -77,6 +77,8 @@ public: _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; } + + virtual bool contains(const glm::vec3& point) const; void updateShapeType(ShapeType type); virtual ShapeType getShapeType() const { return _shapeType; } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 132ad43336..4a756be618 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -92,6 +92,14 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } +bool SphereEntityItem::contains(const glm::vec3& point) const { + // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. + glm::vec3 transformedPoint = (point - getPosition()) / (getDimensions() / 2.0f); + + // Return whether said point is inside the sphere. + return glm::length(transformedPoint) <= 1.0f; +} + bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index f79a2db7ff..98450121c5 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -50,8 +50,7 @@ public: _color[BLUE_INDEX] = value.blue; } - // TODO: implement proper contains for 3D ellipsoid - //virtual bool contains(const glm::vec3& point) const; + virtual bool contains(const glm::vec3& point) const; virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; } From 955723acf10465d46991cce5d7fb141916b386bd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 20 Apr 2015 17:21:27 +0200 Subject: [PATCH 27/74] RenderableEntityItem uses collision hull in contains --- .../src/RenderableModelEntityItem.cpp | 32 +++++++++++++++++++ .../src/RenderableModelEntityItem.h | 2 ++ libraries/shared/src/GLMHelpers.cpp | 7 ++++ libraries/shared/src/GLMHelpers.h | 2 ++ 4 files changed, 43 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 86b0be4dd8..ab823d090b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -415,3 +415,35 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } +bool RenderableModelEntityItem::contains(const glm::vec3& point) const { + bool result = EntityItem::contains(point); + + if (result && _model && _model->getCollisionGeometry()) { + const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); + const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); + + auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { + for (unsigned int j = 0; j < indices.size(); j += primitiveSize) { + if (!isPointBehindTrianglesPlane(point, + mesh.vertices[indices[j]], + mesh.vertices[indices[j + 1]], + mesh.vertices[indices[j + 2]])) { + return false; + } + } + return true; + }; + + for (auto mesh : collisionGeometry.meshes) { + for (auto part : mesh.parts) { + // run through all the triangles and quads + if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || + !checkEachPrimitive(mesh, part.quadIndices, 4)) { + return false; + } + } + } + } + + return result; +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index b632357942..ea153a2dd6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -56,6 +56,8 @@ public: bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); + + virtual bool contains(const glm::vec3& point) const; private: void remapTextures(); diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 4e8fb7d3cd..aed73c1989 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -203,6 +203,13 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) { return glm::angleAxis(angle, axis); } +bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2) { + glm::vec3 v1 = p0 - p1, v2 = p2 - p1; // Non-collinear vectors contained in the plane + glm::vec3 n = glm::cross(v1, v2); // Plane's normal vector, pointing out of the triangle + float d = -glm::dot(n, p0); // Compute plane's equation constant + return (glm::dot(n, point) + d) <= 0; +} + glm::vec3 extractTranslation(const glm::mat4& matrix) { return glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]); } diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 50393b7f5f..e3a2c383e2 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -71,6 +71,8 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2); glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); +bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2); + glm::vec3 extractTranslation(const glm::mat4& matrix); void setTranslation(glm::mat4& matrix, const glm::vec3& translation); From f3fcb749df2787b2886db9a7e8875f0f20a3cffa Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 20 Apr 2015 22:51:39 +0200 Subject: [PATCH 28/74] Fix algorithm + add comments --- .../src/RenderableModelEntityItem.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ab823d090b..e2c3de70af 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -416,34 +416,46 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } bool RenderableModelEntityItem::contains(const glm::vec3& point) const { - bool result = EntityItem::contains(point); - - if (result && _model && _model->getCollisionGeometry()) { + if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { + // Check whether the point is "behind" all the primitives. for (unsigned int j = 0; j < indices.size(); j += primitiveSize) { if (!isPointBehindTrianglesPlane(point, mesh.vertices[indices[j]], mesh.vertices[indices[j + 1]], mesh.vertices[indices[j + 2]])) { + // it's not behind at least one so we bail return false; } } return true; }; + // Check that the point is contained in at least one convex mesh. for (auto mesh : collisionGeometry.meshes) { + bool insideMesh = true; + + // To be considered inside a convex mesh, + // the point needs to be "behind" all the primitives respective planes. for (auto part : mesh.parts) { // run through all the triangles and quads if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || !checkEachPrimitive(mesh, part.quadIndices, 4)) { - return false; + // If not, the point is outside, bail for this mesh + insideMesh = false; + continue; } } + if (insideMesh) { + // It's inside this mesh, return true. + return true; + } } } - return result; + // It wasn't in any mesh, return false. + return false; } From b446644549592ddb65e25e1bedd1682cb31da28c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 14:12:37 +0200 Subject: [PATCH 29/74] Rename CollisionModelURL handle --- libraries/entities/src/EntityItemProperties.cpp | 6 +++--- libraries/entities/src/EntityItemProperties.h | 4 ++-- libraries/entities/src/ModelEntityItem.cpp | 8 ++++---- tests/octree/src/OctreeTests.cpp | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5c834f71bf..01fa90f905 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -245,7 +245,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); - CHECK_PROPERTY_CHANGE(PROP_COLLISION_MODEL_URL, collisionModelURL); + CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, collisionModelURL); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, animationURL); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, animationIsPlaying); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex); @@ -618,7 +618,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem if (properties.getType() == EntityTypes::Model) { APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL()); - APPEND_ENTITY_PROPERTY(PROP_COLLISION_MODEL_URL, appendValue, properties.getCollisionModelURL()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCollisionModelURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex()); @@ -864,7 +864,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Model) { READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL); - READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COLLISION_MODEL_URL, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 5172b3abba..6a5465cdc1 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -93,7 +93,7 @@ enum EntityPropertyList { PROP_LOCAL_GRAVITY, PROP_PARTICLE_RADIUS, - PROP_COLLISION_MODEL_URL, + PROP_COMPOUND_SHAPE_URL, PROP_MARKETPLACE_ID, PROP_ACCELERATION, PROP_SIMULATOR_ID, @@ -197,7 +197,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor); DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString); - DEFINE_PROPERTY_REF(PROP_COLLISION_MODEL_URL, CollisionModelURL, collisionModelURL, QString); + DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CollisionModelURL, collisionModelURL, QString); DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString); DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float); DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index f95eeea8e4..b8de15f99a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -100,9 +100,9 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) { setCollisionModelURL(""); } else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) { - READ_ENTITY_PROPERTY_STRING(PROP_COLLISION_MODEL_URL_OLD_VERSION, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); } else { - READ_ENTITY_PROPERTY_STRING(PROP_COLLISION_MODEL_URL, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); } READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_URL, setAnimationURL); @@ -140,7 +140,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_MODEL_URL; - requestedProperties += PROP_COLLISION_MODEL_URL; + requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_ANIMATION_URL; requestedProperties += PROP_ANIMATION_FPS; requestedProperties += PROP_ANIMATION_FRAME_INDEX; @@ -164,7 +164,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, getModelURL()); - APPEND_ENTITY_PROPERTY(PROP_COLLISION_MODEL_URL, appendValue, getCollisionModelURL()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCollisionModelURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, getAnimationURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex()); diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 705a50aa10..4cfadbccfc 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -74,7 +74,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) { props.setHasProperty(PROP_POSITION); props.setHasProperty(PROP_RADIUS); props.setHasProperty(PROP_MODEL_URL); - props.setHasProperty(PROP_COLLISION_MODEL_URL); + props.setHasProperty(PROP_COMPOUND_SHAPE_URL); props.setHasProperty(PROP_ROTATION); QByteArray encoded = props.encode(); From 7f3be9c89b5b0ecf5decaad39e756aa288f253f7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 15:24:32 +0200 Subject: [PATCH 30/74] Add shapeType/compoundShapeURL to ZoneEntities --- .../entities/src/EntityItemProperties.cpp | 5 ++++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/ZoneEntityItem.cpp | 24 +++++++++++++++++++ libraries/entities/src/ZoneEntityItem.h | 13 +++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 01fa90f905..4ffc872a86 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -657,6 +657,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, properties.getStageAltitude()); APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, properties.getStageDay()); APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, properties.getStageHour()); + + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)properties.getShapeType()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL()); } APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID()); @@ -903,6 +906,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_ALTITUDE, float, setStageAltitude); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_DAY, quint16, setStageDay); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); } READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 6a5465cdc1..8faa9db0e0 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -198,6 +198,7 @@ public: DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor); DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString); DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CollisionModelURL, collisionModelURL, QString); + DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString); DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float); DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float); diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index e0fe238c57..6439922a5d 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -31,6 +31,8 @@ const float ZoneEntityItem::DEFAULT_STAGE_LONGITUDE = 122.407f; const float ZoneEntityItem::DEFAULT_STAGE_ALTITUDE = 0.03f; const quint16 ZoneEntityItem::DEFAULT_STAGE_DAY = 60; const float ZoneEntityItem::DEFAULT_STAGE_HOUR = 12.0f; +const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX; +const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = ""; EntityItem* ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItem* result = new ZoneEntityItem(entityID, properties); @@ -73,6 +75,8 @@ EntityItemProperties ZoneEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageAltitude, getStageAltitude); COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageDay, getStageDay); COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageHour, getStageHour); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); return properties; } @@ -91,6 +95,8 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageAltitude, setStageAltitude); SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageDay, setStageDay); SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageHour, setStageHour); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); if (somethingChanged) { bool wantDebug = false; @@ -122,6 +128,8 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _stageAltitude); READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay); READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour); + READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, _shapeType); + READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, _compoundShapeURL); return bytesRead; } @@ -141,6 +149,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_STAGE_ALTITUDE; requestedProperties += PROP_STAGE_DAY; requestedProperties += PROP_STAGE_HOUR; + requestedProperties += PROP_SHAPE_TYPE; + requestedProperties += PROP_COMPOUND_SHAPE_URL; return requestedProperties; } @@ -165,6 +175,8 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getStageAltitude()); APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getStageDay()); APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getStageHour()); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL()); } void ZoneEntityItem::debugDump() const { @@ -185,3 +197,15 @@ void ZoneEntityItem::debugDump() const { qCDebug(entities) << " _stageHour:" << _stageHour; } +ShapeType ZoneEntityItem::getShapeType() const { + if (_shapeType == SHAPE_TYPE_COMPOUND) { + return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; + } else { + return _shapeType; + } +} + +void ZoneEntityItem::setCompoundShapeURL(const QString& url) { + _compoundShapeURL = url; + _shapeType = _compoundShapeURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND; +} diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 8f1b15d174..bc44d70737 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -91,7 +91,13 @@ public: static bool getZonesArePickable() { return _zonesArePickable; } static void setZonesArePickable(bool value) { _zonesArePickable = value; } - + + void updateShapeType(ShapeType type) { _shapeType = type; } + virtual ShapeType getShapeType() const; + + virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); } + const QString getCompoundShapeURL() const { return _compoundShapeURL; } + virtual void setCompoundShapeURL(const QString& url); virtual void debugDump() const; @@ -105,6 +111,8 @@ public: static const float DEFAULT_STAGE_ALTITUDE; static const quint16 DEFAULT_STAGE_DAY; static const float DEFAULT_STAGE_HOUR; + static const ShapeType DEFAULT_SHAPE_TYPE; + static const QString DEFAULT_COMPOUND_SHAPE_URL; protected: // properties of the "sun" in the zone @@ -118,6 +126,9 @@ protected: float _stageAltitude; uint16_t _stageDay; float _stageHour; + + ShapeType _shapeType = SHAPE_TYPE_NONE; + QString _compoundShapeURL; static bool _zonesArePickable; }; From 8dc98d86b559c39dc34ef4a519b12e87a8c5ce29 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 15:46:54 +0200 Subject: [PATCH 31/74] Bump entities packet version --- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 8f0cee10cf..8fedc6b979 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_ZONE_ENTITIES_EXIST; + return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index a05df968bd..01302f5568 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -138,5 +138,6 @@ const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14; const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15; const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16; const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17; +const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18; #endif // hifi_PacketHeaders_h From 9cec25614212ad0ff85f043c68a4f7f71e06cf8b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 15:51:46 +0200 Subject: [PATCH 32/74] Rename collisionModelURL members/methods --- .../src/EntityTreeRenderer.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 10 +++---- .../src/RenderableModelEntityItem.h | 2 +- .../entities/src/EntityItemProperties.cpp | 16 +++++------ libraries/entities/src/EntityItemProperties.h | 3 +- libraries/entities/src/ModelEntityItem.cpp | 28 +++++++++---------- libraries/entities/src/ModelEntityItem.h | 8 +++--- 7 files changed, 34 insertions(+), 35 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c14a821a38..d5d79f8bad 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -551,7 +551,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(const Entit if (entityItem->getType() == EntityTypes::Model) { const RenderableModelEntityItem* constModelEntityItem = dynamic_cast(entityItem); - if (constModelEntityItem->hasCollisionModel()) { + if (constModelEntityItem->hasCompoundShapeURL()) { RenderableModelEntityItem* modelEntityItem = const_cast(constModelEntityItem); Model* model = modelEntityItem->getModel(this); if (model) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e2c3de70af..b3ac6c2af3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -224,10 +224,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // if we have a previously allocated model, but its URL doesn't match // then we need to let our renderer update our model for us. if (_model && QUrl(getModelURL()) != _model->getURL()) { - result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL()); + result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL()); _needsInitialSimulation = true; } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one - result = _model = _myRenderer->allocateModel(getModelURL(), getCollisionModelURL()); + result = _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL()); _needsInitialSimulation = true; } else { // we already have the model we want... result = _model; @@ -267,8 +267,8 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking); } -void RenderableModelEntityItem::setCollisionModelURL(const QString& url) { - ModelEntityItem::setCollisionModelURL(url); +void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { + ModelEntityItem::setCompoundShapeURL(url); if (_model) { _model->setCollisionModelURL(QUrl(url)); } @@ -410,7 +410,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } glm::vec3 collisionModelDimensions = box.getDimensions(); - info.setParams(type, collisionModelDimensions, _collisionModelURL); + info.setParams(type, collisionModelDimensions, _compoundShapeURL); info.setConvexHulls(_points); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index ea153a2dd6..43f18af0db 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -52,7 +52,7 @@ public: bool needsToCallUpdate() const; - virtual void setCollisionModelURL(const QString& url); + virtual void setCompoundShapeURL(const QString& url); bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4ffc872a86..6ef6877bb1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -44,7 +44,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT), CONSTRUCT_PROPERTY(color, ), CONSTRUCT_PROPERTY(modelURL, ""), - CONSTRUCT_PROPERTY(collisionModelURL, ""), + CONSTRUCT_PROPERTY(compoundShapeURL, ""), CONSTRUCT_PROPERTY(animationURL, ""), CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS), CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX), @@ -175,7 +175,7 @@ void EntityItemProperties::debugDump() const { qCDebug(entities) << " _position=" << _position.x << "," << _position.y << "," << _position.z; qCDebug(entities) << " _dimensions=" << getDimensions(); qCDebug(entities) << " _modelURL=" << _modelURL; - qCDebug(entities) << " _collisionModelURL=" << _collisionModelURL; + qCDebug(entities) << " _compoundShapeURL=" << _compoundShapeURL; qCDebug(entities) << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); props.debugDumpBits(); @@ -245,7 +245,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); - CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, collisionModelURL); + CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, animationURL); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, animationIsPlaying); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex); @@ -322,7 +322,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(visible); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(color); COPY_PROPERTY_TO_QSCRIPTVALUE(modelURL); - COPY_PROPERTY_TO_QSCRIPTVALUE(collisionModelURL); + COPY_PROPERTY_TO_QSCRIPTVALUE(compoundShapeURL); COPY_PROPERTY_TO_QSCRIPTVALUE(animationURL); COPY_PROPERTY_TO_QSCRIPTVALUE(animationIsPlaying); COPY_PROPERTY_TO_QSCRIPTVALUE(animationFPS); @@ -417,7 +417,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(visible, setVisible); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(color, setColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(modelURL, setModelURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(collisionModelURL, setCollisionModelURL); + COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(compoundShapeURL, setCompoundShapeURL); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(animationURL, setAnimationURL); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(animationIsPlaying, setAnimationIsPlaying); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFPS, setAnimationFPS); @@ -618,7 +618,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem if (properties.getType() == EntityTypes::Model) { APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL()); - APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCollisionModelURL()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex()); @@ -867,7 +867,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Model) { READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL); - READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); @@ -963,7 +963,7 @@ void EntityItemProperties::markAllChanged() { _visibleChanged = true; _colorChanged = true; _modelURLChanged = true; - _collisionModelURLChanged = true; + _compoundShapeURLChanged = true; _animationURLChanged = true; _animationIsPlayingChanged = true; _animationFrameIndexChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 8faa9db0e0..faec9e1206 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -197,7 +197,6 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor); DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString); - DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CollisionModelURL, collisionModelURL, QString); DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString); DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float); @@ -341,7 +340,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionModelURL, collisionModelURL, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, CompoundShapeURL, compoundShapeURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationURL, animationURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFPS, animationFPS, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFrameIndex, animationFrameIndex, ""); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b8de15f99a..7616924f4a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -47,7 +47,7 @@ EntityItemProperties ModelEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionModelURL, getCollisionModelURL); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationURL, getAnimationURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying); COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex); @@ -65,7 +65,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionModelURL, setCollisionModelURL); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationURL, setAnimationURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying); SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex); @@ -98,11 +98,11 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); READ_ENTITY_PROPERTY_STRING(PROP_MODEL_URL, setModelURL); if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) { - setCollisionModelURL(""); + setCompoundShapeURL(""); } else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) { - READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); } else { - READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCollisionModelURL); + READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); } READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_URL, setAnimationURL); @@ -164,7 +164,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, getModelURL()); - APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCollisionModelURL()); + APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, getAnimationURL()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex()); @@ -272,7 +272,7 @@ void ModelEntityItem::debugDump() const { qCDebug(entities) << " position:" << getPosition(); qCDebug(entities) << " dimensions:" << getDimensions(); qCDebug(entities) << " model URL:" << getModelURL(); - qCDebug(entities) << " collision model URL:" << getCollisionModelURL(); + qCDebug(entities) << " collision model URL:" << getCompoundShapeURL(); } void ModelEntityItem::updateShapeType(ShapeType type) { @@ -280,8 +280,8 @@ void ModelEntityItem::updateShapeType(ShapeType type) { // we have allowed inconsistent ShapeType's to be stored in SVO files in the past (this was a bug) // but we are now enforcing the entity properties to be consistent. To make the possible we're // introducing a temporary workaround: we will ignore ShapeType updates that conflict with the - // _collisionModelURL. - if (hasCollisionModel()) { + // _compoundShapeURL. + if (hasCompoundShapeURL()) { type = SHAPE_TYPE_COMPOUND; } // END_TEMPORARY_WORKAROUND @@ -295,17 +295,17 @@ void ModelEntityItem::updateShapeType(ShapeType type) { // virtual ShapeType ModelEntityItem::getShapeType() const { if (_shapeType == SHAPE_TYPE_COMPOUND) { - return hasCollisionModel() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; + return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; } else { return _shapeType; } } -void ModelEntityItem::setCollisionModelURL(const QString& url) { - if (_collisionModelURL != url) { - _collisionModelURL = url; +void ModelEntityItem::setCompoundShapeURL(const QString& url) { + if (_compoundShapeURL != url) { + _compoundShapeURL = url; _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; - _shapeType = _collisionModelURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND; + _shapeType = _compoundShapeURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND; } } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 057c5babaf..46fce6ff5f 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -57,13 +57,13 @@ public: const rgbColor& getColor() const { return _color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } bool hasModel() const { return !_modelURL.isEmpty(); } - virtual bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); } + virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); } static const QString DEFAULT_MODEL_URL; const QString& getModelURL() const { return _modelURL; } static const QString DEFAULT_COLLISION_MODEL_URL; - const QString& getCollisionModelURL() const { return _collisionModelURL; } + const QString& getCompoundShapeURL() const { return _compoundShapeURL; } bool hasAnimation() const { return !_animationURL.isEmpty(); } static const QString DEFAULT_ANIMATION_URL; @@ -78,7 +78,7 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } - virtual void setCollisionModelURL(const QString& url); + virtual void setCompoundShapeURL(const QString& url); void setAnimationURL(const QString& url); static const float DEFAULT_ANIMATION_FRAME_INDEX; void setAnimationFrameIndex(float value); @@ -126,7 +126,7 @@ protected: rgbColor _color; QString _modelURL; - QString _collisionModelURL; + QString _compoundShapeURL; quint64 _lastAnimated; QString _animationURL; From 99b3ef0d75fc0961e5c16b83e6364138d1b08a32 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 20:18:35 +0200 Subject: [PATCH 33/74] Move contain function to FBXGeometry --- .../src/RenderableModelEntityItem.cpp | 38 +--------------- libraries/fbx/src/FBXReader.cpp | 43 ++++++++++++++++++- libraries/fbx/src/FBXReader.h | 1 + 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b3ac6c2af3..3f8899f6bd 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -420,42 +420,8 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); - auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { - // Check whether the point is "behind" all the primitives. - for (unsigned int j = 0; j < indices.size(); j += primitiveSize) { - if (!isPointBehindTrianglesPlane(point, - mesh.vertices[indices[j]], - mesh.vertices[indices[j + 1]], - mesh.vertices[indices[j + 2]])) { - // it's not behind at least one so we bail - return false; - } - } - return true; - }; - - // Check that the point is contained in at least one convex mesh. - for (auto mesh : collisionGeometry.meshes) { - bool insideMesh = true; - - // To be considered inside a convex mesh, - // the point needs to be "behind" all the primitives respective planes. - for (auto part : mesh.parts) { - // run through all the triangles and quads - if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || - !checkEachPrimitive(mesh, part.quadIndices, 4)) { - // If not, the point is outside, bail for this mesh - insideMesh = false; - continue; - } - } - if (insideMesh) { - // It's inside this mesh, return true. - return true; - } - } + return collisionGeometry.convexHullContains(point); } - - // It wasn't in any mesh, return false. + return false; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 25ea9ef8e1..95cd99852f 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -125,6 +125,47 @@ Extents FBXGeometry::getUnscaledMeshExtents() const { return scaledExtents; } +// TODO: Move to model::Mesh when Sam's ready +bool FBXGeometry::convexHullContains(const glm::vec3& point) const { + auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { + // Check whether the point is "behind" all the primitives. + for (unsigned int j = 0; j < indices.size(); j += primitiveSize) { + if (!isPointBehindTrianglesPlane(point, + mesh.vertices[indices[j]], + mesh.vertices[indices[j + 1]], + mesh.vertices[indices[j + 2]])) { + // it's not behind at least one so we bail + return false; + } + } + return true; + }; + + // Check that the point is contained in at least one convex mesh. + for (auto mesh : meshes) { + bool insideMesh = true; + + // To be considered inside a convex mesh, + // the point needs to be "behind" all the primitives respective planes. + for (auto part : mesh.parts) { + // run through all the triangles and quads + if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || + !checkEachPrimitive(mesh, part.quadIndices, 4)) { + // If not, the point is outside, bail for this mesh + insideMesh = false; + continue; + } + } + if (insideMesh) { + // It's inside this mesh, return true. + return true; + } + } + + // It wasn't in any mesh, return false. + return false; +} + QString FBXGeometry::getModelNameOfMesh(int meshIndex) const { if (meshIndicesToModelNames.contains(meshIndex)) { return meshIndicesToModelNames.value(meshIndex); @@ -132,8 +173,6 @@ QString FBXGeometry::getModelNameOfMesh(int meshIndex) const { return QString(); } - - static int fbxGeometryMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType >(); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index d1576bc02a..871f3d0581 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -252,6 +252,7 @@ public: /// Returns the unscaled extents of the model's mesh Extents getUnscaledMeshExtents() const; + bool convexHullContains(const glm::vec3& point) const; QHash meshIndicesToModelNames; From 287d625c5221e205a068bdf4b02924946ff75451 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 22 Apr 2015 20:19:45 +0200 Subject: [PATCH 34/74] Added RenderableZoneEntities class --- .../src/RenderableZoneEntityItem.cpp | 50 +++++++++++++++++++ .../src/RenderableZoneEntityItem.h | 39 +++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.cpp create mode 100644 libraries/entities-renderer/src/RenderableZoneEntityItem.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp new file mode 100644 index 0000000000..1c80b1f317 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -0,0 +1,50 @@ +// +// RenderableZoneEntityItem.cpp +// +// +// Created by Clement on 4/22/15. +// Copyright 2015 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 "RenderableZoneEntityItem.h" + +#include +#include + +EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + return new RenderableZoneEntityItem(entityID, properties); +} + +bool RenderableZoneEntityItem::setProperties(const EntityItemProperties& properties) { + QString oldShapeURL = getCompoundShapeURL(); + bool somethingChanged = ZoneEntityItem::setProperties(properties); + if (somethingChanged && oldShapeURL != getCompoundShapeURL()) { + _compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); + } + return somethingChanged; +} + +int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + QString oldShapeURL = getCompoundShapeURL(); + int bytesRead = ZoneEntityItem::readEntitySubclassDataFromBuffer(data, bytesLeftToRead, + args, propertyFlags, overwriteLocalData); + if (oldShapeURL != getCompoundShapeURL()) { + _compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); + } + return bytesRead; +} + +bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { + if (EntityItem::contains(point) && _compoundShapeModel) { + const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry(); + + return geometry.convexHullContains(point); + } + + return false; +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h new file mode 100644 index 0000000000..8d8d8b4b3f --- /dev/null +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -0,0 +1,39 @@ +// +// RenderableZoneEntityItem.h +// +// +// Created by Clement on 4/22/15. +// Copyright 2015 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_RenderableZoneEntityItem_h +#define hifi_RenderableZoneEntityItem_h + +#include + +class NetworkGeometry; + +class RenderableZoneEntityItem : public ZoneEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + ZoneEntityItem(entityItemID, properties) + { } + + virtual bool setProperties(const EntityItemProperties& properties); + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + virtual bool contains(const glm::vec3& point) const; + +private: + + QSharedPointer _compoundShapeModel; +}; + +#endif // hifi_RenderableZoneEntityItem_h \ No newline at end of file From fb4e334c708e516759216d1ecc6be3a3cfd6efe2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 22 Apr 2015 12:38:34 -0700 Subject: [PATCH 35/74] implement volume priority for zones --- .../example/entities/zoneEntityExample.js | 4 +- .../src/EntityTreeRenderer.cpp | 99 ++++++------------- .../src/EntityTreeRenderer.h | 7 +- libraries/entities/src/EntityItem.h | 1 + 4 files changed, 35 insertions(+), 76 deletions(-) diff --git a/examples/example/entities/zoneEntityExample.js b/examples/example/entities/zoneEntityExample.js index 84d87d1370..052de06a1d 100644 --- a/examples/example/entities/zoneEntityExample.js +++ b/examples/example/entities/zoneEntityExample.js @@ -29,7 +29,7 @@ print("zoneEntityA:" + zoneEntityA); var zoneEntityB = Entities.addEntity({ type: "Zone", - position: { x: 1, y: 1, z: 21 }, + position: { x: 5, y: 5, z: 5 }, dimensions: { x: 2, y: 2, z: 2 }, keyLightColor: { red: 0, green: 255, blue: 0 }, keyLightIntensity: 0.9, @@ -46,7 +46,7 @@ print("zoneEntityB:" + zoneEntityB); var zoneEntityC = Entities.addEntity({ type: "Zone", - position: { x: 5, y: 5, z: 15 }, + position: { x: 5, y: 10, z: 5 }, dimensions: { x: 10, y: 10, z: 10 }, keyLightColor: { red: 0, green: 0, blue: 255 }, keyLightIntensity: 0.75, diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c14a821a38..f6557b5f9a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -395,67 +395,14 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _tree->lockForRead(); - // Implement some kind of a stack/union mechanism here... - // - // * As you enter a zone (A), you use it's properties - // * if already in a zone, and you enter the union of that zone and a new zone (A + B) - // you use the settings of the new zone (B) you entered.. but remember that you were previously - // in zone A - // * if you enter a new zone and are in the union of 3 zones (A+B+C) then use zone C and remember - // you were most recently in B - _lastZones = _currentZones; - _currentZones.clear(); + // Whenever you're in an intersection between zones, we will always choose the smallest zone. + _bestZone = NULL; + _bestZoneVolume = std::numeric_limits::max(); _tree->recurseTreeWithOperation(renderOperation, &args); - const ZoneEntityItem* bestZone = NULL; - - if (_currentZones.empty()) { - // if we're not in any current zone, then we can completely erase our zoneHistory - _zoneHistory.clear(); - } else { - // we're in some zone... check to see if we've changed zones.. - QSet newZones = _currentZones - _lastZones; - if (!newZones.empty()) { - // we just entered a new zone, so we want to make a shift - EntityItemID theNewZone = *(newZones.begin()); // random we don't care, if it's one, then this works. - _zoneHistory << _currentZone; // remember the single zone we used to be in. - _currentZone = theNewZone; // change to our new zone - - // do something to remove any item of _zoneHistory that is not in _currentZones - QStack newHistory; - QStack::iterator i = _zoneHistory.begin(); - while(i != _zoneHistory.end()) { - EntityItemID zoneID = *i; - if (_currentZones.contains(zoneID)) { - newHistory << zoneID; - } - ++i; - } - - _zoneHistory = newHistory; - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } else { - - if (_currentZones.contains(_currentZone)) { - // No change in zone, keep the current zone - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } else { - if (!_zoneHistory.empty()) { - _currentZone = _zoneHistory.pop(); - bestZone = dynamic_cast( - static_cast(_tree)->findEntityByEntityItemID(_currentZone)); - } - - } - - } - } - QSharedPointer scene = DependencyManager::get(); - if (bestZone) { + if (_bestZone) { if (!_hasPreviousZone) { _previousKeyLightColor = scene->getKeyLightColor(); _previousKeyLightIntensity = scene->getKeyLightIntensity(); @@ -469,18 +416,16 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _previousStageDay = scene->getStageYearTime(); _hasPreviousZone = true; } - scene->setKeyLightColor(bestZone->getKeyLightColorVec3()); - scene->setKeyLightIntensity(bestZone->getKeyLightIntensity()); - scene->setKeyLightAmbientIntensity(bestZone->getKeyLightAmbientIntensity()); - scene->setKeyLightDirection(bestZone->getKeyLightDirection()); - scene->setStageSunModelEnable(bestZone->getStageSunModelEnabled()); - scene->setStageLocation(bestZone->getStageLongitude(), bestZone->getStageLatitude(), - bestZone->getStageAltitude()); - scene->setStageDayTime(bestZone->getStageHour()); - scene->setStageYearTime(bestZone->getStageDay()); - + scene->setKeyLightColor(_bestZone->getKeyLightColorVec3()); + scene->setKeyLightIntensity(_bestZone->getKeyLightIntensity()); + scene->setKeyLightAmbientIntensity(_bestZone->getKeyLightAmbientIntensity()); + scene->setKeyLightDirection(_bestZone->getKeyLightDirection()); + scene->setStageSunModelEnable(_bestZone->getStageSunModelEnabled()); + scene->setStageLocation(_bestZone->getStageLongitude(), _bestZone->getStageLatitude(), + _bestZone->getStageAltitude()); + scene->setStageDayTime(_bestZone->getStageHour()); + scene->setStageYearTime(_bestZone->getStageDay()); } else { - _currentZone = EntityItemID(); // clear out current zone if (_hasPreviousZone) { scene->setKeyLightColor(_previousKeyLightColor); scene->setKeyLightIntensity(_previousKeyLightIntensity); @@ -698,7 +643,23 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) // like other entity types. So we will skip the normal rendering tests if (entityItem->getType() == EntityTypes::Zone) { if (entityItem->contains(args->_viewFrustum->getPosition())) { - _currentZones << entityItem->getEntityItemID(); + float entityVolumeEstimate = entityItem->getVolumeEstimate(); + if (entityVolumeEstimate < _bestZoneVolume) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } else if (entityVolumeEstimate == _bestZoneVolume) { + if (!_bestZone) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } else { + // in the case of the volume being equal, we will use the + // EntityItemID to deterministically pick one entity over the other + if (entityItem->getEntityItemID() < _bestZone->getEntityItemID()) { + _bestZoneVolume = entityVolumeEstimate; + _bestZone = dynamic_cast(entityItem); + } + } + } } } else { // render entityItem diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index fd979fc9f9..8f720e5e48 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -167,12 +167,9 @@ private: QMultiMap _waitingOnPreload; - QSet _lastZones; - QSet _currentZones; - QStack _zoneHistory; - EntityItemID _currentZone; - bool _hasPreviousZone = false; + const ZoneEntityItem* _bestZone; + float _bestZoneVolume; glm::vec3 _previousKeyLightColor; float _previousKeyLightIntensity; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad856698a2..28f1c7790b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -272,6 +272,7 @@ public: virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); + virtual float getVolumeEstimate() const { return _dimensions.x * _dimensions.y * _dimensions.z; } /// return preferred shape type (actual physical shape may differ) virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } From 35e2b87a70d43cef7447db218df548584528987a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Apr 2015 13:15:57 -0700 Subject: [PATCH 36/74] Rename DDE menu items --- interface/src/Application.cpp | 4 ++-- interface/src/Menu.cpp | 4 ++-- interface/src/Menu.h | 4 ++-- interface/src/devices/DdeFaceTracker.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 92cb750d98..d6894a825a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1744,9 +1744,9 @@ void Application::setActiveFaceTracker() { DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); #endif #ifdef HAVE_DDE - bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); + bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera); Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE); - Menu::getInstance()->getActionForOption(MenuOption::DDEFiltering)->setVisible(isUsingDDE); + Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE); DependencyManager::get()->setEnabled(isUsingDDE); #endif } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6bcc09f316..143c56c935 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -371,7 +371,7 @@ Menu::Menu() { faceTrackerGroup->addAction(faceshiftFaceTracker); #endif #ifdef HAVE_DDE - QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression, + QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseCamera, 0, false, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker); @@ -381,7 +381,7 @@ Menu::Menu() { faceTrackingMenu->addSeparator(); QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); useAudioForMouth->setVisible(false); - QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFiltering, 0, true); + QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); ddeFiltering->setVisible(false); #endif diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8f54d1a796..5a162d31bc 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -130,8 +130,6 @@ namespace MenuOption { const QString ControlWithSpeech = "Control With Speech"; const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; - const QString DDEFaceRegression = "DDE Face Regression"; - const QString DDEFiltering = "DDE Filtering"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; @@ -246,6 +244,8 @@ namespace MenuOption { const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; const QString UseAudioForMouth = "Use Audio for Mouth"; + const QString UseCamera = "Use Camera"; + const QString VelocityFilter = "Velocity Filter"; const QString VisibleToEveryone = "Everyone"; const QString VisibleToFriends = "Friends"; const QString VisibleToNoOne = "No one"; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 938cee729f..03989c6ffb 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -285,7 +285,7 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const { void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { - bool isFiltering = Menu::getInstance()->isOptionChecked(MenuOption::DDEFiltering); + bool isFiltering = Menu::getInstance()->isOptionChecked(MenuOption::VelocityFilter); Packet packet; int bytesToCopy = glm::min((int)sizeof(packet), buffer.size()); From 8d8c4babba722957683f9bca92f79d01ddb17369 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 19:05:57 -0700 Subject: [PATCH 37/74] Coding standard fixes --- interface/src/Application.cpp | 3 +- interface/src/ui/ApplicationOverlay.cpp | 10 +- interface/src/ui/LoginDialog.h | 6 +- .../render-utils/src/OffscreenGlCanvas.cpp | 2 +- .../render-utils/src/OffscreenGlCanvas.h | 2 +- .../render-utils/src/OffscreenQmlDialog.cpp | 2 +- .../render-utils/src/OffscreenQmlDialog.h | 2 +- libraries/render-utils/src/OffscreenUi.cpp | 139 +++++++++--------- libraries/render-utils/src/OffscreenUi.h | 50 +++---- 9 files changed, 107 insertions(+), 109 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e7f8096e33..5adc408d8c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -569,8 +569,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : this->installEventFilter(this); // The offscreen UI needs to intercept the mouse and keyboard // events coming from the onscreen window - _glWidget->installEventFilter( - DependencyManager::get().data()); + _glWidget->installEventFilter(DependencyManager::get().data()); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 5583790b13..2a8f01aafc 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -237,15 +237,15 @@ void ApplicationOverlay::renderOverlay() { // A quick and dirty solution for compositing the old overlay // texture with the new one template -void with_each_texture(GLuint a, GLuint b, F f) { +void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) { glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); - if (a) { - glBindTexture(GL_TEXTURE_2D, a); + if (firstPassTexture) { + glBindTexture(GL_TEXTURE_2D, firstPassTexture); f(); } - if (b) { - glBindTexture(GL_TEXTURE_2D, b); + if (secondPassTexture) { + glBindTexture(GL_TEXTURE_2D, secondPassTexture); f(); } glBindTexture(GL_TEXTURE_2D, 0); diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index d3f54981a5..7fe44bf543 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -25,7 +25,7 @@ class LoginDialog : public OffscreenQmlDialog public: static void toggleAction(); - LoginDialog(QQuickItem *parent = 0); + LoginDialog(QQuickItem* parent = 0); void setStatusText(const QString & a); QString statusText() const; @@ -39,8 +39,8 @@ protected: void handleLoginCompleted(const QUrl& authURL); void handleLoginFailed(); - Q_INVOKABLE void login(const QString & username, const QString & password); - Q_INVOKABLE void openUrl(const QString & url); + Q_INVOKABLE void login(const QString& username, const QString& password); + Q_INVOKABLE void openUrl(const QString& url); private: QString _statusText; const QString _rootUrl; diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index d6b268d4e9..0e5d4928d8 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -15,7 +15,7 @@ OffscreenGlCanvas::OffscreenGlCanvas() { } -void OffscreenGlCanvas::create(QOpenGLContext * sharedContext) { +void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) { if (nullptr != sharedContext) { sharedContext->doneCurrent(); _context.setFormat(sharedContext->format()); diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h index 1b2f15f690..5a64a4cf10 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.h +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -18,7 +18,7 @@ class OffscreenGlCanvas : public QObject { public: OffscreenGlCanvas(); - void create(QOpenGLContext * sharedContext = nullptr); + void create(QOpenGLContext* sharedContext = nullptr); bool makeCurrent(); void doneCurrent(); diff --git a/libraries/render-utils/src/OffscreenQmlDialog.cpp b/libraries/render-utils/src/OffscreenQmlDialog.cpp index d6cfc9951b..ae0525e17d 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.cpp +++ b/libraries/render-utils/src/OffscreenQmlDialog.cpp @@ -10,7 +10,7 @@ #include "OffscreenQmlDialog.h" -OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem *parent) +OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem* parent) : QQuickItem(parent) { } void OffscreenQmlDialog::hide() { diff --git a/libraries/render-utils/src/OffscreenQmlDialog.h b/libraries/render-utils/src/OffscreenQmlDialog.h index 6e94587fd2..bb69b4b63f 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.h +++ b/libraries/render-utils/src/OffscreenQmlDialog.h @@ -47,7 +47,7 @@ class OffscreenQmlDialog : public QQuickItem { Q_OBJECT public: - OffscreenQmlDialog(QQuickItem *parent = 0); + OffscreenQmlDialog(QQuickItem* parent = 0); protected: void hide(); diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index d9dd030758..6849837da3 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -18,18 +18,18 @@ class OffscreenUiRoot : public QQuickItem { Q_OBJECT public: - OffscreenUiRoot(QQuickItem *parent = 0); - Q_INVOKABLE void information(const QString & title, const QString & text); - Q_INVOKABLE void loadChild(const QUrl & url) { + OffscreenUiRoot(QQuickItem* parent = 0); + Q_INVOKABLE void information(const QString& title, const QString& text); + Q_INVOKABLE void loadChild(const QUrl& url) { DependencyManager::get()->load(url); } }; -OffscreenUiRoot::OffscreenUiRoot(QQuickItem *parent) : QQuickItem(parent) { +OffscreenUiRoot::OffscreenUiRoot(QQuickItem* parent) : QQuickItem(parent) { } -void OffscreenUiRoot::information(const QString & title, const QString & text = "foo") { +void OffscreenUiRoot::information(const QString& title, const QString& text) { OffscreenUi::information(title, text); } @@ -55,7 +55,7 @@ OffscreenUi::~OffscreenUi() { doneCurrent(); } -void OffscreenUi::create(QOpenGLContext * shareContext) { +void OffscreenUi::create(QOpenGLContext* shareContext) { OffscreenGlCanvas::create(shareContext); makeCurrent(); @@ -69,8 +69,9 @@ void OffscreenUi::create(QOpenGLContext * shareContext) { _quickWindow->setFlags(_quickWindow->flags() | static_cast(Qt::WA_TranslucentBackground)); // Create a QML engine. _qmlEngine = new QQmlEngine; - if (!_qmlEngine->incubationController()) + if (!_qmlEngine->incubationController()) { _qmlEngine->setIncubationController(_quickWindow->incubationController()); + } // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. @@ -91,11 +92,11 @@ void OffscreenUi::create(QOpenGLContext * shareContext) { _renderControl->initialize(&_context); } -void OffscreenUi::addImportPath(const QString & path) { +void OffscreenUi::addImportPath(const QString& path) { _qmlEngine->addImportPath(path); } -void OffscreenUi::resize(const QSize & newSize) { +void OffscreenUi::resize(const QSize& newSize) { makeCurrent(); // Clear out any fbos with the old size @@ -115,24 +116,25 @@ void OffscreenUi::resize(const QSize & newSize) { doneCurrent(); } -QQmlContext * OffscreenUi::qmlContext() { +QQmlContext* OffscreenUi::qmlContext() { if (nullptr == _rootItem) { return _qmlComponent->creationContext(); } return QQmlEngine::contextForObject(_rootItem); } -void OffscreenUi::setBaseUrl(const QUrl & baseUrl) { +void OffscreenUi::setBaseUrl(const QUrl& baseUrl) { _qmlEngine->setBaseUrl(baseUrl); } -void OffscreenUi::load(const QUrl & qmlSource, std::function f) { +void OffscreenUi::load(const QUrl& qmlSource, std::function f) { qDebug() << "Loading QML from URL " << qmlSource; _qmlComponent->loadUrl(qmlSource); - if (_qmlComponent->isLoading()) - connect(_qmlComponent, &QQmlComponent::statusChanged, this, [] {}); - else + if (_qmlComponent->isLoading()) { + connect(_qmlComponent, &QQmlComponent::statusChanged, this, []{}); + } else { finishQmlLoad(); + } } void OffscreenUi::requestUpdate() { @@ -156,7 +158,7 @@ void OffscreenUi::finishQmlLoad() { return; } - QObject *newObject = _qmlComponent->create(); + QObject* newObject = _qmlComponent->create(); if (_qmlComponent->isError()) { QList errorList = _qmlComponent->errors(); foreach(const QQmlError &error, errorList) @@ -167,7 +169,7 @@ void OffscreenUi::finishQmlLoad() { return; } - QQuickItem * newItem = qobject_cast(newObject); + QQuickItem* newItem = qobject_cast(newObject); if (!newItem) { qWarning("run: Not a QQuickItem"); delete newObject; @@ -200,8 +202,9 @@ void OffscreenUi::updateQuick() { if (_paused) { return; } - if (!makeCurrent()) + if (!makeCurrent()) { return; + } // Polish, synchronize and render the next frame (into our fbo). In this example // everything happens on the same thread and therefore all three steps are performed @@ -234,7 +237,7 @@ void OffscreenUi::updateQuick() { emit textureUpdated(fbo->texture()); } -QPointF OffscreenUi::mapWindowToUi(const QPointF & p, QObject * dest) { +QPointF OffscreenUi::mapWindowToUi(const QPointF& p, QObject* dest) { vec2 sourceSize; if (dynamic_cast(dest)) { sourceSize = toGlm(((QWidget*)dest)->size()); @@ -252,7 +255,7 @@ QPointF OffscreenUi::mapWindowToUi(const QPointF & p, QObject * dest) { // Event handling customization // -bool OffscreenUi::eventFilter(QObject * dest, QEvent * e) { +bool OffscreenUi::eventFilter(QObject* dest, QEvent* e) { // Only intercept events while we're in an active state if (_paused) { return false; @@ -264,50 +267,46 @@ bool OffscreenUi::eventFilter(QObject * dest, QEvent * e) { } switch (e->type()) { - case QEvent::Resize: - { - QResizeEvent * re = (QResizeEvent *)e; - QGLWidget * widget = dynamic_cast(dest); - if (widget) { - this->resize(re->size()); + case QEvent::Resize: { + QResizeEvent* re = (QResizeEvent*)e; + QGLWidget* widget = dynamic_cast(dest); + if (widget) { + this->resize(re->size()); + } + return false; } - return false; - } - case QEvent::KeyPress: - case QEvent::KeyRelease: - { - e->ignore(); - if (QCoreApplication::sendEvent(_quickWindow, e)) { - return e->isAccepted(); + case QEvent::KeyPress: + case QEvent::KeyRelease: { + e->ignore(); + if (QCoreApplication::sendEvent(_quickWindow, e)) { + return e->isAccepted(); + } + break; } - } - break; - case QEvent::Wheel: - { - QWheelEvent * we = (QWheelEvent*)e; - QWheelEvent mappedEvent(mapWindowToUi(we->pos(), dest), we->delta(), we->buttons(), we->modifiers(), we->orientation()); - QCoreApplication::sendEvent(_quickWindow, &mappedEvent); - return true; - } - break; + case QEvent::Wheel: { + QWheelEvent* we = (QWheelEvent*)e; + QWheelEvent mappedEvent(mapWindowToUi(we->pos(), dest), we->delta(), we->buttons(), we->modifiers(), we->orientation()); + QCoreApplication::sendEvent(_quickWindow, &mappedEvent); + return true; + } - // Fall through - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - { - QMouseEvent * me = (QMouseEvent *)e; - QPointF originalPos = me->localPos(); - QPointF transformedPos = _mouseTranslator(originalPos); - QMouseEvent mappedEvent(e->type(), mapWindowToUi(transformedPos, dest), me->screenPos(), me->button(), me->buttons(), me->modifiers()); - QCoreApplication::sendEvent(_quickWindow, &mappedEvent); - return QObject::event(e); - } + // Fall through + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: { + QMouseEvent* me = (QMouseEvent *)e; + QPointF originalPos = me->localPos(); + QPointF transformedPos = _mouseTranslator(originalPos); + QMouseEvent mappedEvent(e->type(), mapWindowToUi(transformedPos, dest), me->screenPos(), me->button(), me->buttons(), me->modifiers()); + QCoreApplication::sendEvent(_quickWindow, &mappedEvent); + return QObject::event(e); + } - default: break; + default: + break; } return false; @@ -334,22 +333,22 @@ bool OffscreenUi::isPaused() const { return _paused; } -void OffscreenUi::setProxyWindow(QWindow * window) { +void OffscreenUi::setProxyWindow(QWindow* window) { _renderControl->_renderWindow = window; } -void OffscreenUi::show(const QUrl & url, const QString & name) { - QQuickItem * item = _rootItem->findChild(name); +void OffscreenUi::show(const QUrl& url, const QString& name) { + QQuickItem* item = _rootItem->findChild(name); // First load? - if (nullptr == item) { + if (!item) { load(url); return; } item->setEnabled(true); } -void OffscreenUi::toggle(const QUrl & url, const QString & name) { - QQuickItem * item = _rootItem->findChild(name); +void OffscreenUi::toggle(const QUrl& url, const QString& name) { + QQuickItem* item = _rootItem->findChild(name); // First load? if (nullptr == item) { load(url); @@ -358,31 +357,31 @@ void OffscreenUi::toggle(const QUrl & url, const QString & name) { item->setEnabled(!item->isEnabled()); } -void OffscreenUi::messageBox(const QString &title, const QString &text, +void OffscreenUi::messageBox(const QString& title, const QString& text, QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, ButtonCallback f) { } -void OffscreenUi::information(const QString &title, const QString &text, +void OffscreenUi::information(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, ButtonCallback callback) { callback(QMessageBox::information(nullptr, title, text, buttons)); } -void OffscreenUi::question(const QString &title, const QString &text, +void OffscreenUi::question(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, ButtonCallback callback) { callback(QMessageBox::question(nullptr, title, text, buttons)); } -void OffscreenUi::warning(const QString &title, const QString &text, +void OffscreenUi::warning(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, ButtonCallback callback) { callback(QMessageBox::warning(nullptr, title, text, buttons)); } -void OffscreenUi::critical(const QString &title, const QString &text, +void OffscreenUi::critical(const QString& title, const QString& text, QMessageBox::StandardButtons buttons, ButtonCallback callback) { callback(QMessageBox::critical(nullptr, title, text, buttons)); @@ -391,4 +390,4 @@ void OffscreenUi::critical(const QString &title, const QString &text, OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {}; -#include "OffscreenUi.moc" \ No newline at end of file +#include "OffscreenUi.moc" diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index 73c022e4be..16db24e5ae 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -38,7 +38,7 @@ class OffscreenUi : public OffscreenGlCanvas, public Dependency { class QMyQuickRenderControl : public QQuickRenderControl { protected: - QWindow * renderWindow(QPoint * offset) Q_DECL_OVERRIDE{ + QWindow* renderWindow(QPoint* offset) Q_DECL_OVERRIDE{ if (nullptr == _renderWindow) { return QQuickRenderControl::renderWindow(offset); } @@ -49,59 +49,59 @@ class OffscreenUi : public OffscreenGlCanvas, public Dependency { } private: - QWindow * _renderWindow{ nullptr }; + QWindow* _renderWindow{ nullptr }; friend class OffscreenUi; }; public: - using MouseTranslator = std::function < QPointF(const QPointF &) > ; + using MouseTranslator = std::function; OffscreenUi(); virtual ~OffscreenUi(); - void create(QOpenGLContext * context); - void resize(const QSize & size); - void load(const QUrl & qmlSource, std::function f = [](QQmlContext*) {}); - void load(const QString & qmlSourceFile, std::function f = [](QQmlContext*) {}) { + void create(QOpenGLContext* context); + void resize(const QSize& size); + void load(const QUrl& qmlSource, std::function f = [](QQmlContext*) {}); + void load(const QString& qmlSourceFile, std::function f = [](QQmlContext*) {}) { load(QUrl(qmlSourceFile), f); } - void show(const QUrl & url, const QString & name); - void toggle(const QUrl & url, const QString & name); - void setBaseUrl(const QUrl & baseUrl); - void addImportPath(const QString & path); + void show(const QUrl& url, const QString& name); + void toggle(const QUrl& url, const QString& name); + void setBaseUrl(const QUrl& baseUrl); + void addImportPath(const QString& path); QQmlContext * qmlContext(); void pause(); void resume(); bool isPaused() const; - void setProxyWindow(QWindow * window); - QPointF mapWindowToUi(const QPointF & p, QObject * dest); - virtual bool eventFilter(QObject * dest, QEvent * e); + void setProxyWindow(QWindow* window); + QPointF mapWindowToUi(const QPointF& p, QObject* dest); + virtual bool eventFilter(QObject* dest, QEvent* e); void setMouseTranslator(MouseTranslator mt) { _mouseTranslator = mt; } // Messagebox replacement functions - using ButtonCallback = std::function < void(QMessageBox::StandardButton) >; + using ButtonCallback = std::function; static ButtonCallback NO_OP_CALLBACK; - static void messageBox(const QString &title, const QString &text, + static void messageBox(const QString& title, const QString& text, QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, ButtonCallback f); - static void information(const QString &title, const QString &text, + static void information(const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, ButtonCallback callback = NO_OP_CALLBACK); - static void question(const QString &title, const QString &text, + static void question(const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), ButtonCallback callback = [](QMessageBox::StandardButton) {}); - static void warning(const QString &title, const QString &text, + static void warning(const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, ButtonCallback callback = [](QMessageBox::StandardButton) {}); - static void critical(const QString &title, const QString &text, + static void critical(const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, ButtonCallback callback = [](QMessageBox::StandardButton) {}); @@ -121,11 +121,11 @@ signals: void textureUpdated(GLuint texture); private: - QMyQuickRenderControl *_renderControl{ new QMyQuickRenderControl }; - QQuickWindow *_quickWindow{ nullptr }; - QQmlEngine *_qmlEngine{ nullptr }; - QQmlComponent *_qmlComponent{ nullptr }; - QQuickItem * _rootItem{ nullptr }; + QMyQuickRenderControl* _renderControl{ new QMyQuickRenderControl }; + QQuickWindow* _quickWindow{ nullptr }; + QQmlEngine* _qmlEngine{ nullptr }; + QQmlComponent* _qmlComponent{ nullptr }; + QQuickItem* _rootItem{ nullptr }; QTimer _updateTimer; FboCache _fboCache; bool _polish{ true }; From c4d2bd2cdaac29a237fa84398e923db9bb633115 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 19:18:09 -0700 Subject: [PATCH 38/74] More coding standard fixes --- interface/src/Application.h | 4 ++-- interface/src/GLCanvas.cpp | 2 +- interface/src/ui/AddressBarDialog.cpp | 6 +++--- interface/src/ui/AddressBarDialog.h | 4 ++-- interface/src/ui/LoginDialog.cpp | 10 +++++----- interface/src/ui/LoginDialog.h | 2 +- libraries/render-utils/src/FboCache.cpp | 2 +- libraries/render-utils/src/FboCache.h | 2 +- .../render-utils/src/OffscreenQmlDialog.cpp | 2 +- libraries/render-utils/src/OffscreenUi.cpp | 6 ++++-- libraries/shared/src/ThreadHelpers.h | 4 ++-- tests/render-utils/src/main.cpp | 18 ++++++++---------- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index cb54f7dc79..89de18dde5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -171,8 +171,8 @@ public: void touchUpdateEvent(QTouchEvent* event); void wheelEvent(QWheelEvent* event); - void dropEvent(QDropEvent *event); - void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent* event); + void dragEnterEvent(QDragEnterEvent* event); bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index d0c0cb6713..0e25f0f596 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -127,7 +127,7 @@ void GLCanvas::throttleRender() { int updateTime = 0; bool GLCanvas::event(QEvent* event) { switch (event->type()) { - case QEvent::MouseMove: + case QEvent::MouseMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::KeyPress: diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 5ef9b930ac..6b5c92c194 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -17,7 +17,7 @@ QML_DIALOG_DEF(AddressBarDialog) -AddressBarDialog::AddressBarDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { +AddressBarDialog::AddressBarDialog(QQuickItem* parent) : OffscreenQmlDialog(parent) { auto addressManager = DependencyManager::get(); connect(addressManager.data(), &AddressManager::lookupResultIsOffline, this, &AddressBarDialog::displayAddressOfflineMessage); connect(addressManager.data(), &AddressManager::lookupResultIsNotFound, this, &AddressBarDialog::displayAddressNotFoundMessage); @@ -25,10 +25,10 @@ AddressBarDialog::AddressBarDialog(QQuickItem *parent) : OffscreenQmlDialog(pare } void AddressBarDialog::hide() { - ((QQuickItem *)parent())->setEnabled(false); + ((QQuickItem*)parent())->setEnabled(false); } -void AddressBarDialog::loadAddress(const QString & address) { +void AddressBarDialog::loadAddress(const QString& address) { qDebug() << "Called LoadAddress with address " << address; if (!address.isEmpty()) { DependencyManager::get()->handleLookupString(address); diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index b4f4c44e0f..a9035cc915 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -20,14 +20,14 @@ class AddressBarDialog : public OffscreenQmlDialog QML_DIALOG_DECL public: - AddressBarDialog(QQuickItem *parent = 0); + AddressBarDialog(QQuickItem* parent = 0); protected: void displayAddressOfflineMessage(); void displayAddressNotFoundMessage(); void hide(); - Q_INVOKABLE void loadAddress(const QString & address); + Q_INVOKABLE void loadAddress(const QString& address); }; #endif diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 3637d824fb..10541415bf 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -41,7 +41,7 @@ void LoginDialog::toggleAction() { } } -void LoginDialog::handleLoginCompleted(const QUrl& authURL) { +void LoginDialog::handleLoginCompleted(const QUrl&) { hide(); } @@ -49,9 +49,9 @@ void LoginDialog::handleLoginFailed() { setStatusText("Invalid username or password.< / font>"); } -void LoginDialog::setStatusText(const QString &a) { +void LoginDialog::setStatusText(const QString& statusText) { if (a != _statusText) { - _statusText = a; + _statusText = statusText; emit statusTextChanged(); } } @@ -64,12 +64,12 @@ QString LoginDialog::rootUrl() const { return _rootUrl; } -void LoginDialog::login(const QString & username, const QString & password) { +void LoginDialog::login(const QString& username, const QString& password) { qDebug() << "Attempting to login " << username; setStatusText("Authenticating..."); AccountManager::getInstance().requestAccessToken(username, password); } -void LoginDialog::openUrl(const QString & url) { +void LoginDialog::openUrl(const QString& url) { qDebug() << url; } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 7fe44bf543..b4f83bb9ad 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -27,7 +27,7 @@ public: LoginDialog(QQuickItem* parent = 0); - void setStatusText(const QString & a); + void setStatusText(const QString& a); QString statusText() const; QString rootUrl() const; diff --git a/libraries/render-utils/src/FboCache.cpp b/libraries/render-utils/src/FboCache.cpp index fdd29d20d8..2ca3d47bdf 100644 --- a/libraries/render-utils/src/FboCache.cpp +++ b/libraries/render-utils/src/FboCache.cpp @@ -72,7 +72,7 @@ QOpenGLFramebufferObject* FboCache::getReadyFbo() { return result; } -void FboCache::setSize(const QSize & newSize) { +void FboCache::setSize(const QSize& newSize) { if (_size == newSize) { return; } diff --git a/libraries/render-utils/src/FboCache.h b/libraries/render-utils/src/FboCache.h index 975d602278..30278470fd 100644 --- a/libraries/render-utils/src/FboCache.h +++ b/libraries/render-utils/src/FboCache.h @@ -30,7 +30,7 @@ public: // the appropriate OpenGL context is active when doing so. // Important.... textures are sharable resources, but FBOs ARE NOT. - void setSize(const QSize & newSize); + void setSize(const QSize& newSize); QOpenGLFramebufferObject* getReadyFbo(); // These operations are thread safe and require no OpenGL context. They manipulate the diff --git a/libraries/render-utils/src/OffscreenQmlDialog.cpp b/libraries/render-utils/src/OffscreenQmlDialog.cpp index ae0525e17d..98dc68f94b 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.cpp +++ b/libraries/render-utils/src/OffscreenQmlDialog.cpp @@ -14,5 +14,5 @@ OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem* parent) : QQuickItem(parent) { } void OffscreenQmlDialog::hide() { - ((QQuickItem *)parent())->setEnabled(false); + ((QQuickItem*)parent())->setEnabled(false); } diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index 6849837da3..5fb2773d31 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -139,13 +139,15 @@ void OffscreenUi::load(const QUrl& qmlSource, std::function void OffscreenUi::requestUpdate() { _polish = true; - if (!_updateTimer.isActive()) + if (!_updateTimer.isActive()) { _updateTimer.start(); + } } void OffscreenUi::requestRender() { - if (!_updateTimer.isActive()) + if (!_updateTimer.isActive()) { _updateTimer.start(); + } } void OffscreenUi::finishQmlLoad() { diff --git a/libraries/shared/src/ThreadHelpers.h b/libraries/shared/src/ThreadHelpers.h index 8a64691da7..cc0e1ee666 100644 --- a/libraries/shared/src/ThreadHelpers.h +++ b/libraries/shared/src/ThreadHelpers.h @@ -21,9 +21,9 @@ void withLock(L lock, F function) { } template -void withLock(QMutex & lock, F function) { +void withLock(QMutex& lock, F function) { QMutexLocker locker(&lock); function(); } -#endif \ No newline at end of file +#endif diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index eb61fd1f72..7adad34879 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -70,7 +70,7 @@ public: }; -const QString & getQmlDir() { +const QString& getQmlDir() { static QString dir; if (dir.isEmpty()) { QDir path(__FILE__); @@ -98,7 +98,7 @@ protected: void renderQml(); private: - void resizeWindow(const QSize & size) { + void resizeWindow(const QSize& size) { _size = size; DependencyManager::get()->resize(_size); } @@ -126,7 +126,7 @@ public: makeCurrent(); { - QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this); + QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(this); logger->initialize(); // initializes in the current context, i.e. ctx logger->enableMessages(); connect(logger, &QOpenGLDebugLogger::messageLogged, this, [&](const QOpenGLDebugMessage & debugMessage) { @@ -201,12 +201,12 @@ public: protected: - void resizeEvent(QResizeEvent * ev) override { + void resizeEvent(QResizeEvent* ev) override { resizeWindow(ev->size()); } - void keyPressEvent(QKeyEvent *event) { + void keyPressEvent(QKeyEvent* event) { switch (event->key()) { case Qt::Key_L: if (event->modifiers() & Qt::CTRL) { @@ -217,7 +217,7 @@ protected: QWindow::keyPressEvent(event); } - void moveEvent(QMoveEvent *event) { + void moveEvent(QMoveEvent* event) { static qreal oldPixelRatio = 0.0; if (devicePixelRatio() != oldPixelRatio) { oldPixelRatio = devicePixelRatio(); @@ -232,8 +232,8 @@ protected: #define SERIF_FONT_FAMILY "Times New Roman" #endif -static const wchar_t * EXAMPLE_TEXT = L"Hello"; -//static const wchar_t * EXAMPLE_TEXT = L"\xC1y Hello 1.0\ny\xC1 line 2\n\xC1y"; +static const wchar_t* EXAMPLE_TEXT = L"Hello"; +//static const wchar_t* EXAMPLE_TEXT = L"\xC1y Hello 1.0\ny\xC1 line 2\n\xC1y"; static const glm::uvec2 QUAD_OFFSET(10, 10); static const glm::vec3 COLORS[4] = { { 1.0, 1.0, 1.0 }, { 0.5, 1.0, 0.5 }, { @@ -283,7 +283,6 @@ void QTestWindow::renderText() { } void QTestWindow::renderQml() { - glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -297,7 +296,6 @@ void QTestWindow::renderQml() { } glBegin(GL_QUADS); { - glTexCoord2f(0, 0); glVertex2f(-1, -1); glTexCoord2f(0, 1); From 930ec7a6d8ecb8d61566d85d91a7afd3295bb252 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 19:22:10 -0700 Subject: [PATCH 39/74] One more --- tests/render-utils/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 7adad34879..9d7363c241 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -84,7 +84,7 @@ const QString& getQmlDir() { class QTestWindow : public QWindow { Q_OBJECT - QOpenGLContext * _context{ nullptr }; + QOpenGLContext* _context{ nullptr }; QSize _size; TextRenderer* _textRenderer[4]; RateCounter fps; From 732e9723cd0294880776dfd74b371c9db824eecc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 19:24:43 -0700 Subject: [PATCH 40/74] Messed up rename --- interface/src/ui/LoginDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 10541415bf..4df42c0f15 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -50,7 +50,7 @@ void LoginDialog::handleLoginFailed() { } void LoginDialog::setStatusText(const QString& statusText) { - if (a != _statusText) { + if (statusText != _statusText) { _statusText = statusText; emit statusTextChanged(); } From 44efcdf82ad48ee56a72674a377543699bc7b24d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 20:08:49 -0700 Subject: [PATCH 41/74] More coding standard --- libraries/render-utils/src/OffscreenUi.cpp | 56 ++++++++++++---------- libraries/render-utils/src/OffscreenUi.h | 12 ++--- libraries/render-utils/src/RenderUtil.h | 4 +- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index 5fb2773d31..d63f3330e9 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -239,17 +239,17 @@ void OffscreenUi::updateQuick() { emit textureUpdated(fbo->texture()); } -QPointF OffscreenUi::mapWindowToUi(const QPointF& p, QObject* dest) { +QPointF OffscreenUi::mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject) { vec2 sourceSize; - if (dynamic_cast(dest)) { - sourceSize = toGlm(((QWidget*)dest)->size()); - } else if (dynamic_cast(dest)) { - sourceSize = toGlm(((QWindow*)dest)->size()); + if (dynamic_cast(sourceObject)) { + sourceSize = toGlm(((QWidget*)sourceObject)->size()); + } else if (dynamic_cast(sourceObject)) { + sourceSize = toGlm(((QWindow*)sourceObject)->size()); } - vec2 pos = toGlm(p); - pos /= sourceSize; - pos *= vec2(toGlm(_quickWindow->size())); - return QPointF(pos.x, pos.y); + vec2 offscreenPosition = toGlm(sourcePosition); + offscreenPosition /= sourceSize; + offscreenPosition *= vec2(toGlm(_quickWindow->size())); + return QPointF(offscreenPosition.x, offscreenPosition.y); } /////////////////////////////////////////////////////// @@ -257,39 +257,42 @@ QPointF OffscreenUi::mapWindowToUi(const QPointF& p, QObject* dest) { // Event handling customization // -bool OffscreenUi::eventFilter(QObject* dest, QEvent* e) { +bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { // Only intercept events while we're in an active state if (_paused) { return false; } // Don't intercept our own events, or we enter an infinite recursion - if (dest == _quickWindow) { + if (originalDestination == _quickWindow) { return false; } - switch (e->type()) { + switch (event->type()) { case QEvent::Resize: { - QResizeEvent* re = (QResizeEvent*)e; - QGLWidget* widget = dynamic_cast(dest); + QResizeEvent* resizeEvent = (QResizeEvent*)event; + QGLWidget* widget = dynamic_cast(originalDestination); if (widget) { - this->resize(re->size()); + this->resize(resizeEvent->size()); } return false; } case QEvent::KeyPress: case QEvent::KeyRelease: { - e->ignore(); - if (QCoreApplication::sendEvent(_quickWindow, e)) { - return e->isAccepted(); + event->ignore(); + if (QCoreApplication::sendEvent(_quickWindow, event)) { + return event->isAccepted(); } break; } case QEvent::Wheel: { - QWheelEvent* we = (QWheelEvent*)e; - QWheelEvent mappedEvent(mapWindowToUi(we->pos(), dest), we->delta(), we->buttons(), we->modifiers(), we->orientation()); + QWheelEvent* wheelEvent = (QWheelEvent*)event; + QWheelEvent mappedEvent( + mapWindowToUi(wheelEvent->pos(), originalDestination), + wheelEvent->delta(), wheelEvent->buttons(), + wheelEvent->modifiers(), wheelEvent->orientation()); QCoreApplication::sendEvent(_quickWindow, &mappedEvent); return true; } @@ -299,12 +302,15 @@ bool OffscreenUi::eventFilter(QObject* dest, QEvent* e) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { - QMouseEvent* me = (QMouseEvent *)e; - QPointF originalPos = me->localPos(); + QMouseEvent* mouseEvent = (QMouseEvent *)event; + QPointF originalPos = mouseEvent->localPos(); QPointF transformedPos = _mouseTranslator(originalPos); - QMouseEvent mappedEvent(e->type(), mapWindowToUi(transformedPos, dest), me->screenPos(), me->button(), me->buttons(), me->modifiers()); + QMouseEvent mappedEvent(mouseEvent->type(), + mapWindowToUi(transformedPos, originalDestination), + mouseEvent->screenPos(), mouseEvent->button(), + mouseEvent->buttons(), mouseEvent->modifiers()); QCoreApplication::sendEvent(_quickWindow, &mappedEvent); - return QObject::event(e); + return QObject::event(event); } default: @@ -352,7 +358,7 @@ void OffscreenUi::show(const QUrl& url, const QString& name) { void OffscreenUi::toggle(const QUrl& url, const QString& name) { QQuickItem* item = _rootItem->findChild(name); // First load? - if (nullptr == item) { + if (!item) { load(url); return; } diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index 16db24e5ae..d86f99554e 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -67,16 +67,16 @@ public: void toggle(const QUrl& url, const QString& name); void setBaseUrl(const QUrl& baseUrl); void addImportPath(const QString& path); - QQmlContext * qmlContext(); + QQmlContext* qmlContext(); void pause(); void resume(); bool isPaused() const; void setProxyWindow(QWindow* window); - QPointF mapWindowToUi(const QPointF& p, QObject* dest); - virtual bool eventFilter(QObject* dest, QEvent* e); - void setMouseTranslator(MouseTranslator mt) { - _mouseTranslator = mt; + QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); + virtual bool eventFilter(QObject* originalDestination, QEvent* event); + void setMouseTranslator(MouseTranslator mouseTranslator) { + _mouseTranslator = mouseTranslator; } @@ -130,7 +130,7 @@ private: FboCache _fboCache; bool _polish{ true }; bool _paused{ true }; - MouseTranslator _mouseTranslator{ [](const QPointF & p) { return p; } }; + MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p; } }; }; #endif diff --git a/libraries/render-utils/src/RenderUtil.h b/libraries/render-utils/src/RenderUtil.h index 74d6c23791..8c1b1e12e7 100644 --- a/libraries/render-utils/src/RenderUtil.h +++ b/libraries/render-utils/src/RenderUtil.h @@ -37,7 +37,7 @@ void withProjectionIdentity(F f) { } template -void withProjectionMatrix(GLfloat * matrix, F f) { +void withProjectionMatrix(GLfloat* matrix, F f) { withProjectionPush([&] { glLoadMatrixf(matrix); f(); @@ -58,7 +58,7 @@ void withModelviewIdentity(F f) { } template -void withModelviewMatrix(GLfloat * matrix, F f) { +void withModelviewMatrix(GLfloat* matrix, F f) { withModelviewPush([&] { glLoadMatrixf(matrix); f(); From eab4ad9ea98343afeb4bd8a7a171a8aa2957ae91 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 20:16:41 -0700 Subject: [PATCH 42/74] More coding standard stuff --- interface/src/ui/AddressBarDialog.h | 2 +- interface/src/ui/LoginDialog.h | 4 ++-- libraries/render-utils/src/OffscreenQmlDialog.cpp | 2 +- libraries/render-utils/src/OffscreenQmlDialog.h | 2 +- libraries/render-utils/src/OffscreenUi.cpp | 7 ++++++- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index a9035cc915..28056edd30 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -20,7 +20,7 @@ class AddressBarDialog : public OffscreenQmlDialog QML_DIALOG_DECL public: - AddressBarDialog(QQuickItem* parent = 0); + AddressBarDialog(QQuickItem* parent = nullptr); protected: void displayAddressOfflineMessage(); diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index b4f83bb9ad..b6d505943e 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -25,9 +25,9 @@ class LoginDialog : public OffscreenQmlDialog public: static void toggleAction(); - LoginDialog(QQuickItem* parent = 0); + LoginDialog(QQuickItem* parent = nullptr); - void setStatusText(const QString& a); + void setStatusText(const QString& statusText); QString statusText() const; QString rootUrl() const; diff --git a/libraries/render-utils/src/OffscreenQmlDialog.cpp b/libraries/render-utils/src/OffscreenQmlDialog.cpp index 98dc68f94b..d1e060245d 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.cpp +++ b/libraries/render-utils/src/OffscreenQmlDialog.cpp @@ -14,5 +14,5 @@ OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem* parent) : QQuickItem(parent) { } void OffscreenQmlDialog::hide() { - ((QQuickItem*)parent())->setEnabled(false); + static_cast(parent())->setEnabled(false); } diff --git a/libraries/render-utils/src/OffscreenQmlDialog.h b/libraries/render-utils/src/OffscreenQmlDialog.h index bb69b4b63f..eca82261c0 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.h +++ b/libraries/render-utils/src/OffscreenQmlDialog.h @@ -47,7 +47,7 @@ class OffscreenQmlDialog : public QQuickItem { Q_OBJECT public: - OffscreenQmlDialog(QQuickItem* parent = 0); + OffscreenQmlDialog(QQuickItem* parent = nullptr); protected: void hide(); diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index d63f3330e9..d4e1f15b22 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -14,6 +14,11 @@ #include #include +// Time between receiving a request to render the offscreen UI actually triggering +// the render. Could possibly be increased depending on the framerate we expect to +// achieve. +static const int SMALL_INTERVAL = 5; + class OffscreenUiRoot : public QQuickItem { Q_OBJECT public: @@ -76,7 +81,7 @@ void OffscreenUi::create(QOpenGLContext* shareContext) { // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. _updateTimer.setSingleShot(true); - _updateTimer.setInterval(5); + _updateTimer.setInterval(SMALL_INTERVAL); connect(&_updateTimer, &QTimer::timeout, this, &OffscreenUi::updateQuick); // Now hook up the signals. For simplicy we don't differentiate between From de179256d3a15aad8a78b391047b47e52e0e2efa Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Apr 2015 20:19:19 -0700 Subject: [PATCH 43/74] Kill all the whitespace --- libraries/render-utils/src/OffscreenUi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index d4e1f15b22..db93a14b0d 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -275,7 +275,7 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { switch (event->type()) { case QEvent::Resize: { - QResizeEvent* resizeEvent = (QResizeEvent*)event; + QResizeEvent* resizeEvent = static_cast(event); QGLWidget* widget = dynamic_cast(originalDestination); if (widget) { this->resize(resizeEvent->size()); @@ -293,7 +293,7 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { } case QEvent::Wheel: { - QWheelEvent* wheelEvent = (QWheelEvent*)event; + QWheelEvent* wheelEvent = static_cast(event); QWheelEvent mappedEvent( mapWindowToUi(wheelEvent->pos(), originalDestination), wheelEvent->delta(), wheelEvent->buttons(), @@ -307,7 +307,7 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { - QMouseEvent* mouseEvent = (QMouseEvent *)event; + QMouseEvent* mouseEvent = static_cast(event); QPointF originalPos = mouseEvent->localPos(); QPointF transformedPos = _mouseTranslator(originalPos); QMouseEvent mappedEvent(mouseEvent->type(), From 3ebe72f02576bd513406fab5960184d572178f24 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 12:12:42 +0200 Subject: [PATCH 44/74] Fix read macro --- libraries/entities/src/ZoneEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 6439922a5d..82c59d2e71 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -129,7 +129,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay); READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour); READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, _shapeType); - READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, _compoundShapeURL); + READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); return bytesRead; } From 837a0d3ba84e3c8e2b503c84fc5931e73a0fcaca Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 12:13:52 +0200 Subject: [PATCH 45/74] rename collision model in edit.js --- examples/html/entityProperties.html | 10 +++++----- examples/libraries/ToolTip.js | 2 +- examples/libraries/entityPropertyDialogBox.js | 4 ++-- libraries/entities/src/ModelEntityItem.cpp | 4 ++-- libraries/entities/src/ModelEntityItem.h | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index dd5bced393..c11f6d94d5 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -162,7 +162,7 @@ var elModelSections = document.querySelectorAll(".model-section"); var elModelURL = document.getElementById("property-model-url"); - var elCollisionModelURL = document.getElementById("property-collision-model-url"); + var elCompoundShapeURL = document.getElementById("property-compound-shape-url"); var elModelAnimationURL = document.getElementById("property-model-animation-url"); var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); @@ -306,7 +306,7 @@ } elModelURL.value = properties.modelURL; - elCollisionModelURL.value = properties.collisionModelURL; + elCompoundShapeURL.value = properties.compoundShapeURL; elModelAnimationURL.value = properties.animationURL; elModelAnimationPlaying.checked = properties.animationIsPlaying; elModelAnimationFPS.value = properties.animationFPS; @@ -444,7 +444,7 @@ elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff')); elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); - elCollisionModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionModelURL')); + elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL')); elModelAnimationURL.addEventListener('change', createEmitTextPropertyUpdateFunction('animationURL')); elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying')); elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS')); @@ -712,9 +712,9 @@
-
Collision Model URL
+
Compound Shape URL
- +
diff --git a/examples/libraries/ToolTip.js b/examples/libraries/ToolTip.js index 680f617436..2b0e125d4b 100644 --- a/examples/libraries/ToolTip.js +++ b/examples/libraries/ToolTip.js @@ -53,7 +53,7 @@ function Tooltip() { text += "ID: " + properties.id + "\n" if (properties.type == "Model") { text += "Model URL: " + properties.modelURL + "\n" - text += "Collision Model URL: " + properties.collisionModelURL + "\n" + text += "Compound Shape URL: " + properties.compoundShapeURL + "\n" text += "Animation URL: " + properties.animationURL + "\n" text += "Animation is playing: " + properties.animationIsPlaying + "\n" if (properties.sittingPoints && properties.sittingPoints.length > 0) { diff --git a/examples/libraries/entityPropertyDialogBox.js b/examples/libraries/entityPropertyDialogBox.js index d8a91da8f9..255cec4265 100644 --- a/examples/libraries/entityPropertyDialogBox.js +++ b/examples/libraries/entityPropertyDialogBox.js @@ -52,7 +52,7 @@ EntityPropertyDialogBox = (function () { if (properties.type == "Model") { array.push({ label: "Model URL:", value: properties.modelURL }); index++; - array.push({ label: "Collision Model URL:", value: properties.collisionModelURL }); + array.push({ label: "Compound Shape URL:", value: properties.compoundShapeURL }); index++; array.push({ label: "Animation URL:", value: properties.animationURL }); index++; @@ -284,7 +284,7 @@ EntityPropertyDialogBox = (function () { properties.locked = array[index++].value; if (properties.type == "Model") { properties.modelURL = array[index++].value; - properties.collisionModelURL = array[index++].value; + properties.compoundShapeURL = array[index++].value; properties.animationURL = array[index++].value; var newAnimationIsPlaying = array[index++].value; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 7616924f4a..1abb48abcd 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -21,7 +21,7 @@ #include "ModelEntityItem.h" const QString ModelEntityItem::DEFAULT_MODEL_URL = QString(""); -const QString ModelEntityItem::DEFAULT_COLLISION_MODEL_URL = QString(""); +const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString(""); const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString(""); const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; const bool ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; @@ -272,7 +272,7 @@ void ModelEntityItem::debugDump() const { qCDebug(entities) << " position:" << getPosition(); qCDebug(entities) << " dimensions:" << getDimensions(); qCDebug(entities) << " model URL:" << getModelURL(); - qCDebug(entities) << " collision model URL:" << getCompoundShapeURL(); + qCDebug(entities) << " compound shape URL:" << getCompoundShapeURL(); } void ModelEntityItem::updateShapeType(ShapeType type) { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 46fce6ff5f..6fe2adc928 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -62,7 +62,7 @@ public: static const QString DEFAULT_MODEL_URL; const QString& getModelURL() const { return _modelURL; } - static const QString DEFAULT_COLLISION_MODEL_URL; + static const QString DEFAULT_COMPOUND_SHAPE_URL; const QString& getCompoundShapeURL() const { return _compoundShapeURL; } bool hasAnimation() const { return !_animationURL.isEmpty(); } From 01f4f349114756ded818c95a91b4a30ebfd22270 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 13:04:59 +0200 Subject: [PATCH 46/74] Centralize contains standard cases --- libraries/entities/src/EntityItem.cpp | 19 +++++++++++++++++++ libraries/entities/src/EntityItem.h | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 8 -------- .../entities/src/ParticleEffectEntityItem.h | 2 -- libraries/entities/src/SphereEntityItem.cpp | 8 -------- libraries/entities/src/SphereEntityItem.h | 2 -- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0e6976c730..ea012922b8 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1060,6 +1060,25 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(_dimensions); } +bool EntityItem::contains(const glm::vec3 &point) const { + switch (getShapeType()) { + case SHAPE_TYPE_BOX: { + // Transform point to be in a space where the box is a 1m cube centered on the origin. + glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); + return AABox(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f).contains(transformedPoint); + } + case SHAPE_TYPE_SPHERE: + case SHAPE_TYPE_ELLIPSOID: { + // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. + glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); + // Return whether said point is inside the sphere. + return glm::length(transformedPoint) <= 1.0f; + } + default: + return getAABox().contains(point); + } +} + void EntityItem::computeShapeInfo(ShapeInfo& info) { info.setParams(getShapeType(), 0.5f * getDimensions()); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 4e1578510d..49b853d8dd 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -253,7 +253,7 @@ public: // TODO: get rid of users of getRadius()... float getRadius() const; - virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } + virtual bool contains(const glm::vec3& point) const; virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f12259d057..45312f465b 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -236,14 +236,6 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius()); } -bool ParticleEffectEntityItem::contains(const glm::vec3& point) const { - // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. - glm::vec3 transformedPoint = (point - getPosition()) / (getDimensions() / 2.0f); - - // Return whether said point is inside the sphere. - return glm::length(transformedPoint) <= 1.0f; -} - bool ParticleEffectEntityItem::isAnimatingSomething() const { return getAnimationIsPlaying() && getAnimationFPS() != 0.0f; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index b563274fa1..b00eb94685 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -77,8 +77,6 @@ public: _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; } - - virtual bool contains(const glm::vec3& point) const; void updateShapeType(ShapeType type); virtual ShapeType getShapeType() const { return _shapeType; } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 4a756be618..132ad43336 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -92,14 +92,6 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } -bool SphereEntityItem::contains(const glm::vec3& point) const { - // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. - glm::vec3 transformedPoint = (point - getPosition()) / (getDimensions() / 2.0f); - - // Return whether said point is inside the sphere. - return glm::length(transformedPoint) <= 1.0f; -} - bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 98450121c5..b6516b714f 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -50,8 +50,6 @@ public: _color[BLUE_INDEX] = value.blue; } - virtual bool contains(const glm::vec3& point) const; - virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; } virtual bool supportsDetailedRayIntersection() const { return true; } From f117941c8d6042ed7f77d61ddb8ed8c109113edc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 13:25:14 +0200 Subject: [PATCH 47/74] Macro fixing --- libraries/entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 6ef6877bb1..7d5a40f6fd 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -907,7 +907,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_DAY, quint16, setStageDay); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); } READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID); diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 82c59d2e71..5447c24baf 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -128,7 +128,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _stageAltitude); READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay); READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour); - READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, _shapeType); + READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL); return bytesRead; From fb4d1d35574ce085e989f80ef18f051cebdc3c30 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 14:01:22 +0200 Subject: [PATCH 48/74] Fix compoundShapeURL reseting shapeType --- libraries/entities/src/ZoneEntityItem.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 5447c24baf..64d0b2fe31 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -58,6 +58,8 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte _stageAltitude = DEFAULT_STAGE_ALTITUDE; _stageDay = DEFAULT_STAGE_DAY; _stageHour = DEFAULT_STAGE_HOUR; + _shapeType = DEFAULT_SHAPE_TYPE; + _compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL; setProperties(properties); } @@ -207,5 +209,9 @@ ShapeType ZoneEntityItem::getShapeType() const { void ZoneEntityItem::setCompoundShapeURL(const QString& url) { _compoundShapeURL = url; - _shapeType = _compoundShapeURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND; + if (!_compoundShapeURL.isEmpty()) { + updateShapeType(SHAPE_TYPE_COMPOUND); + } else if (_shapeType == SHAPE_TYPE_COMPOUND) { + _shapeType = DEFAULT_SHAPE_TYPE; + } } From 15482d6a573011f0bd6192b92710a21132d143b8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 15:21:51 +0200 Subject: [PATCH 49/74] Don't compute shape for zones --- libraries/entities/src/ZoneEntityItem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index bc44d70737..ad64557103 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -92,6 +92,7 @@ public: static bool getZonesArePickable() { return _zonesArePickable; } static void setZonesArePickable(bool value) { _zonesArePickable = value; } + virtual bool isReadyToComputeShape() { return false; } void updateShapeType(ShapeType type) { _shapeType = type; } virtual ShapeType getShapeType() const; From c91ca146d5f191c99d896ef5ed6c198432f8fe36 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 15:22:58 +0200 Subject: [PATCH 50/74] Add different shapes to zone example --- examples/example/entities/zoneEntityExample.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/example/entities/zoneEntityExample.js b/examples/example/entities/zoneEntityExample.js index 84d87d1370..660ff2945d 100644 --- a/examples/example/entities/zoneEntityExample.js +++ b/examples/example/entities/zoneEntityExample.js @@ -22,7 +22,8 @@ var zoneEntityA = Entities.addEntity({ dimensions: { x: 10, y: 10, z: 10 }, keyLightColor: { red: 255, green: 0, blue: 0 }, stageSunModelEnabled: false, - keyLightDirection: { x: 0, y: -1.0, z: 0 } + keyLightDirection: { x: 0, y: -1.0, z: 0 }, + shapeType: "sphere" }); print("zoneEntityA:" + zoneEntityA); @@ -51,7 +52,9 @@ var zoneEntityC = Entities.addEntity({ keyLightColor: { red: 0, green: 0, blue: 255 }, keyLightIntensity: 0.75, keyLightDirection: { x: 0, y: 0, z: -1 }, - stageSunModelEnabled: false + stageSunModelEnabled: false, + shapeType: "compound", + compoundShapeURL: "http://headache.hungry.com/~seth/hifi/cube.fbx" }); print("zoneEntityC:" + zoneEntityC); From 3a0b5f9d22d2fe060e1185a6ced6bb89b8f830a8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 15:34:03 +0200 Subject: [PATCH 51/74] Register RenderableZoneEntityItem in EntityTreeRenderer --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 3 ++- libraries/entities-renderer/src/RenderableZoneEntityItem.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index d5d79f8bad..751fda2abe 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -34,8 +34,8 @@ #include "RenderableParticleEffectEntityItem.h" #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" +#include "RenderableZoneEntityItem.h" #include "EntitiesRendererLogging.h" -#include "ZoneEntityItem.h" EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, AbstractScriptingServicesInterface* scriptingServices) : @@ -57,6 +57,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory) _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 1c80b1f317..27232d7dda 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -40,6 +40,10 @@ int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch } bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { + if (getShapeType() != SHAPE_TYPE_COMPOUND) { + return EntityItem::contains(point); + } + if (EntityItem::contains(point) && _compoundShapeModel) { const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry(); From 6be09109661830e2594794ae280f6237c1e7d580 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 15:58:18 +0200 Subject: [PATCH 52/74] Fix contain for collision hulls --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 3 ++- libraries/entities-renderer/src/RenderableZoneEntityItem.cpp | 5 +++-- libraries/shared/src/GLMHelpers.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3f8899f6bd..8acd3b796b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -419,8 +419,9 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const { if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); + glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - return collisionGeometry.convexHullContains(point); + return collisionGeometry.convexHullContains(transformedPoint); } return false; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 27232d7dda..472d14093e 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -44,10 +44,11 @@ bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { return EntityItem::contains(point); } - if (EntityItem::contains(point) && _compoundShapeModel) { + if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) { const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry(); + glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - return geometry.convexHullContains(point); + return geometry.convexHullContains(transformedPoint); } return false; diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index aed73c1989..5d1b70275c 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -207,7 +207,7 @@ bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, gl glm::vec3 v1 = p0 - p1, v2 = p2 - p1; // Non-collinear vectors contained in the plane glm::vec3 n = glm::cross(v1, v2); // Plane's normal vector, pointing out of the triangle float d = -glm::dot(n, p0); // Compute plane's equation constant - return (glm::dot(n, point) + d) <= 0; + return (glm::dot(n, point) + d) >= 0; } glm::vec3 extractTranslation(const glm::mat4& matrix) { From 99fd590a909e1fa3e93abcbf70105f3b22d2d438 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 16:05:06 +0200 Subject: [PATCH 53/74] Update compound shape geometry when async get --- libraries/entities-renderer/src/RenderableZoneEntityItem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 472d14093e..905ac5cfde 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -43,6 +43,9 @@ bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { if (getShapeType() != SHAPE_TYPE_COMPOUND) { return EntityItem::contains(point); } + if (!_compoundShapeModel && hasCompoundShapeURL()) { + const_cast(this)->_compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); + } if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) { const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry(); From bda72025af1ea7dd49a5bfe71a8894f3a5e1662e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 16:40:40 +0200 Subject: [PATCH 54/74] Check mesh extend before going through triangles --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/fbx/src/FBXReader.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ea012922b8..7c47dadd2f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1060,7 +1060,7 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(_dimensions); } -bool EntityItem::contains(const glm::vec3 &point) const { +bool EntityItem::contains(const glm::vec3& point) const { switch (getShapeType()) { case SHAPE_TYPE_BOX: { // Transform point to be in a space where the box is a 1m cube centered on the origin. diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 95cd99852f..1c89ee4067 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -127,6 +127,10 @@ Extents FBXGeometry::getUnscaledMeshExtents() const { // TODO: Move to model::Mesh when Sam's ready bool FBXGeometry::convexHullContains(const glm::vec3& point) const { + if (!getUnscaledMeshExtents().containsPoint(point)) { + return false; + } + auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { // Check whether the point is "behind" all the primitives. for (unsigned int j = 0; j < indices.size(); j += primitiveSize) { From f494f86ee5aaece234e3cde75017038bc077c2d1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 17:48:29 +0200 Subject: [PATCH 55/74] Handle registration point in transforms --- .../src/RenderableModelEntityItem.cpp | 4 +- .../src/RenderableZoneEntityItem.cpp | 5 +-- libraries/entities/src/EntityItem.cpp | 39 +++++++++++++------ libraries/entities/src/EntityItem.h | 5 +++ libraries/entities/src/SphereEntityItem.cpp | 8 +--- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8acd3b796b..8ca6562505 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -419,9 +419,7 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const { if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); - glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - - return collisionGeometry.convexHullContains(transformedPoint); + return collisionGeometry.convexHullContains(worldToEntity(point)); } return false; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 905ac5cfde..e4c56dc419 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -49,9 +49,8 @@ bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) { const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry(); - glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - - return geometry.convexHullContains(transformedPoint); + glm::vec3 meshDimensions = geometry.getUnscaledMeshExtents().maximum - geometry.getUnscaledMeshExtents().minimum; + return geometry.convexHullContains(worldToEntity(point) * meshDimensions); } return false; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 7c47dadd2f..2f4e8c87d7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include @@ -843,7 +845,27 @@ bool EntityItem::isMoving() const { return hasVelocity() || hasAngularVelocity(); } -bool EntityItem::lifetimeHasExpired() const { +glm::mat4 EntityItem::getEntityToWorldMatrix() const { + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); + return translation * rotation * scale * registration; +} + +glm::mat4 EntityItem::getWorldToEntityMatrix() const { + return glm::inverse(getEntityToWorldMatrix()); +} + +glm::vec3 EntityItem::entityToWorld(const glm::vec3 point) const { + return glm::vec3(getEntityToWorldMatrix() * glm::vec4(point, 1.0f)); +} + +glm::vec3 EntityItem::worldToEntity(const glm::vec3 point) const { + return glm::vec3(getWorldToEntityMatrix() * glm::vec4(point, 1.0f)); +} + +bool EntityItem::lifetimeHasExpired() const { return isMortal() && (getAge() > getLifetime()); } @@ -1062,18 +1084,11 @@ float EntityItem::getRadius() const { bool EntityItem::contains(const glm::vec3& point) const { switch (getShapeType()) { - case SHAPE_TYPE_BOX: { - // Transform point to be in a space where the box is a 1m cube centered on the origin. - glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - return AABox(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f).contains(transformedPoint); - } + case SHAPE_TYPE_BOX: + return AABox(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f).contains(worldToEntity(point)); case SHAPE_TYPE_SPHERE: - case SHAPE_TYPE_ELLIPSOID: { - // Transform point to be in a space where the elipsoide is a perfect sphere centered on the origin. - glm::vec3 transformedPoint = (glm::inverse(getRotation()) * (point - getPosition())) / (getDimensions() / 2.0f); - // Return whether said point is inside the sphere. - return glm::length(transformedPoint) <= 1.0f; - } + case SHAPE_TYPE_ELLIPSOID: + return glm::length(worldToEntity(point)) <= 0.5f; default: return getAABox().contains(point); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index facc5c333f..0ebcd06a77 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -297,6 +297,11 @@ public: static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; } static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; } + glm::mat4 getEntityToWorldMatrix() const; + glm::mat4 getWorldToEntityMatrix() const; + glm::vec3 worldToEntity(const glm::vec3 point) const; + glm::vec3 entityToWorld(const glm::vec3 point) const; + protected: static bool _sendPhysicsUpdates; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 132ad43336..d17e49cb59 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -96,11 +96,7 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 translation = glm::translate(getPosition()); - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 scale = glm::scale(getDimensions()); - glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint()); - glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; + glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::normalize(glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f))); @@ -112,7 +108,7 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons glm::vec3 entityFrameHitAt = entityFrameOrigin + (entityFrameDirection * localDistance); // then translate back to work coordinates glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); - distance = glm::distance(origin,hitAt); + distance = glm::distance(origin, hitAt); return true; } return false; From 51d99da29f2524b4a8c94a8a648c3ee549f431ba Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 17:50:26 +0200 Subject: [PATCH 56/74] Magic number --- libraries/entities/src/EntityItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2f4e8c87d7..445158af35 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1088,7 +1088,8 @@ bool EntityItem::contains(const glm::vec3& point) const { return AABox(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f).contains(worldToEntity(point)); case SHAPE_TYPE_SPHERE: case SHAPE_TYPE_ELLIPSOID: - return glm::length(worldToEntity(point)) <= 0.5f; + static const float UNIT_SPHERE_RADIUS = 1.0f / 2.0f; + return glm::length(worldToEntity(point)) <= UNIT_SPHERE_RADIUS; default: return getAABox().contains(point); } From 5654e3abed40e3e6839c33eb444ed10b244411e6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Apr 2015 13:23:00 -0700 Subject: [PATCH 57/74] Add zone overlay manager --- examples/edit.js | 6 ++++++ examples/libraries/lightOverlayManager.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index 480b87d416..091de29374 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -13,6 +13,8 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +Script.include(["libraries/overlays.js"]); + Script.include([ "libraries/stringHelpers.js", "libraries/dataviewHelpers.js", @@ -28,6 +30,7 @@ Script.include([ "libraries/gridTool.js", "libraries/entityList.js", "libraries/lightOverlayManager.js", + "libraries/zoneOverlayManager.js", ]); var selectionDisplay = SelectionDisplay; @@ -35,6 +38,8 @@ var selectionManager = SelectionManager; var entityPropertyDialogBox = EntityPropertyDialogBox; var lightOverlayManager = new LightOverlayManager(); +var zoneOverlayManager = new ZoneOverlayManager(); +zoneOverlayManager.setVisible(true); var cameraManager = new CameraManager(); @@ -47,6 +52,7 @@ var entityListTool = EntityListTool(); selectionManager.addEventListener(function() { selectionDisplay.updateHandles(); lightOverlayManager.updatePositions(); + zoneOverlayManager.updatePositions(); }); var windowDimensions = Controller.getViewportDimensions(); diff --git a/examples/libraries/lightOverlayManager.js b/examples/libraries/lightOverlayManager.js index 8032d77c49..a140461a27 100644 --- a/examples/libraries/lightOverlayManager.js +++ b/examples/libraries/lightOverlayManager.js @@ -122,7 +122,7 @@ LightOverlayManager = function() { Entities.clearingEntities.connect(clearEntities); // Add existing entities - var ids = Entities.findEntities(MyAvatar.position, 100); + var ids = Entities.findEntities(MyAvatar.position, 64000); for (var i = 0; i < ids.length; i++) { addEntity(ids[i]); } From af46ece9af95a238171662a47da3e16f4a2aa99d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:33:10 -0700 Subject: [PATCH 58/74] Remove overlays.js include --- examples/edit.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 091de29374..a15870f84e 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -13,8 +13,6 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -Script.include(["libraries/overlays.js"]); - Script.include([ "libraries/stringHelpers.js", "libraries/dataviewHelpers.js", From ab261f44439651bee510c5ffc9baa7a3cf955e02 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:33:33 -0700 Subject: [PATCH 59/74] Update zone overlay to only be visible when edit is on --- examples/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index a15870f84e..d745b95f33 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -37,7 +37,6 @@ var entityPropertyDialogBox = EntityPropertyDialogBox; var lightOverlayManager = new LightOverlayManager(); var zoneOverlayManager = new ZoneOverlayManager(); -zoneOverlayManager.setVisible(true); var cameraManager = new CameraManager(); @@ -245,6 +244,7 @@ var toolBar = (function () { } toolBar.selectTool(activeButton, isActive); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + zoneOverlayManager.setVisible(isActive); }; // Sets visibility of tool buttons, excluding the power button From 6612f9cb61b0c3eb48e3ac357ed36629d5b905f0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:33:58 -0700 Subject: [PATCH 60/74] Fix key light properties in proeprties window --- examples/html/entityProperties.html | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 649b9164ed..348dc00df4 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -187,8 +187,8 @@ var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red"); var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green"); var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue"); - var elZoneKeyLightIntensity = document.getElementById("property-zone-key-color-intensity"); - var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-color-ambient-intensity"); + var elZoneKeyLightIntensity = document.getElementById("property-zone-key-intensity"); + var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-ambient-intensity"); var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); var elZoneKeyLightDirectionZ = document.getElementById("property-zone-key-light-direction-z"); @@ -905,7 +905,7 @@
-
Key Color
+
Key Light Color
R
G
@@ -913,13 +913,19 @@
-
Key Intensity
+
Key Light Intensity
- +
-
Key Direction
+
Key Light Ambient Intensity
+
+ +
+
+
+
Key Light Direction
Pitch
Yaw
From b31f95a002cc52a58b4b1e75440c180df43e1857 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:34:23 -0700 Subject: [PATCH 61/74] Fix cube rendering not working with transparency --- interface/src/ui/overlays/Cube3DOverlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index a9bfbae8dd..60f985b083 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -77,7 +77,7 @@ void Cube3DOverlay::render(RenderArgs* args) { if (_drawOnHUD) { DependencyManager::get()->renderSolidCube(1.0f, glm::vec4(1.0f, 1.0f, 1.0f, alpha)); } else { - DependencyManager::get()->renderSolidCube(1.0f, glm::vec4(1.0f, 1.0f, 1.0f, alpha)); + DependencyManager::get()->renderSolidCube(1.0f, glm::vec4(1.0f, 1.0f, 1.0f, alpha)); } glPopMatrix(); @@ -89,7 +89,7 @@ void Cube3DOverlay::render(RenderArgs* args) { if (_drawOnHUD) { DependencyManager::get()->renderSolidCube(1.0f, cubeColor); } else { - DependencyManager::get()->renderSolidCube(1.0f, cubeColor); + DependencyManager::get()->renderSolidCube(1.0f, cubeColor); } glPopMatrix(); } else { From e0d4a0b1e15d0ba572fdad15eadc3ea19e040c26 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:36:41 -0700 Subject: [PATCH 62/74] Add functionality to turn zone picking off --- libraries/entities/src/EntityScriptingInterface.cpp | 9 +++++++++ libraries/entities/src/EntityScriptingInterface.h | 3 +++ libraries/entities/src/ZoneEntityItem.cpp | 6 ++++++ libraries/entities/src/ZoneEntityItem.h | 6 +++++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 53335beda0..13e6b83393 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -15,6 +15,7 @@ #include "EntityTree.h" #include "LightEntityItem.h" #include "ModelEntityItem.h" +#include "ZoneEntityItem.h" EntityScriptingInterface::EntityScriptingInterface() : @@ -315,6 +316,14 @@ bool EntityScriptingInterface::getLightsArePickable() const { return LightEntityItem::getLightsArePickable(); } +void EntityScriptingInterface::setZonesArePickable(bool value) { + ZoneEntityItem::setZonesArePickable(value); +} + +bool EntityScriptingInterface::getZonesArePickable() const { + return ZoneEntityItem::getZonesArePickable(); +} + void EntityScriptingInterface::setSendPhysicsUpdates(bool value) { EntityItem::setSendPhysicsUpdates(value); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 075f5a712b..151036e926 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -111,6 +111,9 @@ public slots: Q_INVOKABLE void setLightsArePickable(bool value); Q_INVOKABLE bool getLightsArePickable() const; + Q_INVOKABLE void setZonesArePickable(bool value); + Q_INVOKABLE bool getZonesArePickable() const; + Q_INVOKABLE void setSendPhysicsUpdates(bool value); Q_INVOKABLE bool getSendPhysicsUpdates() const; diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index e0fe238c57..60a61e4e89 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -185,3 +185,9 @@ void ZoneEntityItem::debugDump() const { qCDebug(entities) << " _stageHour:" << _stageHour; } +bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject, bool precisionPicking) const { + + return _zonesArePickable; +} diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 8f1b15d174..bc1d77ab65 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -91,7 +91,11 @@ public: static bool getZonesArePickable() { return _zonesArePickable; } static void setZonesArePickable(bool value) { _zonesArePickable = value; } - + + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject, bool precisionPicking) const; virtual void debugDump() const; From 4a99c21e7bf5d6a2ed563590cedf035411fd8542 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:36:53 -0700 Subject: [PATCH 63/74] Add zoneOverlayManager.js --- examples/libraries/zoneOverlayManager.js | 169 +++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 examples/libraries/zoneOverlayManager.js diff --git a/examples/libraries/zoneOverlayManager.js b/examples/libraries/zoneOverlayManager.js new file mode 100644 index 0000000000..603caf44c7 --- /dev/null +++ b/examples/libraries/zoneOverlayManager.js @@ -0,0 +1,169 @@ +ZoneOverlayManager = function(isEntityFunc, entityAddedFunc, entityRemovedFunc, entityMovedFunc) { + var self = this; + + var visible = false; + + // List of all created overlays + var allOverlays = []; + + // List of overlays not currently being used + var unusedOverlays = []; + + // Map from EntityItemID.id to overlay id + var entityOverlays = {}; + + // Map from EntityItemID.id to EntityItemID object + var entityIDs = {}; + + this.updatePositions = function(ids) { + for (var id in entityIDs) { + var entityID = entityIDs[id]; + var properties = Entities.getEntityProperties(entityID); + Overlays.editOverlay(entityOverlays[entityID.id].solid, { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + }); + Overlays.editOverlay(entityOverlays[entityID.id].outline, { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + visible: true, + }); + } + }; + + this.findRayIntersection = function(pickRay) { + return false; + + var result = Overlays.findRayIntersection(pickRay); + var found = false; + + if (result.intersects) { + for (var id in entityOverlays) { + if (result.overlayID == entityOverlays[id]) { + result.entityID = entityIDs[id]; + found = true; + break; + } + } + + if (!found) { + result.intersects = false; + } + } + + return result; + }; + + this.setVisible = function(isVisible) { + if (visible != isVisible) { + visible = isVisible; + for (var id in entityOverlays) { + Overlays.editOverlay(entityOverlays[id].solid, { visible: visible }); + Overlays.editOverlay(entityOverlays[id].outline, { visible: visible }); + } + } + }; + + // Allocate or get an unused overlay + function getOverlay() { + if (unusedOverlays.length == 0) { + var overlay = Overlays.addOverlay("cube", { + }); + allOverlays.push(overlay); + } else { + var overlay = unusedOverlays.pop(); + }; + return overlay; + } + + function releaseOverlay(overlay) { + unusedOverlays.push(overlay); + Overlays.editOverlay(overlay, { visible: false }); + } + + function addEntity(entityID) { + var properties = Entities.getEntityProperties(entityID); + if (properties.type == "Zone" && !(entityID.id in entityOverlays)) { + var overlaySolid = getOverlay(); + var overlayOutline = getOverlay(); + + entityOverlays[entityID.id] = { + solid: overlaySolid, + outline: overlayOutline, + } + entityIDs[entityID.id] = entityID; + + var color = { + red: Math.round(Math.random() * 255), + green: Math.round(Math.random() * 255), + blue: Math.round(Math.random() * 255) + }; + Overlays.editOverlay(overlaySolid, { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + visible: visible, + solid: true, + alpha: 0.1, + color: color, + ignoreRayIntersection: true, + }); + Overlays.editOverlay(overlayOutline, { + position: properties.position, + rotation: properties.rotation, + dimensions: properties.dimensions, + visible: visible, + solid: false, + dashed: false, + lineWidth: 2.0, + alpha: 1.0, + color: color, + ignoreRayIntersection: true, + }); + } + } + + function deleteEntity(entityID) { + if (entityID.id in entityOverlays) { + releaseOverlay(entityOverlays[entityID.id].outline); + releaseOverlay(entityOverlays[entityID.id].solid); + delete entityOverlays[entityID.id]; + } + } + + function changeEntityID(oldEntityID, newEntityID) { + entityOverlays[newEntityID.id] = entityOverlays[oldEntityID.id]; + entityIDs[newEntityID.id] = newEntityID; + + delete entityOverlays[oldEntityID.id]; + delete entityIDs[oldEntityID.id]; + } + + function clearEntities() { + for (var id in entityOverlays) { + releaseOverlay(entityOverlays[id].outline); + releaseOverlay(entityOverlays[id].solid); + } + entityOverlays = {}; + entityIDs = {}; + } + + Entities.addingEntity.connect(addEntity); + Entities.changingEntityID.connect(changeEntityID); + Entities.deletingEntity.connect(deleteEntity); + Entities.clearingEntities.connect(clearEntities); + + // Add existing entities + var ids = Entities.findEntities(MyAvatar.position, 64000); + for (var i = 0; i < ids.length; i++) { + addEntity(ids[i]); + } + + Script.scriptEnding.connect(function() { + for (var i = 0; i < allOverlays.length; i++) { + Overlays.deleteOverlay(allOverlays[i]); + } + }); +}; From d45e935b93a7c254da94ed9da995a85e89d676d0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:52:01 -0700 Subject: [PATCH 64/74] Add show zone overlay option to menu --- examples/edit.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index d745b95f33..8e7ccbc3c8 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -80,11 +80,13 @@ var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode"; +var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Edit Mode"; var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode"; +var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain." @@ -244,7 +246,7 @@ var toolBar = (function () { } toolBar.selectTool(activeButton, isActive); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); - zoneOverlayManager.setVisible(isActive); + zoneOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); }; // Sets visibility of tool buttons, excluding the power button @@ -805,6 +807,8 @@ function setupModelMenus() { isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS, isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true" }); + Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, + isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true" }); Entities.setLightsArePickable(false); } @@ -833,12 +837,14 @@ function cleanupModelMenus() { Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE); + Menu.removeMenuItem("View", MENU_SHOW_ZONES_IN_EDIT_MODE); } Script.scriptEnding.connect(function() { Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); progressDialog.cleanup(); toolBar.cleanup(); @@ -971,6 +977,8 @@ function handeMenuEvent(menuItem) { selectAllEtitiesInCurrentSelectionBox(true); } else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + } else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) { + zoneOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); } tooltip.show(false); } From 30b9e16c1a0b1cba9d7618e2297243fc041c9625 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 09:52:21 -0700 Subject: [PATCH 65/74] Remove unused findRayIntersection from zoneOverlayManager --- examples/libraries/zoneOverlayManager.js | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/examples/libraries/zoneOverlayManager.js b/examples/libraries/zoneOverlayManager.js index 603caf44c7..9898b888fa 100644 --- a/examples/libraries/zoneOverlayManager.js +++ b/examples/libraries/zoneOverlayManager.js @@ -28,34 +28,10 @@ ZoneOverlayManager = function(isEntityFunc, entityAddedFunc, entityRemovedFunc, position: properties.position, rotation: properties.rotation, dimensions: properties.dimensions, - visible: true, }); } }; - this.findRayIntersection = function(pickRay) { - return false; - - var result = Overlays.findRayIntersection(pickRay); - var found = false; - - if (result.intersects) { - for (var id in entityOverlays) { - if (result.overlayID == entityOverlays[id]) { - result.entityID = entityIDs[id]; - found = true; - break; - } - } - - if (!found) { - result.intersects = false; - } - } - - return result; - }; - this.setVisible = function(isVisible) { if (visible != isVisible) { visible = isVisible; From 83490051d9f47315e32d0768956ad43850a0d922 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 18:55:20 +0200 Subject: [PATCH 66/74] Move shape related contains() to ShapeInfo --- .../src/EntityTreeRenderer.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderableZoneEntityItem.cpp | 4 +- .../src/RenderableZoneEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 17 +++---- libraries/entities/src/EntityItem.h | 2 +- libraries/shared/src/ShapeInfo.cpp | 48 +++++++++++++++++++ libraries/shared/src/ShapeInfo.h | 4 ++ 9 files changed, 66 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index dde13552f3..af3e71ae58 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -324,7 +324,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { // create a list of entities that actually contain the avatar's position foreach(const EntityItem* entity, foundEntities) { - if (entity->contains(avatarPosition)) { + if (const_cast(entity)->contains(avatarPosition)) { entitiesContainingAvatar << entity->getEntityItemID(); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8ca6562505..40053cae48 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -415,7 +415,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } -bool RenderableModelEntityItem::contains(const glm::vec3& point) const { +bool RenderableModelEntityItem::contains(const glm::vec3& point) { if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 43f18af0db..f718c82936 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -57,7 +57,7 @@ public: bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); - virtual bool contains(const glm::vec3& point) const; + virtual bool contains(const glm::vec3& point); private: void remapTextures(); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index e4c56dc419..4f198cff2e 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -39,12 +39,12 @@ int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch return bytesRead; } -bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { +bool RenderableZoneEntityItem::contains(const glm::vec3& point) { if (getShapeType() != SHAPE_TYPE_COMPOUND) { return EntityItem::contains(point); } if (!_compoundShapeModel && hasCompoundShapeURL()) { - const_cast(this)->_compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); + _compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); } if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 8d8d8b4b3f..0b49b39055 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -29,7 +29,7 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - virtual bool contains(const glm::vec3& point) const; + virtual bool contains(const glm::vec3& point); private: diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 445158af35..1dbd9fe91f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1082,16 +1082,13 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(_dimensions); } -bool EntityItem::contains(const glm::vec3& point) const { - switch (getShapeType()) { - case SHAPE_TYPE_BOX: - return AABox(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f).contains(worldToEntity(point)); - case SHAPE_TYPE_SPHERE: - case SHAPE_TYPE_ELLIPSOID: - static const float UNIT_SPHERE_RADIUS = 1.0f / 2.0f; - return glm::length(worldToEntity(point)) <= UNIT_SPHERE_RADIUS; - default: - return getAABox().contains(point); +bool EntityItem::contains(const glm::vec3& point) { + if (getShapeType() == SHAPE_TYPE_COMPOUND) { + return getAABox().contains(point); + } else { + ShapeInfo info; + info.setParams(getShapeType(), glm::vec3(0.5f)); + return info.contains(worldToEntity(point)); } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 0ebcd06a77..1150e11a8a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -253,7 +253,7 @@ public: // TODO: get rid of users of getRadius()... float getRadius() const; - virtual bool contains(const glm::vec3& point) const; + virtual bool contains(const glm::vec3& point); virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 544df35b86..2c88685a90 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -124,6 +124,54 @@ float ShapeInfo::computeVolume() const { return volume; } +bool ShapeInfo::contains(const glm::vec3& point) const { + switch(_type) { + case SHAPE_TYPE_SPHERE: + return glm::length(point) <= _halfExtents.x; + case SHAPE_TYPE_ELLIPSOID: { + glm::vec3 scaledPoint = glm::abs(point) / _halfExtents; + return glm::length(scaledPoint) <= 1.0f; + } + case SHAPE_TYPE_CYLINDER_X: + return glm::length(glm::vec2(point.y, point.z)) <= _halfExtents.z; + case SHAPE_TYPE_CYLINDER_Y: + return glm::length(glm::vec2(point.x, point.z)) <= _halfExtents.x; + case SHAPE_TYPE_CYLINDER_Z: + return glm::length(glm::vec2(point.x, point.y)) <= _halfExtents.y; + case SHAPE_TYPE_CAPSULE_X: { + if (glm::abs(point.x) <= _halfExtents.x) { + return glm::length(glm::vec2(point.y, point.z)) <= _halfExtents.z; + } else { + glm::vec3 absPoint = glm::abs(point) - _halfExtents.x; + return glm::length(absPoint) <= _halfExtents.z; + } + } + case SHAPE_TYPE_CAPSULE_Y: { + if (glm::abs(point.y) <= _halfExtents.y) { + return glm::length(glm::vec2(point.x, point.z)) <= _halfExtents.x; + } else { + glm::vec3 absPoint = glm::abs(point) - _halfExtents.y; + return glm::length(absPoint) <= _halfExtents.x; + } + } + case SHAPE_TYPE_CAPSULE_Z: { + if (glm::abs(point.z) <= _halfExtents.z) { + return glm::length(glm::vec2(point.x, point.y)) <= _halfExtents.y; + } else { + glm::vec3 absPoint = glm::abs(point) - _halfExtents.z; + return glm::length(absPoint) <= _halfExtents.y; + } + } + case SHAPE_TYPE_BOX: + default: { + glm::vec3 absPoint = glm::abs(point); + return absPoint.x <= _halfExtents.x + && absPoint.y <= _halfExtents.y + && absPoint.z <= _halfExtents.z; + } + } +} + const DoubleHashKey& ShapeInfo::getHash() const { // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 8770ef62c7..114d209788 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -57,6 +57,10 @@ public: void appendToPoints (const QVector& newPoints) { _points << newPoints; } float computeVolume() const; + + /// Returns whether point is inside the shape + /// For compound shapes it will only return whether it is inside the bounding box + bool contains(const glm::vec3& point) const; const DoubleHashKey& getHash() const; From 78207f0d519a112fa1ac1d1ace2f7ae51136c0dc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 10:00:05 -0700 Subject: [PATCH 67/74] Make zones pickable in edit.js while control is down --- examples/edit.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/edit.js b/examples/edit.js index 8e7ccbc3c8..55c85b3b2f 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -517,12 +517,23 @@ function rayPlaneIntersection(pickRay, point, normal) { } function findClickedEntity(event) { + var pickZones = event.isControl; + + if (pickZones) { + print("Picking zones"); + Entities.setZonesArePickable(true); + } + var pickRay = Camera.computePickRay(event.x, event.y); var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking var lightResult = lightOverlayManager.findRayIntersection(pickRay); lightResult.accurate = true; + if (pickZones) { + Entities.setZonesArePickable(false); + } + var result; if (!entityResult.intersects && !lightResult.intersects) { From c21e06e7a757de1c77df87027667f0d911323342 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 23 Apr 2015 10:08:59 -0700 Subject: [PATCH 68/74] don't pile things up at the origin during a load --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 12fb1ba99d..9a4471cce6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -621,7 +621,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef auto nodeList = DependencyManager::get(); const QUuid& myNodeID = nodeList->getSessionUUID(); - if (_simulatorID == myNodeID) { + if (_simulatorID == myNodeID && !_simulatorID.isNull()) { // the packet that produced this bitstream originally came from physics simulations performed by // this node, so our version has to be newer than what the packet contained. _position = savePosition; From b340cd06bfc619f8f28f456722c03ff87aa050e8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 19:14:07 +0200 Subject: [PATCH 69/74] Fix volume formula for capsules --- libraries/shared/src/ShapeInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 2c88685a90..1c86f109c5 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -114,7 +114,7 @@ float ShapeInfo::computeVolume() const { } case SHAPE_TYPE_CAPSULE_Y: { float radius = _halfExtents.x; - volume = PI * radius * radius * (2.0f * _halfExtents.y + 4.0f * radius / 3.0f); + volume = PI * radius * radius * (2.0f * (_halfExtents.y - _halfExtents.x) + 4.0f * radius / 3.0f); break; } default: From b776ea811065de9e5ff330ab639796cda570d822 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 23 Apr 2015 19:15:06 +0200 Subject: [PATCH 70/74] Make ::contains() back into a const --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- libraries/entities-renderer/src/RenderableModelEntityItem.h | 2 +- libraries/entities-renderer/src/RenderableZoneEntityItem.cpp | 4 ++-- libraries/entities-renderer/src/RenderableZoneEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index af3e71ae58..dde13552f3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -324,7 +324,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { // create a list of entities that actually contain the avatar's position foreach(const EntityItem* entity, foundEntities) { - if (const_cast(entity)->contains(avatarPosition)) { + if (entity->contains(avatarPosition)) { entitiesContainingAvatar << entity->getEntityItemID(); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 40053cae48..8ca6562505 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -415,7 +415,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } -bool RenderableModelEntityItem::contains(const glm::vec3& point) { +bool RenderableModelEntityItem::contains(const glm::vec3& point) const { if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index f718c82936..43f18af0db 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -57,7 +57,7 @@ public: bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); - virtual bool contains(const glm::vec3& point); + virtual bool contains(const glm::vec3& point) const; private: void remapTextures(); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 4f198cff2e..e4c56dc419 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -39,12 +39,12 @@ int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch return bytesRead; } -bool RenderableZoneEntityItem::contains(const glm::vec3& point) { +bool RenderableZoneEntityItem::contains(const glm::vec3& point) const { if (getShapeType() != SHAPE_TYPE_COMPOUND) { return EntityItem::contains(point); } if (!_compoundShapeModel && hasCompoundShapeURL()) { - _compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); + const_cast(this)->_compoundShapeModel = DependencyManager::get()->getGeometry(getCompoundShapeURL(), QUrl(), true); } if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 0b49b39055..8d8d8b4b3f 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -29,7 +29,7 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - virtual bool contains(const glm::vec3& point); + virtual bool contains(const glm::vec3& point) const; private: diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1dbd9fe91f..65fe72fc1a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1082,7 +1082,7 @@ float EntityItem::getRadius() const { return 0.5f * glm::length(_dimensions); } -bool EntityItem::contains(const glm::vec3& point) { +bool EntityItem::contains(const glm::vec3& point) const { if (getShapeType() == SHAPE_TYPE_COMPOUND) { return getAABox().contains(point); } else { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1150e11a8a..0ebcd06a77 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -253,7 +253,7 @@ public: // TODO: get rid of users of getRadius()... float getRadius() const; - virtual bool contains(const glm::vec3& point); + virtual bool contains(const glm::vec3& point) const; virtual bool isReadyToComputeShape() { return true; } virtual void computeShapeInfo(ShapeInfo& info); From 361bf7e4413ba0c2e72326b408fb7a7194be70df Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 10:15:18 -0700 Subject: [PATCH 71/74] Remove unnecessary print --- examples/edit.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index 55c85b3b2f..59dcbaad19 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -520,7 +520,6 @@ function findClickedEntity(event) { var pickZones = event.isControl; if (pickZones) { - print("Picking zones"); Entities.setZonesArePickable(true); } From ac7b37323157b02d8e69b388128f92571ac92cee Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 23 Apr 2015 10:27:28 -0700 Subject: [PATCH 72/74] Throttle rendering needs to ensure it's active context --- interface/src/GLCanvas.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 0e25f0f596..9a9512a0b0 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -115,6 +115,7 @@ void GLCanvas::throttleRender() { OculusManager::beginFrameTiming(); } + makeCurrent(); Application::getInstance()->paintGL(); swapBuffers(); From d0af5580c8ff28bdff91337530deb4b6c989c0db Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 23 Apr 2015 10:28:03 -0700 Subject: [PATCH 73/74] Fix mouse wheel and clickthrough bugs in offscreen UI --- libraries/render-utils/src/OffscreenUi.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index db93a14b0d..969d3052cd 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -298,8 +298,11 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { mapWindowToUi(wheelEvent->pos(), originalDestination), wheelEvent->delta(), wheelEvent->buttons(), wheelEvent->modifiers(), wheelEvent->orientation()); - QCoreApplication::sendEvent(_quickWindow, &mappedEvent); - return true; + mappedEvent.ignore(); + if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { + return mappedEvent.isAccepted(); + } + break; } // Fall through @@ -314,8 +317,11 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { mapWindowToUi(transformedPos, originalDestination), mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); - QCoreApplication::sendEvent(_quickWindow, &mappedEvent); - return QObject::event(event); + mappedEvent.ignore(); + if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { + return mappedEvent.isAccepted(); + } + break; } default: From 1657c5092031a43d698368d9110083955de69f2d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 23 Apr 2015 12:00:13 -0700 Subject: [PATCH 74/74] Add limits to zone fields in entity properties window --- examples/html/entityProperties.html | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 348dc00df4..46afe5abf9 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -386,8 +386,8 @@ elZoneKeyLightColorRed.value = properties.keyLightColor.red; elZoneKeyLightColorGreen.value = properties.keyLightColor.green; elZoneKeyLightColorBlue.value = properties.keyLightColor.blue; - elZoneKeyLightIntensity.value = properties.keyLightIntensity; - elZoneKeyLightAmbientIntensity.value = properties.keyLightAmbientIntensity; + elZoneKeyLightIntensity.value = properties.keyLightIntensity.toFixed(2); + elZoneKeyLightAmbientIntensity.value = properties.keyLightAmbientIntensity.toFixed(2); elZoneKeyLightDirectionX.value = properties.keyLightDirection.x.toFixed(2); elZoneKeyLightDirectionY.value = properties.keyLightDirection.y.toFixed(2); elZoneKeyLightDirectionZ.value = properties.keyLightDirection.z.toFixed(2); @@ -907,21 +907,21 @@
Key Light Color
-
R
-
G
-
B
+
R
+
G
+
B
Key Light Intensity
- +
Key Light Ambient Intensity
- +
@@ -936,31 +936,31 @@
Stage Latitude
- +
Stage Longitude
- +
Stage Altitude
- +
Stage Day
- +
Stage Hour
- +