diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 2561a1502d..edd68e12bf 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -17,4 +17,5 @@ if (UNIX) target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) +include_application_version() copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 40aef1c707..ec0e5b9e5a 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -129,6 +129,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri packetReceiver.registerListener(PacketType::CreateAssignment, this, "handleCreateAssignmentPacket"); packetReceiver.registerListener(PacketType::StopNode, this, "handleStopNodePacket"); } + void AssignmentClient::stopAssignmentClient() { qDebug() << "Forced stop of assignment-client."; @@ -172,7 +173,6 @@ void AssignmentClient::aboutToQuit() { qInstallMessageHandler(0); } - void AssignmentClient::setUpStatusToMonitor() { // send a stats packet every 1 seconds connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatusPacketToACM); @@ -217,7 +217,6 @@ void AssignmentClient::sendAssignmentRequest() { qDebug() << "Failed to read local assignment server port from shared memory" << "- will send assignment request to previous assignment server socket."; } - } nodeList->sendAssignment(_requestAssignment); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 7268f9281b..2edae340c3 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setOrganizationName("High Fidelity"); setOrganizationDomain("highfidelity.io"); setApplicationName("assignment-client"); + setApplicationName(BUILD_VERSION); // use the verbose message handler in Logging qInstallMessageHandler(LogHandler::verboseMessageHandler); @@ -93,10 +95,8 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : Q_UNREACHABLE(); } - const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments()); - unsigned int numForks = 0; if (parser.isSet(numChildsOption)) { numForks = parser.value(numChildsOption).toInt(); @@ -139,7 +139,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : assignmentPool = parser.value(poolOption); } - QUuid walletUUID; if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString(); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 72765dd0df..ddea6cc702 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -203,7 +203,7 @@ void AssignmentClientMonitor::checkSpares() { void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer packet) { // read out the sender ID - QUuid senderID = QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)); + QUuid senderID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); auto nodeList = DependencyManager::get(); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 10a5992fd8..7e822951d8 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -90,7 +90,7 @@ int AudioMixerClientData::parseData(NLPacket& packet) { // grab the stream identifier for this injected audio packet.seek(sizeof(quint16)); - QUuid streamIdentifier = QUuid::fromRfc4122(packet.read(NUM_BYTES_RFC4122_UUID)); + QUuid streamIdentifier = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); bool isStereo; packet.readPrimitive(&isStereo); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index fec51f76cb..65660b178e 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -15,7 +15,7 @@ int AvatarMixerClientData::parseData(NLPacket& packet) { // compute the offset to the data payload - return _avatar.parseDataFromBuffer(packet.read(packet.bytesLeftToRead())); + return _avatar.parseDataFromBuffer(packet.readWithoutCopy(packet.bytesLeftToRead())); } bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() { diff --git a/interface/InterfaceVersion.h.in b/cmake/macros/ApplicationVersion.h.in similarity index 54% rename from interface/InterfaceVersion.h.in rename to cmake/macros/ApplicationVersion.h.in index 2f902de41c..736d00726c 100644 --- a/interface/InterfaceVersion.h.in +++ b/cmake/macros/ApplicationVersion.h.in @@ -1,11 +1,9 @@ // -// InterfaceVersion.h -// interface/src +// ApplicationVersion.h.in +// cmake/macros // -// Created by Leonardo Murillo on 12/16/13. -// Copyright 2013 High Fidelity, Inc. -// -// Declaration of version and build data +// Created by Leonardo Murillo on 8/13/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 diff --git a/cmake/macros/IncludeApplicationVersion.cmake b/cmake/macros/IncludeApplicationVersion.cmake new file mode 100644 index 0000000000..96137294a7 --- /dev/null +++ b/cmake/macros/IncludeApplicationVersion.cmake @@ -0,0 +1,22 @@ +# +# IncludeApplicationVersion.cmake +# cmake/macros +# +# Created by Leonardo Murillo on 07/14/2015. +# 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 +# + +macro(INCLUDE_APPLICATION_VERSION) + if (DEFINED ENV{JOB_ID}) + set (BUILD_SEQ $ENV{JOB_ID}) + elseif (DEFINED ENV{ghprbPullId}) + set (BUILD_SEQ "PR: $ENV{ghprbPullId} - Commit: $ENV{ghprbActualCommit}") + else () + set(BUILD_SEQ "dev") + endif () + configure_file("${MACRO_DIR}/ApplicationVersion.h.in" "${PROJECT_BINARY_DIR}/includes/ApplicationVersion.h") + include_directories("${PROJECT_BINARY_DIR}/includes") +endmacro(INCLUDE_APPLICATION_VERSION) diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 41f2d15486..e4fa1d874d 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -31,4 +31,5 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) +include_application_version() copy_dlls_beside_windows_executable() diff --git a/domain-server/resources/web/index.shtml b/domain-server/resources/web/index.shtml index b159d624a4..0f720ebe79 100644 --- a/domain-server/resources/web/index.shtml +++ b/domain-server/resources/web/index.shtml @@ -9,6 +9,7 @@ Type + Version UUID Pool Username @@ -24,6 +25,7 @@ <% _.each(nodes, function(node, node_index){ %> <%- node.type %> + <%- node.version %> <%- node.uuid %> <%- node.pool %> <%- node.username %> @@ -75,4 +77,4 @@ - \ No newline at end of file + diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4e5b563fc6..071626ef1e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : setOrganizationName("High Fidelity"); setOrganizationDomain("highfidelity.io"); setApplicationName("domain-server"); + setApplicationVersion(BUILD_VERSION); QSettings::setDefaultFormat(QSettings::IniFormat); // make sure we have a fresh AccountManager instance @@ -738,6 +740,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) if (isAssignment) { nodeData->setAssignmentUUID(matchingQueuedAssignment->getUUID()); nodeData->setWalletUUID(pendingAssigneeData->getWalletUUID()); + nodeData->setNodeVersion(pendingAssigneeData->getNodeVersion()); // always allow assignment clients to create and destroy entities newNode->setCanAdjustLocks(true); @@ -1168,7 +1171,8 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer packe // add the information for that deployed assignment to the hash of pending assigned nodes PendingAssignedNodeData* pendingNodeData = new PendingAssignedNodeData(assignmentToDeploy->getUUID(), - requestAssignment.getWalletUUID()); + requestAssignment.getWalletUUID(), + requestAssignment.getNodeVersion()); _pendingAssignedNodes.insert(uniqueAssignment.getUUID(), pendingNodeData); } else { if (requestAssignment.getType() != Assignment::AgentType @@ -1478,7 +1482,7 @@ const char JSON_KEY_POOL[] = "pool"; const char JSON_KEY_PENDING_CREDITS[] = "pending_credits"; const char JSON_KEY_WAKE_TIMESTAMP[] = "wake_timestamp"; const char JSON_KEY_USERNAME[] = "username"; - +const char JSON_KEY_VERSION[] = "version"; QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { QJsonObject nodeJson; @@ -1505,6 +1509,7 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { // add the node username, if it exists nodeJson[JSON_KEY_USERNAME] = nodeData->getUsername(); + nodeJson[JSON_KEY_VERSION] = nodeData->getNodeVersion(); SharedAssignmentPointer matchingAssignment = _allAssignments.value(nodeData->getAssignmentUUID()); if (matchingAssignment) { @@ -1527,7 +1532,6 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { } const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment"; - QString pathForAssignmentScript(const QUuid& assignmentUUID) { QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION); newPath += "/scripts/"; @@ -1537,7 +1541,6 @@ QString pathForAssignmentScript(const QUuid& assignmentUUID) { } const QString URI_OAUTH = "/oauth"; - bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) { const QString JSON_MIME_TYPE = "application/json"; @@ -2024,8 +2027,6 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl } const QString OAUTH_JSON_ACCESS_TOKEN_KEY = "access_token"; - - QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenReply) { // pull the access token from the returned JSON and store it with the matching session UUID QJsonDocument returnedJSON = QJsonDocument::fromJson(tokenReply->readAll()); @@ -2042,7 +2043,6 @@ QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenR } const QString DS_SETTINGS_SESSIONS_GROUP = "web-sessions"; - Headers DomainServer::setupCookieHeadersFromProfileReply(QNetworkReply* profileReply) { Headers cookieHeaders; diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index 57ed96acab..2c57368653 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -50,6 +50,10 @@ public: const NodeSet& getNodeInterestSet() const { return _nodeInterestSet; } void setNodeInterestSet(const NodeSet& nodeInterestSet) { _nodeInterestSet = nodeInterestSet; } + + void setNodeVersion(const QString& nodeVersion) { _nodeVersion = nodeVersion; } + const QString& getNodeVersion() { return _nodeVersion; } + private: QJsonObject mergeJSONStatsFromNewObject(const QJsonObject& newObject, QJsonObject destinationObject); @@ -62,6 +66,7 @@ private: HifiSockAddr _sendingSockAddr; bool _isAuthenticated; NodeSet _nodeInterestSet; + QString _nodeVersion; }; #endif // hifi_DomainServerNodeData_h diff --git a/domain-server/src/PendingAssignedNodeData.cpp b/domain-server/src/PendingAssignedNodeData.cpp index 21b3aa4ca4..30310ac01f 100644 --- a/domain-server/src/PendingAssignedNodeData.cpp +++ b/domain-server/src/PendingAssignedNodeData.cpp @@ -11,9 +11,10 @@ #include "PendingAssignedNodeData.h" -PendingAssignedNodeData::PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID) : +PendingAssignedNodeData::PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID, const QString& nodeVersion) : _assignmentUUID(assignmentUUID), - _walletUUID(walletUUID) + _walletUUID(walletUUID), + _nodeVersion(nodeVersion) { } \ No newline at end of file diff --git a/domain-server/src/PendingAssignedNodeData.h b/domain-server/src/PendingAssignedNodeData.h index 93d99a6f8f..2d546f573f 100644 --- a/domain-server/src/PendingAssignedNodeData.h +++ b/domain-server/src/PendingAssignedNodeData.h @@ -18,16 +18,20 @@ class PendingAssignedNodeData : public QObject { Q_OBJECT public: - PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID); + PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID, const QString& nodeVersion); void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } const QUuid& getAssignmentUUID() const { return _assignmentUUID; } void setWalletUUID(const QUuid& walletUUID) { _walletUUID = walletUUID; } const QUuid& getWalletUUID() const { return _walletUUID; } + + const QString& getNodeVersion() const { return _nodeVersion; } + private: QUuid _assignmentUUID; QUuid _walletUUID; + QString _nodeVersion; }; #endif // hifi_PendingAssignedNodeData_h \ No newline at end of file diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 922047b90c..c602c36382 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -16,6 +16,4 @@ Script.load("notifications.js"); Script.load("users.js"); Script.load("grab.js"); Script.load("directory.js"); -Script.load("mouseLook.js"); -Script.load("hmdControls.js"); Script.load("dialTone.js"); diff --git a/examples/edit.js b/examples/edit.js index 53f56dc03a..988e0a04b1 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1043,17 +1043,23 @@ function getPositionToCreateEntity() { var placementPosition = Vec3.sum(Camera.position, offset); var cameraPosition = Camera.position; + + var HALF_TREE_SCALE = 16384; - var cameraOutOfBounds = cameraPosition.x < 0 || cameraPosition.y < 0 || cameraPosition.z < 0; - var placementOutOfBounds = placementPosition.x < 0 || placementPosition.y < 0 || placementPosition.z < 0; + var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE + || Math.abs(cameraPosition.y) > HALF_TREE_SCALE + || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; + var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE + || Math.abs(placementPosition.y) > HALF_TREE_SCALE + || Math.abs(placementPosition.z) > HALF_TREE_SCALE; if (cameraOutOfBounds && placementOutOfBounds) { return null; } - placementPosition.x = Math.max(0, placementPosition.x); - placementPosition.y = Math.max(0, placementPosition.y); - placementPosition.z = Math.max(0, placementPosition.z); + placementPosition.x = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.x)); + placementPosition.y = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.y)); + placementPosition.z = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.z)); return placementPosition; } diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 8ebcec99fe..d7ee9228f4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -14,20 +14,12 @@ endforeach() find_package(Qt5LinguistTools REQUIRED) find_package(Qt5LinguistToolsMacros) -if (DEFINED ENV{JOB_ID}) - set(BUILD_SEQ $ENV{JOB_ID}) -elseif (DEFINED ENV{ghprbPullId}) - set(BUILD_SEQ "PR: $ENV{ghprbPullId} - Commit: $ENV{ghprbActualCommit}") -else () - set(BUILD_SEQ "dev") -endif () - if (WIN32) add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines endif() -configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h") +include_application_version() # grab the implementation and header files from src dirs file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h") @@ -174,7 +166,7 @@ if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE) endif () # include headers for interface and InterfaceConfig. -include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes") +include_directories("${PROJECT_SOURCE_DIR}/src") target_link_libraries( ${TARGET_NAME} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e633faf510..a28435e258 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -103,7 +104,6 @@ #include "AudioClient.h" #include "DiscoverabilityManager.h" #include "GLCanvas.h" -#include "InterfaceVersion.h" #include "LODManager.h" #include "Menu.h" #include "ModelPackager.h" @@ -175,8 +175,6 @@ public: using namespace std; // Starfield information -static uint8_t THROTTLED_IDLE_TIMER_DELAY = 10; - const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB static QTimer* locationUpdateTimer = NULL; @@ -737,6 +735,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _keyboardFocusHighlight->setVisible(false); } }); + + connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); } void Application::aboutToQuit() { @@ -2108,8 +2108,11 @@ void Application::idle() { // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in // perpetuity and not expect events to get backed up. + bool isThrottled = getActiveDisplayPlugin()->isThrottled(); + static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15; static const int IDLE_TIMER_DELAY_MS = 2; - int desiredInterval = getActiveDisplayPlugin()->isThrottled() ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; + int desiredInterval = isThrottled ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; + //qDebug() << "isThrottled:" << isThrottled << "desiredInterval:" << desiredInterval; if (idleTimer->interval() != desiredInterval) { idleTimer->start(desiredInterval); @@ -4612,6 +4615,24 @@ void Application::checkSkeleton() { } } +bool Application::isForeground() { + return _isForeground && !getWindow()->isMinimized(); +} + +void Application::activeChanged(Qt::ApplicationState state) { + switch (state) { + case Qt::ApplicationActive: + _isForeground = true; + break; + + case Qt::ApplicationSuspended: + case Qt::ApplicationHidden: + case Qt::ApplicationInactive: + default: + _isForeground = false; + break; + } +} void Application::showFriendsWindow() { const QString FRIENDS_WINDOW_TITLE = "Add/Remove Friends"; const QString FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends"; @@ -4725,6 +4746,7 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti } static QVector> _currentDisplayPluginActions; +static bool _activatingDisplayPlugin{false}; void Application::updateDisplayMode() { auto menu = Menu::getInstance(); @@ -4771,7 +4793,9 @@ void Application::updateDisplayMode() { if (newDisplayPlugin) { _offscreenContext->makeCurrent(); + _activatingDisplayPlugin = true; newDisplayPlugin->activate(); + _activatingDisplayPlugin = false; _offscreenContext->makeCurrent(); offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); _offscreenContext->makeCurrent(); @@ -4779,10 +4803,17 @@ void Application::updateDisplayMode() { oldDisplayPlugin = _displayPlugin; _displayPlugin = newDisplayPlugin; - + + // If the displayPlugin is a screen based HMD, then it will want the HMDTools displayed + // Direct Mode HMDs (like windows Oculus) will be isHmd() but will have a screen of -1 + bool newPluginWantsHMDTools = newDisplayPlugin ? + (newDisplayPlugin->isHmd() && (newDisplayPlugin->getHmdScreen() >= 0)) : false; + bool oldPluginWantedHMDTools = oldDisplayPlugin ? + (oldDisplayPlugin->isHmd() && (oldDisplayPlugin->getHmdScreen() >= 0)) : false; + // Only show the hmd tools after the correct plugin has // been activated so that it's UI is setup correctly - if (newDisplayPlugin->isHmd()) { + if (newPluginWantsHMDTools) { showDisplayPluginsTools(); } @@ -4791,7 +4822,7 @@ void Application::updateDisplayMode() { _offscreenContext->makeCurrent(); // if the old plugin was HMD and the new plugin is not HMD, then hide our hmdtools - if (oldDisplayPlugin->isHmd() && !newDisplayPlugin->isHmd()) { + if (oldPluginWantedHMDTools && !newPluginWantsHMDTools) { DependencyManager::get()->hmdTools(false); } } @@ -4888,14 +4919,17 @@ void Application::removeMenu(const QString& menuName) { void Application::addMenuItem(const QString& path, const QString& name, std::function onClicked, bool checkable, bool checked, const QString& groupName) { auto menu = Menu::getInstance(); MenuWrapper* parentItem = menu->getMenu(path); - QAction* action = parentItem->addAction(name); + QAction* action = menu->addActionToQMenuAndActionHash(parentItem, name); connect(action, &QAction::triggered, [=] { onClicked(action->isChecked()); }); action->setCheckable(checkable); action->setChecked(checked); - _currentDisplayPluginActions.push_back({ path, name }); - _currentInputPluginActions.push_back({ path, name }); + if (_activatingDisplayPlugin) { + _currentDisplayPluginActions.push_back({ path, name }); + } else { + _currentInputPluginActions.push_back({ path, name }); + } } void Application::removeMenuItem(const QString& menuName, const QString& menuItem) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 4819bd08a4..a1765109ce 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -291,6 +291,7 @@ public: virtual void unsetFullscreen(const QScreen* avoid) override; virtual void showDisplayPluginsTools() override; virtual QGLWidget* getPrimarySurface() override; + virtual bool isForeground() override; void setActiveDisplayPlugin(const QString& pluginName); @@ -476,6 +477,7 @@ private slots: void faceTrackerMuteToggled(); void setCursorVisible(bool visible); + void activeChanged(Qt::ApplicationState state); private: void resetCameras(Camera& camera, const glm::uvec2& size); @@ -688,6 +690,7 @@ private: SimpleMovingAverage _simsPerSecond{10}; int _simsPerSecondReport = 0; quint64 _lastSimsPerSecondUpdate = 0; + bool _isForeground = true; // starts out assumed to be in foreground }; #endif // hifi_Application_h diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 0d0d335b67..bfa2dacf3a 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -18,8 +18,6 @@ #include "MainWindow.h" -const int MSECS_PER_FRAME_WHEN_THROTTLED = 66; - static QGLFormat& getDesiredGLFormat() { // Specify an OpenGL 3.3 format using the Core profile. // That is, no old-school fixed pipeline functionality @@ -35,10 +33,7 @@ static QGLFormat& getDesiredGLFormat() { return glFormat; } -GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()), - _throttleRendering(false), - _idleRenderInterval(MSECS_PER_FRAME_WHEN_THROTTLED) -{ +GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()) { #ifdef Q_OS_LINUX // Cause GLCanvas::eventFilter to be called. // It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. @@ -46,15 +41,6 @@ GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()), #endif } -void GLCanvas::stopFrameTimer() { - _frameTimer.stop(); -} - -bool GLCanvas::isThrottleRendering() const { - return (_throttleRendering - || (Application::getInstance()->getWindow()->isMinimized() && Application::getInstance()->isThrottleFPSEnabled())); -} - int GLCanvas::getDeviceWidth() const { return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f); } @@ -66,17 +52,17 @@ int GLCanvas::getDeviceHeight() const { void GLCanvas::initializeGL() { setAttribute(Qt::WA_AcceptTouchEvents); setAcceptDrops(true); - connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); - connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); - // Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate. setAutoBufferSwap(false); } void GLCanvas::paintGL() { PROFILE_RANGE(__FUNCTION__); - if (!_throttleRendering && - (!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled())) { + + // FIXME - I'm not sure why this still remains, it appears as if this GLCanvas gets a single paintGL call near + // the beginning of the application starting up. I'm not sure if we really need to call Application::paintGL() + // in this case, since the display plugins eventually handle all the painting + if ((!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled())) { Application::getInstance()->paintGL(); } } @@ -85,39 +71,6 @@ void GLCanvas::resizeGL(int width, int height) { Application::getInstance()->resizeGL(); } -void GLCanvas::activeChanged(Qt::ApplicationState state) { - switch (state) { - case Qt::ApplicationActive: - // If we're active, stop the frame timer and the throttle. - _frameTimer.stop(); - _throttleRendering = false; - break; - - case Qt::ApplicationSuspended: - case Qt::ApplicationHidden: - // If we're hidden or are about to suspend, don't render anything. - _throttleRendering = false; - _frameTimer.stop(); - break; - - default: - // Otherwise, throttle. - if (!_throttleRendering && !Application::getInstance()->isAboutToQuit() - && Application::getInstance()->isThrottleFPSEnabled()) { - _frameTimer.start(_idleRenderInterval); - _throttleRendering = true; - } - break; - } -} - -void GLCanvas::throttleRender() { - _frameTimer.start(_idleRenderInterval); - if (!Application::getInstance()->getWindow()->isMinimized()) { - Application::getInstance()->paintGL(); - } -} - int updateTime = 0; bool GLCanvas::event(QEvent* event) { switch (event->type()) { diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index bcaa9577d1..73c5b5e8bf 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -23,28 +23,18 @@ class GLCanvas : public QGLWidget { public: GLCanvas(); - void stopFrameTimer(); - - bool isThrottleRendering() const; - int getDeviceWidth() const; int getDeviceHeight() const; QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } protected: - QTimer _frameTimer; - bool _throttleRendering; - int _idleRenderInterval; - virtual void initializeGL(); virtual void paintGL(); virtual void resizeGL(int width, int height); virtual bool event(QEvent* event); private slots: - void activeChanged(Qt::ApplicationState state); - void throttleRender(); bool eventFilter(QObject*, QEvent* event); }; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b0a78fdd83..ca46b80f92 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -283,7 +283,7 @@ namespace MenuOption { const QString TestPing = "Test Ping"; const QString ThirdPerson = "Third Person"; const QString ThreePointCalibration = "3 Point Calibration"; - const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; + const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Basic2DWindowOpenGLDisplayPlugin.cpp const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 3a01367fc7..8f687a93d6 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -43,11 +43,13 @@ void renderWorldBox(gpu::Batch& batch) { auto transform = Transform{}; batch.setModelTransform(transform); - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(TREE_SCALE, 0.0f, 0.0f), red); - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, TREE_SCALE, 0.0f), green); - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, TREE_SCALE), blue); - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, TREE_SCALE), glm::vec3(TREE_SCALE, 0.0f, TREE_SCALE), grey); - geometryCache->renderLine(batch, glm::vec3(TREE_SCALE, 0.0f, TREE_SCALE), glm::vec3(TREE_SCALE, 0.0f, 0.0f), grey); + + // TODO - consider alternate rendering for negative build-able space in the domain + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), red); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), green); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), blue); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), grey); + geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), grey); // Draw meter markers along the 3 axis to help with measuring things const float MARKER_DISTANCE = 1.0f; diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index 8888c9bae5..d552db1735 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -112,7 +112,7 @@ int InboundAudioStream::parseData(NLPacket& packet) { // parse the info after the seq number and before the audio data (the stream properties) int prePropertyPosition = packet.pos(); - int propertyBytes = parseStreamProperties(packet.getType(), packet.read(packet.bytesLeftToRead()), networkSamples); + int propertyBytes = parseStreamProperties(packet.getType(), packet.readWithoutCopy(packet.bytesLeftToRead()), networkSamples); packet.seek(prePropertyPosition + propertyBytes); // handle this packet based on its arrival status. @@ -131,7 +131,7 @@ int InboundAudioStream::parseData(NLPacket& packet) { if (packet.getType() == PacketType::SilentAudioFrame) { writeDroppableSilentSamples(networkSamples); } else { - parseAudioData(packet.getType(), packet.read(packet.bytesLeftToRead()), networkSamples); + parseAudioData(packet.getType(), packet.readWithoutCopy(packet.bytesLeftToRead()), networkSamples); } break; } diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 5c65f89990..4378e818ec 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -53,11 +53,11 @@ void AvatarHashMap::processAvatarDataPacket(QSharedPointer packet, Sha // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around) while (packet->bytesLeftToRead()) { - QUuid sessionUUID = QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); int positionBeforeRead = packet->pos(); - QByteArray byteArray = packet->read(packet->bytesLeftToRead()); + QByteArray byteArray = packet->readWithoutCopy(packet->bytesLeftToRead()); if (sessionUUID != _lastOwnerSessionUUID) { AvatarSharedPointer avatar = _avatarHash.value(sessionUUID); @@ -114,7 +114,7 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer packet, } void AvatarHashMap::processAvatarBillboardPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - QUuid sessionUUID = QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); AvatarSharedPointer avatar = _avatarHash.value(sessionUUID); if (!avatar) { @@ -129,7 +129,7 @@ void AvatarHashMap::processAvatarBillboardPacket(QSharedPointer packet void AvatarHashMap::processKillAvatar(QSharedPointer packet, SharedNodePointer sendingNode) { // read the node id - QUuid sessionUUID = QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)); + QUuid sessionUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); removeAvatar(sessionUUID); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index ce6467cd55..7667fa1a29 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -9,12 +9,11 @@ #include #include +#include const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display"); -const QString MENU_PARENT = "View"; -const QString MENU_NAME = "Display Options"; -const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; +const QString MENU_PATH = "Display"; const QString FULLSCREEN = "Fullscreen"; const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const { @@ -22,15 +21,44 @@ const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const { } void Basic2DWindowOpenGLDisplayPlugin::activate() { -// container->addMenu(MENU_PATH); -// container->addMenuItem(MENU_PATH, FULLSCREEN, -// [this] (bool clicked) { this->setFullscreen(clicked); }, -// true, false); + CONTAINER->addMenu(MENU_PATH); + CONTAINER->addMenuItem(MENU_PATH, FULLSCREEN, + [this](bool clicked) { + if (clicked) { + CONTAINER->setFullscreen(getFullscreenTarget()); + } else { + CONTAINER->unsetFullscreen(); + } + }, true, false); MainWindowOpenGLDisplayPlugin::activate(); } void Basic2DWindowOpenGLDisplayPlugin::deactivate() { -// container->removeMenuItem(MENU_NAME, FULLSCREEN); -// container->removeMenu(MENU_PATH); MainWindowOpenGLDisplayPlugin::deactivate(); } + +int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval(bool isThrottled) const { + static const int THROTTLED_PAINT_TIMER_DELAY = MSECS_PER_SECOND / 15; + static const int PAINT_TIMER_DELAY_MS = 1; + + return isThrottled ? THROTTLED_PAINT_TIMER_DELAY : PAINT_TIMER_DELAY_MS; +} + +bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { + static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h + + bool shouldThrottle = (!CONTAINER->isForeground() && CONTAINER->isOptionChecked(ThrottleFPSIfNotFocus)); + + if (_isThrottled != shouldThrottle) { + int desiredInterval = getDesiredInterval(shouldThrottle); + _timer.start(desiredInterval); + _isThrottled = shouldThrottle; + } + + return shouldThrottle; +} + +// FIXME target the screen the window is currently on +QScreen* Basic2DWindowOpenGLDisplayPlugin::getFullscreenTarget() { + return qApp->primaryScreen(); +} diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index d19326f007..477e214f4e 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -9,6 +9,7 @@ #include "MainWindowOpenGLDisplayPlugin.h" +class QScreen; class Basic2DWindowOpenGLDisplayPlugin : public MainWindowOpenGLDisplayPlugin { Q_OBJECT @@ -18,6 +19,14 @@ public: virtual const QString & getName() const override; + virtual bool isThrottled() const override; + +protected: + int getDesiredInterval(bool isThrottled) const; + mutable bool _isThrottled = false; + private: static const QString NAME; + QScreen* getFullscreenTarget(); + int _fullscreenTarget{ -1 }; }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 9986610a50..9b6b92d8d4 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -37,8 +37,8 @@ protected: virtual void doneCurrent() = 0; virtual void swapBuffers() = 0; - QTimer _timer; - ProgramPtr _program; + mutable QTimer _timer; + ProgramPtr _program; ShapeWrapperPtr _plane; }; diff --git a/libraries/entities/src/AddEntityOperator.cpp b/libraries/entities/src/AddEntityOperator.cpp index b85d12c2da..51015c1ff4 100644 --- a/libraries/entities/src/AddEntityOperator.cpp +++ b/libraries/entities/src/AddEntityOperator.cpp @@ -25,7 +25,8 @@ AddEntityOperator::AddEntityOperator(EntityTree* tree, { // caller must have verified existence of newEntity assert(_newEntity); - _newEntityBox = _newEntity->getMaximumAACube().clamp(0.0f, (float)TREE_SCALE); + + _newEntityBox = _newEntity->getMaximumAACube().clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE); } bool AddEntityOperator::preRecursion(OctreeElement* element) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index e7c280686a..31c2ffad1e 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -253,7 +253,7 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object // define these inline here so the macros work inline void EntityItemProperties::setPosition(const glm::vec3& value) - { _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; } + { _position = glm::clamp(value, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); _positionChanged = true; } inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { debug << "EntityItemProperties[" << "\n"; diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index f2bd1e873e..06f5023193 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -113,7 +113,7 @@ void EntitySimulation::sortEntitiesThatMoved() { // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. PerformanceTimer perfTimer("sortingEntities"); MovingEntitiesOperator moveOperator(_entityTree); - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE); + AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); SetOfEntities::iterator itemItr = _entitiesToSort.begin(); while (itemItr != _entitiesToSort.end()) { EntityItemPointer entity = *itemItr; @@ -195,7 +195,7 @@ void EntitySimulation::changeEntity(EntityItemPointer entity) { bool wasRemoved = false; uint32_t dirtyFlags = entity->getDirtyFlags(); if (dirtyFlags & EntityItem::DIRTY_POSITION) { - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE); + AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); AACube newCube = entity->getMaximumAACube(); if (!domainBounds.touches(newCube)) { qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ba2691aa3b..ba0e3f495f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -873,7 +873,7 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s break; // bail to prevent buffer overflow } - QUuid entityID = QUuid::fromRfc4122(packet.read(NUM_BYTES_RFC4122_UUID)); + QUuid entityID = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 856550f297..a023f46c5e 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -444,14 +444,14 @@ bool EntityTreeElement::bestFitBounds(const AABox& bounds) const { } bool EntityTreeElement::containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const { - glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, (float)TREE_SCALE); - glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, (float)TREE_SCALE); + glm::vec3 clampedMin = glm::clamp(minPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); + glm::vec3 clampedMax = glm::clamp(maxPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); return _cube.contains(clampedMin) && _cube.contains(clampedMax); } bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const { - glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, (float)TREE_SCALE); - glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, (float)TREE_SCALE); + glm::vec3 clampedMin = glm::clamp(minPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); + glm::vec3 clampedMax = glm::clamp(maxPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) { diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index ddfea13d07..7dd1ab849c 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -52,7 +52,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() { void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) { EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); - AABox newCubeClamped = newCube.clamp(0.0f, (float)TREE_SCALE); + AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); if (_wantDebug) { qCDebug(entities) << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------"; diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 6720839da0..991d725f97 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -47,7 +47,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, // which can handle all potential rotations? // the getMaximumAACube is the relaxed form. _oldEntityCube = _existingEntity->getMaximumAACube(); - _oldEntityBox = _oldEntityCube.clamp(0.0f, (float)TREE_SCALE); // clamp to domain bounds + _oldEntityBox = _oldEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds // If the old properties doesn't contain the properties required to calculate a bounding box, // get them from the existing entity. Registration point is required to correctly calculate @@ -123,7 +123,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, } } - _newEntityBox = _newEntityCube.clamp(0.0f, (float)TREE_SCALE); // clamp to domain bounds + _newEntityBox = _newEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds if (_wantDebug) { diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 6b386ace92..d79e6bde58 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -28,4 +28,5 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) # append tbb includes to our list of includes to bubble -target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS}) \ No newline at end of file +target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS}) +include_application_version() \ No newline at end of file diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index 293d86475f..b63373858e 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -15,6 +15,7 @@ #include +#include #include "Assignment.h" Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { @@ -52,11 +53,14 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, const _location(location), _payload(), _isStatic(false), - _walletUUID() + _walletUUID(), + _nodeVersion() { if (_command == Assignment::CreateCommand) { // this is a newly created assignment, generate a random UUID _uuid = QUuid::createUuid(); + } else if (_command == Assignment::RequestCommand) { + _nodeVersion = BUILD_VERSION; } } @@ -64,7 +68,8 @@ Assignment::Assignment(NLPacket& packet) : _pool(), _location(GlobalLocation), _payload(), - _walletUUID() + _walletUUID(), + _nodeVersion() { if (packet.getType() == PacketType::RequestAssignment) { _command = Assignment::RequestCommand; @@ -83,15 +88,14 @@ Assignment::Assignment(NLPacket& packet) : Assignment::Assignment(const Assignment& otherAssignment) { - _uuid = otherAssignment._uuid; - _command = otherAssignment._command; _type = otherAssignment._type; _location = otherAssignment._location; _pool = otherAssignment._pool; _payload = otherAssignment._payload; _walletUUID = otherAssignment._walletUUID; + _nodeVersion = otherAssignment._nodeVersion; } Assignment& Assignment::operator=(const Assignment& rhsAssignment) { @@ -110,6 +114,7 @@ void Assignment::swap(Assignment& otherAssignment) { swap(_pool, otherAssignment._pool); swap(_payload, otherAssignment._payload); swap(_walletUUID, otherAssignment._walletUUID); + swap(_nodeVersion, otherAssignment._nodeVersion); } const char* Assignment::getTypeName() const { @@ -139,7 +144,13 @@ QDebug operator<<(QDebug debug, const Assignment &assignment) { } QDataStream& operator<<(QDataStream &out, const Assignment& assignment) { - out << (quint8) assignment._type << assignment._uuid << assignment._pool << assignment._payload; + out << (quint8) assignment._type; + + if (assignment._command == Assignment::RequestCommand) { + out << assignment._nodeVersion; + } + + out << assignment._uuid << assignment._pool << assignment._payload; if (assignment._command == Assignment::RequestCommand) { out << assignment._walletUUID; @@ -151,6 +162,9 @@ QDataStream& operator<<(QDataStream &out, const Assignment& assignment) { QDataStream& operator>>(QDataStream &in, Assignment& assignment) { quint8 packedType; in >> packedType; + if (assignment._command == Assignment::RequestCommand) { + in >> assignment._nodeVersion; + } assignment._type = (Assignment::Type) packedType; in >> assignment._uuid >> assignment._pool >> assignment._payload; diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 67f861f850..6950223a9d 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -83,6 +83,8 @@ public: void setWalletUUID(const QUuid& walletUUID) { _walletUUID = walletUUID; } const QUuid& getWalletUUID() const { return _walletUUID; } + const QString& getNodeVersion() const { return _nodeVersion; } + const char* getTypeName() const; friend QDebug operator<<(QDebug debug, const Assignment& assignment); @@ -98,6 +100,7 @@ protected: QByteArray _payload; /// an optional payload attached to this assignment, a maximum for 1024 bytes will be packed bool _isStatic; /// defines if this assignment needs to be re-queued in the domain-server if it stops being fulfilled QUuid _walletUUID; /// the UUID for the wallet that should be paid for this assignment + QString _nodeVersion; }; #endif // hifi_Assignment_h diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index fdb3461c1f..48febf39bd 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -397,7 +397,7 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { void LimitedNodeList::processKillNode(NLPacket& packet) { // read the node id - QUuid nodeUUID = QUuid::fromRfc4122(packet.read(NUM_BYTES_RFC4122_UUID)); + QUuid nodeUUID = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); // kill the node with this UUID, if it exists killNodeWithUUID(nodeUUID); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 44b9c0b829..6616707579 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include "AccountManager.h" @@ -367,7 +368,6 @@ void NodeList::sendDSPathQuery(const QString& newPath) { } } - void NodeList::processDomainServerPathResponse(QSharedPointer packet) { // This is a response to a path query we theoretically made. // In the future we may want to check that this was actually from our DS and for a query we actually made. @@ -457,14 +457,13 @@ void NodeList::pingPunchForDomainServer() { } } - void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer packet) { if (_domainHandler.getSockAddr().isNull()) { // refuse to process this packet if we aren't currently connected to the DS return; } // read in the connection token from the packet, then send domain-server checkin - _domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID))); + _domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID))); sendDomainServerCheckIn(); } @@ -548,7 +547,7 @@ void NodeList::sendAssignment(Assignment& assignment) { : PacketType::RequestAssignment; auto assignmentPacket = NLPacket::create(assignmentPacketType); - + QDataStream packetStream(assignmentPacket.get()); packetStream << assignment; diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 13f8a39e26..81747749be 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -213,6 +213,13 @@ void Packet::writeSequenceNumber(SequenceNumber seqNum) { } QByteArray Packet::read(qint64 maxSize) { + qint64 sizeToRead = std::min(size() - pos(), maxSize); + QByteArray data { getPayload() + pos(), (int) sizeToRead }; + seek(pos() + sizeToRead); + return data; +} + +QByteArray Packet::readWithoutCopy(qint64 maxSize) { qint64 sizeToRead = std::min(size() - pos(), maxSize); QByteArray data { QByteArray::fromRawData(getPayload() + pos(), sizeToRead) }; seek(pos() + sizeToRead); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 91b5974e09..569ff4b9a4 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -81,7 +81,8 @@ public: using QIODevice::read; QByteArray read(qint64 maxSize); - + QByteArray readWithoutCopy(qint64 maxSize); // this can only be used if packet will stay in scope + template qint64 peekPrimitive(T* data); template qint64 readPrimitive(T* data); template qint64 writePrimitive(const T& data); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 5562490344..db2a426696 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -67,7 +67,7 @@ PacketVersion versionForPacketType(PacketType::Value packetType) { case EntityAdd: case EntityEdit: case EntityData: - return VERSION_ENTITIES_POLYLINE; + return VERSION_OCTREE_CENTERED_ORIGIN; case AvatarData: return 12; default: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 1aeadb1af9..75d8105dca 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -142,5 +142,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35; const PacketVersion VERSION_POLYVOX_TEXTURES = 36; const PacketVersion VERSION_ENTITIES_POLYLINE = 37; +const PacketVersion VERSION_OCTREE_CENTERED_ORIGIN = 38; #endif // hifi_PacketHeaders_h \ No newline at end of file diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 4a1baea2d5..a98f042006 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -17,7 +17,8 @@ const quint64 CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels -const int TREE_SCALE = 16384; // ~10 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe +const int TREE_SCALE = 32768; // ~20 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe +const int HALF_TREE_SCALE = TREE_SCALE / 2; // This controls the LOD. Larger number will make smaller voxels visible at greater distance. const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * 400.0f; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 85ea0caef0..2bbacccf95 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -191,6 +191,7 @@ void OctreeElement::calculateAACube() { // this tells you the "size" of the voxel float voxelScale = (float)TREE_SCALE / powf(2.0f, numberOfThreeBitSectionsInCode(getOctalCode())); corner *= (float)TREE_SCALE; + corner -= (float)HALF_TREE_SCALE; _cube.setBox(corner, voxelScale); } @@ -717,8 +718,8 @@ int OctreeElement::getMyChildContaining(const AACube& cube) const { } // Determine which of our children the minimum and maximum corners of the cube live in... - glm::vec3 cubeCornerMinimum = glm::clamp(cube.getCorner(), 0.0f, (float)TREE_SCALE); - glm::vec3 cubeCornerMaximum = glm::clamp(cube.calcTopFarLeft(), 0.0f, (float)TREE_SCALE); + glm::vec3 cubeCornerMinimum = glm::clamp(cube.getCorner(), (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); + glm::vec3 cubeCornerMaximum = glm::clamp(cube.calcTopFarLeft(), (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); if (_cube.contains(cubeCornerMinimum) && _cube.contains(cubeCornerMaximum)) { int childIndexCubeMinimum = getMyChildContainingPoint(cubeCornerMinimum); diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 3e41b58bb6..fe40cfd53c 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -31,7 +31,7 @@ const float DEFAULT_KEYHOLE_RADIUS = 3.0f; const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; const float DEFAULT_NEAR_CLIP = 0.08f; -const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; +const float DEFAULT_FAR_CLIP = (float)HALF_TREE_SCALE; class ViewFrustum { public: diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index 85c5c814de..7f6346a181 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -26,4 +26,5 @@ public: virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) = 0; virtual void showDisplayPluginsTools() = 0; virtual QGLWidget* getPrimarySurface() = 0; + virtual bool isForeground() = 0; };