diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 1eb43a45a5..23df64be2e 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -1486,16 +1486,16 @@ std::pair AssetServer::readMetaFile(AssetUtils::AssetHash hash) if (error.error == QJsonParseError::NoError && doc.isObject()) { auto root = doc.object(); - auto bakeVersion = root[BAKE_VERSION_KEY].toInt(-1); + auto bakeVersion = root[BAKE_VERSION_KEY]; auto failedLastBake = root[FAILED_LAST_BAKE_KEY]; auto lastBakeErrors = root[LAST_BAKE_ERRORS_KEY]; - if (bakeVersion != -1 + if (bakeVersion.isDouble() && failedLastBake.isBool() && lastBakeErrors.isString()) { AssetMeta meta; - meta.bakeVersion = bakeVersion; + meta.bakeVersion = bakeVersion.toInt(); meta.failedLastBake = failedLastBake.toBool(); meta.lastBakeErrors = lastBakeErrors.toString(); diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index 1c66fb213f..4d0773f5f5 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66.zip - URL_MD5 91edfde96e06efc847ca327ab97f4c74 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v2.zip + URL_MD5 d76bdb3e2bf7ae5d20115bd97b0c44a8 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake index 742c5b5b94..acafd9b6c7 100644 --- a/cmake/macros/GenerateInstallers.cmake +++ b/cmake/macros/GenerateInstallers.cmake @@ -14,12 +14,24 @@ macro(GENERATE_INSTALLERS) set(CPACK_MODULE_PATH ${CPACK_MODULE_PATH} "${HF_CMAKE_DIR}/templates") - set(_DISPLAY_NAME ${BUILD_ORGANIZATION}) + + if (CLIENT_ONLY) + set(_PACKAGE_NAME_EXTRA "-Interface") + set(INSTALLER_TYPE "client_only") + string(REGEX REPLACE "High Fidelity" "High Fidelity Interface" _DISPLAY_NAME ${BUILD_ORGANIZATION}) + elseif (SERVER_ONLY) + set(_PACKAGE_NAME_EXTRA "-Sandbox") + set(INSTALLER_TYPE "server_only") + string(REGEX REPLACE "High Fidelity" "High Fidelity Sandbox" _DISPLAY_NAME ${BUILD_ORGANIZATION}) + else () + set(_DISPLAY_NAME ${BUILD_ORGANIZATION}) + set(INSTALLER_TYPE "full") + endif () set(CPACK_PACKAGE_NAME ${_DISPLAY_NAME}) set(CPACK_PACKAGE_VENDOR "High Fidelity") set(CPACK_PACKAGE_VERSION ${BUILD_VERSION}) - set(CPACK_PACKAGE_FILE_NAME "HighFidelity-Beta-${BUILD_VERSION}") + set(CPACK_PACKAGE_FILE_NAME "HighFidelity-Beta${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}") set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME}) set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME}) if (PR_BUILD) diff --git a/cmake/templates/CPackProperties.cmake.in b/cmake/templates/CPackProperties.cmake.in index 9c303f7532..80d86ac030 100644 --- a/cmake/templates/CPackProperties.cmake.in +++ b/cmake/templates/CPackProperties.cmake.in @@ -48,3 +48,4 @@ set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@") set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@") set(SERVER_COMPONENT_CONDITIONAL "@SERVER_COMPONENT_CONDITIONAL@") set(CLIENT_COMPONENT_CONDITIONAL "@CLIENT_COMPONENT_CONDITIONAL@") +set(INSTALLER_TYPE "@INSTALLER_TYPE@") diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 7faa67d1b0..bdedf4cbba 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -710,11 +710,9 @@ Function PostInstallOptionsPage !insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED} ${EndIf} - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)" - Pop $CleanInstallCheckbox - IntOp $CurrentOffset $CurrentOffset + 15 - ${EndIf} + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)" + Pop $CleanInstallCheckbox + IntOp $CurrentOffset $CurrentOffset + 15 ${If} @PR_BUILD@ == 1 ; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked @@ -809,10 +807,8 @@ Function ReadPostInstallOptions ${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState ${EndIf} - ${If} @CLIENT_COMPONENT_CONDITIONAL@ - ; check if the user asked for a clean install - ${NSD_GetState} $CleanInstallCheckbox $CleanInstallState - ${EndIf} + ; check if the user asked for a clean install + ${NSD_GetState} $CleanInstallCheckbox $CleanInstallState FunctionEnd Function HandlePostInstallOptions @@ -856,13 +852,23 @@ Function HandlePostInstallOptions ${EndIf} ${EndIf} - ${If} @CLIENT_COMPONENT_CONDITIONAL@ - ; check if the user asked for a clean install - ${If} $CleanInstallState == ${BST_CHECKED} - SetShellVarContext current - RMDir /r "$APPDATA\@BUILD_ORGANIZATION@" - RMDir /r "$LOCALAPPDATA\@BUILD_ORGANIZATION@" + ; check if the user asked for a clean install + ${If} $CleanInstallState == ${BST_CHECKED} + SetShellVarContext current + + ${If} @SERVER_COMPONENT_CONDITIONAL@ + RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\Server Console" + RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\assignment-client" + RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\domain-server" + Delete "$APPDATA\@BUILD_ORGANIZATION@\domain-server.json" ${EndIf} + + ${If} @CLIENT_COMPONENT_CONDITIONAL@ + Delete "$APPDATA\@BUILD_ORGANIZATION@\Interface\AccountInfo.bin" + Delete "$APPDATA\@BUILD_ORGANIZATION@\Interface.json" + ${EndIf} + + RMDir /r "$LOCALAPPDATA\@BUILD_ORGANIZATION@" ${EndIf} ${If} @PR_BUILD@ == 1 @@ -976,6 +982,13 @@ Section "-Core installation" ;Store installation folder WriteRegStr HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + ;Write some information about this install to the installation folder + FileOpen $0 "$INSTDIR\installer.ini" w + FileWrite $0 "type=@INSTALLER_TYPE@$\r$\n" + FileWrite $0 "campaign=$CampaignName$\r$\n" + FileWrite $0 "exepath=$EXEPATH$\r$\n" + FileClose $0 + ;Package the signed uninstaller produced by the inner loop !ifndef INNER ; this packages the signed uninstaller diff --git a/interface/resources/controllers/touchscreenvirtualpad.json b/interface/resources/controllers/touchscreenvirtualpad.json index 907ff8b403..bae1172152 100644 --- a/interface/resources/controllers/touchscreenvirtualpad.json +++ b/interface/resources/controllers/touchscreenvirtualpad.json @@ -5,8 +5,25 @@ { "from": "TouchscreenVirtualPad.LX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" }, - { "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05} , "invert" ], "to": "Actions.Yaw" }, + { "from": "TouchscreenVirtualPad.JUMP_BUTTON_PRESS", "when": "!Application.CameraIndependent", "to": "Actions.VERTICAL_UP" }, + + { "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", + "filters": [ + { "type": "deadZone", "min": 0.000 }, + { "type": "scale", "scale": 0.06 }, + "invert" + ], + "to": "Actions.Yaw" + }, + + { "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", + "filters": [ + { "type": "deadZone", "min": 0.000 }, + { "type": "scale", "scale": 0.06 }, + "invert" + ], + "to": "Actions.Pitch" + } - { "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05}, "invert" ], "to": "Actions.Pitch" } ] } diff --git a/interface/resources/images/fly.png b/interface/resources/images/fly.png new file mode 100644 index 0000000000..0edfcab21b Binary files /dev/null and b/interface/resources/images/fly.png differ diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml index efc8519c1e..8e7db44b7d 100644 --- a/interface/resources/qml/controls/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/FlickableWebViewCore.qml @@ -122,9 +122,21 @@ Item { newViewRequestedCallback(request) } + // Prior to 5.10, the WebEngineView loading property is true during initial page loading and then stays false + // as in-page javascript adds more html content. However, in 5.10 there is a bug such that adding html turns + // loading true, and never turns it false again. safeLoading provides a workaround, but it should be removed + // when QT fixes this. + property bool safeLoading: false + property bool loadingLatched: false + property var loadingRequest: null onLoadingChanged: { - flick.onLoadingChanged(loadRequest) - loadingChangedCallback(loadRequest) + webViewCore.loadingRequest = loadRequest; + webViewCore.safeLoading = webViewCore.loading && !loadingLatched; + webViewCore.loadingLatched |= webViewCore.loading; + } + onSafeLoadingChanged: { + flick.onLoadingChanged(webViewCore.loadingRequest) + loadingChangedCallback(webViewCore.loadingRequest) } } @@ -133,7 +145,7 @@ Item { x: flick.width/2 - width/2 y: flick.height/2 - height/2 source: "../../icons/loader-snake-64-w.gif" - visible: webViewCore.loading && /^(http.*|)$/i.test(webViewCore.url.toString()) + visible: webViewCore.safeLoading && /^(http.*|)$/i.test(webViewCore.url.toString()) playing: visible z: 10000 } diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 6e1bb4b309..6ce4722d04 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -272,6 +272,8 @@ ModalWindow { root.canceled(); // FIXME we are leaking memory to avoid a crash // root.destroy(); + + root.disableFade = true visible = false; } } @@ -296,6 +298,8 @@ ModalWindow { root.selected(root.result); // FIXME we are leaking memory to avoid a crash // root.destroy(); + + root.disableFade = true visible = false; } } diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index 6f05179bd5..ec62f16087 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -171,6 +171,8 @@ ModalWindow { root.canceled(); // FIXME we are leaking memory to avoid a crash // root.destroy(); + + root.disableFade = true visible = false; } } @@ -183,6 +185,8 @@ ModalWindow { root.selected(root.result); // FIXME we are leaking memory to avoid a crash // root.destroy(); + + root.disableFade = true visible = false; } } diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 4b9e1af4f1..2da32514cb 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -141,7 +141,10 @@ StackView { bottom: parent.bottom } - onHostChanged: updateLocationTextTimer.restart(); + onHostChanged: { + updateLocationTextTimer.restart(); + DialogsManager.hideAddressBar(); + } Rectangle { id: navBar diff --git a/interface/resources/qml/windows/Fadable.qml b/interface/resources/qml/windows/Fadable.qml index 4d506755f2..52d2264e7d 100644 --- a/interface/resources/qml/windows/Fadable.qml +++ b/interface/resources/qml/windows/Fadable.qml @@ -39,7 +39,7 @@ FocusScope { // If someone directly set the visibility to false // toggle it back on and use the targetVisible flag to transition // via fading. - if ((!visible && fadeTargetProperty != 0.0) || (visible && fadeTargetProperty == 0.0)) { + if (!disableFade && ((!visible && fadeTargetProperty != 0.0) || (visible && fadeTargetProperty == 0.0))) { var target = visible; visible = !visible; fadeTargetProperty = target ? 1.0 : 0.0; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4b64e8a0c5..343074f61c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3046,7 +3046,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { static const QString SENT_TO_PREVIOUS_LOCATION = "previous_location"; static const QString SENT_TO_ENTRY = "entry"; - static const QString SENT_TO_SANDBOX = "sandbox"; QString sentTo; @@ -3055,15 +3054,8 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { #if !defined(Q_OS_ANDROID) showHelp(); #endif - if (sandboxIsRunning) { - qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; - DependencyManager::get()->goToLocalSandbox(); - sentTo = SENT_TO_SANDBOX; - } else { - qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry."; - DependencyManager::get()->goToEntry(); - sentTo = SENT_TO_ENTRY; - } + DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; firstRun.set(false); } else { diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index e2d47bf844..33cfc481d7 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -129,7 +129,7 @@ void DiscoverabilityManager::updateLocation() { // Update Steam if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { - steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); + steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingPublicAddress()); } } diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index f8a62e848c..5f762ab511 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -110,6 +110,7 @@ bool SelectionScriptingInterface::enableListHighlight(const QString& listName, c } if (!(*highlightStyle).isBoundToList()) { + enableListToScene(listName); (*highlightStyle).setBoundToList(true); } @@ -133,6 +134,7 @@ bool SelectionScriptingInterface::disableListHighlight(const QString& listName) auto highlightStyle = _highlightStyleMap.find(listName); if (highlightStyle != _highlightStyleMap.end()) { if ((*highlightStyle).isBoundToList()) { + disableListToScene(listName); } _highlightStyleMap.erase(highlightStyle); @@ -476,4 +478,4 @@ QVariantMap SelectionHighlightStyle::toVariantMap() const { properties["isOutlineSmooth"] = _style._isOutlineSmooth; return properties; -} \ No newline at end of file +} diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 3046ac371e..ed6efb39c6 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -165,6 +165,8 @@ public: * @param listName {string} name of the selection * @param highlightStyle {jsObject} highlight style fields (see Selection.getListHighlightStyle for a detailed description of the highlightStyle). * @returns {bool} true if the selection was successfully enabled for highlight. + * + * Note: This function will implicitly call Selection.enableListToScene */ Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle); @@ -175,8 +177,10 @@ public: * @function Selection.disableListHighlight * @param listName {string} name of the selection * @returns {bool} true if the selection was successfully disabled for highlight, false otherwise. + * + * Note: This function will implicitly call Selection.disableListToScene */ - Q_INVOKABLE bool disableListHighlight(const QString& listName); + Q_INVOKABLE bool disableListHighlight(const QString& listName); /**jsdoc * Enable scene selection for the named selection. * If the Selection doesn't exist, it will be created. @@ -246,7 +250,7 @@ private: void setupHandler(const QString& selectionName); void removeHandler(const QString& selectionName); - + }; #endif // hifi_SelectionScriptingInterface_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 9b3089d78d..69103a40b5 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -95,7 +95,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename) { // adding URL to snapshot - QUrl currentURL = DependencyManager::get()->currentShareableAddress(); + QUrl currentURL = DependencyManager::get()->currentPublicAddress(); shot.setText(URL, currentURL.toString()); QString username = DependencyManager::get()->getAccountInfo().getUsername(); diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index 3408cb8512..37505db629 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -65,7 +65,7 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { } else { emit DependencyManager::get()->snapshotShared(true, contents); - delete this; + this->deleteLater(); } } @@ -75,23 +75,27 @@ void SnapshotUploader::uploadFailure(QNetworkReply& reply) { if (replyString.size() == 0) { replyString = reply.errorString(); } + replyString = replyString.left(1000); // Only print first 1000 characters of error + qDebug() << "Snapshot upload reply error (truncated):" << replyString; emit DependencyManager::get()->snapshotShared(true, replyString); // maybe someday include _inWorldLocation, _filename? - delete this; + this->deleteLater(); } void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { QString replyString = reply.readAll(); emit DependencyManager::get()->snapshotShared(false, replyString); - delete this; + this->deleteLater(); } void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { QString replyString = reply.readAll(); - qDebug() << "Error " << reply.errorString() << " uploading snapshot " << _pathname << " from " << _inWorldLocation; + qDebug() << "Error " << reply.errorString() << " uploading snapshot story " << _pathname << " from " << _inWorldLocation; if (replyString.size() == 0) { replyString = reply.errorString(); } + replyString = replyString.left(1000); // Only print first 1000 characters of error + qDebug() << "Snapshot story upload reply error (truncated):" << replyString; emit DependencyManager::get()->snapshotShared(true, replyString); - delete this; + this->deleteLater(); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 97f74fa24e..f33af1b580 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -25,11 +25,11 @@ static const QString FULLSCREEN = "Fullscreen"; void Basic2DWindowOpenGLDisplayPlugin::customizeContext() { #if defined(Q_OS_ANDROID) + qreal dpi = getFullscreenTarget()->physicalDotsPerInch(); + _virtualPadPixelSize = dpi * VirtualPad::Manager::BASE_DIAMETER_PIXELS / VirtualPad::Manager::DPI; + auto iconPath = PathUtils::resourcesPath() + "images/analog_stick.png"; auto image = QImage(iconPath); - qreal dpi = getFullscreenTarget()->physicalDotsPerInch(); - _virtualPadPixelSize = dpi * VirtualPad::Manager::PIXEL_SIZE / VirtualPad::Manager::DPI; - if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } @@ -69,6 +69,29 @@ void Basic2DWindowOpenGLDisplayPlugin::customizeContext() { _virtualPadStickBaseTexture->assignStoredMip(0, image.byteCount(), image.constBits()); _virtualPadStickBaseTexture->setAutoGenerateMips(true); } + + _virtualPadJumpBtnPixelSize = dpi * VirtualPad::Manager::JUMP_BTN_FULL_PIXELS / VirtualPad::Manager::DPI; + iconPath = PathUtils::resourcesPath() + "images/fly.png"; + image = QImage(iconPath); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + if ((image.width() > 0) && (image.height() > 0)) { + image = image.scaled(_virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize, Qt::KeepAspectRatio); + image = image.mirrored(); + + _virtualPadJumpBtnTexture = gpu::Texture::createStrict( + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + image.width(), image.height(), + gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + _virtualPadJumpBtnTexture->setSource("virtualPad jump"); + auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); + _virtualPadJumpBtnTexture->setUsage(usage.build()); + _virtualPadJumpBtnTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + _virtualPadJumpBtnTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + _virtualPadJumpBtnTexture->setAutoGenerateMips(true); + } #endif Parent::customizeContext(); } @@ -124,6 +147,20 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); }); + + // render stick head + auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(), + _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize); + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_cursorPipeline); + batch.setResourceTexture(0, _virtualPadJumpBtnTexture); + batch.resetViewTransform(); + batch.setModelTransform(jumpTransform); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); } #endif Parent::compositeExtra(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 26c48743b7..a061a4c923 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -46,5 +46,8 @@ private: gpu::TexturePointer _virtualPadStickTexture; gpu::TexturePointer _virtualPadStickBaseTexture; qreal _virtualPadPixelSize; + + gpu::TexturePointer _virtualPadJumpBtnTexture; + qreal _virtualPadJumpBtnPixelSize; #endif }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index c33b87e5cf..b61f24972a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -135,10 +135,8 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St template std::shared_ptr make_renderer(const EntityItemPointer& entity) { - T* rawResult = new T(entity); - // We want to use deleteLater so that renderer destruction gets pushed to the main thread - return std::shared_ptr(rawResult, std::bind(&QObject::deleteLater, rawResult)); + return std::shared_ptr(new T(entity), [](T* ptr) { ptr->deleteLater(); }); } EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _entity(entity) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index bd00ded12d..f31ed4e238 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -34,7 +34,7 @@ static const QString WEB_ENTITY_QML = "controls/WebEntityView.qml"; const float METERS_TO_INCHES = 39.3701f; static uint32_t _currentWebCount{ 0 }; -// Don't allow more than 100 concurrent web views +// Don't allow more than 20 concurrent web views static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 20; // If a web-view hasn't been rendered for 30 seconds, de-allocate the framebuffer static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND; @@ -88,8 +88,14 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe return true; } - if (uvec2(getWindowSize(entity)) != toGlm(_webSurface->size())) { - return true; + { + QSharedPointer webSurface; + withReadLock([&] { + webSurface = _webSurface; + }); + if (webSurface && uvec2(getWindowSize(entity)) != toGlm(webSurface->size())) { + return true; + } } if (_lastSourceUrl != entity->getSourceUrl()) { @@ -108,9 +114,15 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe } bool WebEntityRenderer::needsRenderUpdate() const { - if (!_webSurface) { - // If we have rendered recently, and there is no web surface, we're going to create one - return true; + { + QSharedPointer webSurface; + withReadLock([&] { + webSurface = _webSurface; + }); + if (!webSurface) { + // If we have rendered recently, and there is no web surface, we're going to create one + return true; + } } return Parent::needsRenderUpdate(); diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 0a28368e9e..957104bd30 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -41,6 +41,7 @@ bool TouchscreenVirtualPadDevice::isSupported() const { void TouchscreenVirtualPadDevice::init() { _fixedPosition = true; // This should be config + _viewTouchUpdateCount = 0; QScreen* eventScreen = qApp->primaryScreen(); if (_screenDPIProvided != eventScreen->physicalDotsPerInch()) { @@ -50,12 +51,14 @@ void TouchscreenVirtualPadDevice::init() { _screenDPIProvided = eventScreen->physicalDotsPerInch(); _screenDPI = eventScreen->physicalDotsPerInch(); - _fixedRadius = _screenDPI * 0.5f * VirtualPad::Manager::PIXEL_SIZE / VirtualPad::Manager::DPI; - _fixedRadiusForCalc = _fixedRadius - _screenDPI * VirtualPad::Manager::STICK_RADIUS / VirtualPad::Manager::DPI; + _fixedRadius = _screenDPI * 0.5f * VirtualPad::Manager::BASE_DIAMETER_PIXELS / VirtualPad::Manager::DPI; + _fixedRadiusForCalc = _fixedRadius - _screenDPI * VirtualPad::Manager::STICK_RADIUS_PIXELS / VirtualPad::Manager::DPI; + + _jumpButtonRadius = _screenDPI * VirtualPad::Manager::JUMP_BTN_TRIMMED_RADIUS_PIXELS / VirtualPad::Manager::DPI; } auto& virtualPadManager = VirtualPad::Manager::instance(); - setupFixedCenter(virtualPadManager, true); + setupControlsPositions(virtualPadManager, true); if (_fixedPosition) { virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled @@ -64,19 +67,23 @@ void TouchscreenVirtualPadDevice::init() { KeyboardMouseDevice::enableTouch(false); // Touch for view controls is managed by this plugin } -void TouchscreenVirtualPadDevice::setupFixedCenter(VirtualPad::Manager& virtualPadManager, bool force) { - if (!_fixedPosition) return; - - //auto& virtualPadManager = VirtualPad::Manager::instance(); +void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& virtualPadManager, bool force) { if (_extraBottomMargin == virtualPadManager.extraBottomMargin() && !force) return; // Our only criteria to decide a center change is the bottom margin - _extraBottomMargin = virtualPadManager.extraBottomMargin(); - float margin = _screenDPI * VirtualPad::Manager::BASE_MARGIN / VirtualPad::Manager::DPI; QScreen* eventScreen = qApp->primaryScreen(); // do not call every time - _fixedCenterPosition = glm::vec2( _fixedRadius + margin, eventScreen->size().height() - margin - _fixedRadius - _extraBottomMargin); + _extraBottomMargin = virtualPadManager.extraBottomMargin(); + // Movement stick + float margin = _screenDPI * VirtualPad::Manager::BASE_MARGIN_PIXELS / VirtualPad::Manager::DPI; + _fixedCenterPosition = glm::vec2( _fixedRadius + margin, eventScreen->size().height() - margin - _fixedRadius - _extraBottomMargin); _moveRefTouchPoint = _fixedCenterPosition; virtualPadManager.getLeftVirtualPad()->setFirstTouch(_moveRefTouchPoint); + + // Jump button + float leftMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_LEFT_MARGIN_PIXELS / VirtualPad::Manager::DPI; + float bottomMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_BOTTOM_MARGIN_PIXELS/ VirtualPad::Manager::DPI; + _jumpButtonPosition = glm::vec2( _jumpButtonRadius + leftMargin, eventScreen->size().height() - bottomMargin - _jumpButtonRadius - _extraBottomMargin); + virtualPadManager.setJumpButtonPosition(_jumpButtonPosition); } float clip(float n, float lower, float upper) { @@ -131,22 +138,15 @@ void TouchscreenVirtualPadDevice::processInputDeviceForMove(VirtualPad::Manager& } void TouchscreenVirtualPadDevice::processInputDeviceForView() { - float rightDistanceScaleX, rightDistanceScaleY; - rightDistanceScaleX = (_viewCurrentTouchPoint.x - _viewRefTouchPoint.x) / _screenDPIScale.x; - rightDistanceScaleY = (_viewCurrentTouchPoint.y - _viewRefTouchPoint.y) / _screenDPIScale.y; - - rightDistanceScaleX = clip(rightDistanceScaleX, -_viewStickRadiusInches, _viewStickRadiusInches); - rightDistanceScaleY = clip(rightDistanceScaleY, -_viewStickRadiusInches, _viewStickRadiusInches); - - // NOW BETWEEN -1 1 - rightDistanceScaleX /= _viewStickRadiusInches; - rightDistanceScaleY /= _viewStickRadiusInches; - - _inputDevice->_axisStateMap[controller::RX] = rightDistanceScaleX; - _inputDevice->_axisStateMap[controller::RY] = rightDistanceScaleY; + // We use average across how many times we've got touchUpdate events. + // Using the average instead of the full deltaX and deltaY, makes deltaTime in MyAvatar dont't accelerate rotation when there is a low touchUpdate rate (heavier domains). + // (Because it multiplies this input value by deltaTime (with a coefficient)). + _inputDevice->_axisStateMap[controller::RX] = _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.x - _viewRefTouchPoint.x) / _viewTouchUpdateCount; + _inputDevice->_axisStateMap[controller::RY] = _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.y - _viewRefTouchPoint.y) / _viewTouchUpdateCount; // after use, save last touch point as ref _viewRefTouchPoint = _viewCurrentTouchPoint; + _viewTouchUpdateCount = 0; } void TouchscreenVirtualPadDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { @@ -156,7 +156,7 @@ void TouchscreenVirtualPadDevice::pluginUpdate(float deltaTime, const controller }); auto& virtualPadManager = VirtualPad::Manager::instance(); - setupFixedCenter(virtualPadManager); + setupControlsPositions(virtualPadManager); if (_moveHasValidTouch) { processInputDeviceForMove(virtualPadManager); @@ -221,6 +221,7 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { if (!virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { moveTouchEnd(); viewTouchEnd(); + jumpTouchEnd(); return; } // touch end here is a big reset -> resets both pads @@ -229,7 +230,9 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { debugPoints(event, " END ----------------"); moveTouchEnd(); viewTouchEnd(); + jumpTouchEnd(); _inputDevice->_axisStateMap.clear(); + _inputDevice->_buttonPressedMap.clear(); } void TouchscreenVirtualPadDevice::processUnusedTouches(std::map unusedTouchesInEvent) { @@ -263,9 +266,11 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { const QList& tPoints = event->touchPoints(); bool moveTouchFound = false; bool viewTouchFound = false; + bool jumpTouchFound = false; int idxMoveStartingPointCandidate = -1; int idxViewStartingPointCandidate = -1; + int idxJumpStartingPointCandidate = -1; glm::vec2 thisPoint; int thisPointId; @@ -290,6 +295,13 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } + if (!jumpTouchFound && _jumpHasValidTouch && _jumpCurrentTouchId == thisPointId) { + // valid if it's an ongoing touch + jumpTouchFound = true; + jumpTouchUpdate(thisPoint); + continue; + } + if (!moveTouchFound && idxMoveStartingPointCandidate == -1 && moveTouchBeginIsValid(thisPoint) && (!_unusedTouches.count(thisPointId) || _unusedTouches[thisPointId] == MOVE )) { idxMoveStartingPointCandidate = i; @@ -302,8 +314,16 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { continue; } + if (!jumpTouchFound && idxJumpStartingPointCandidate == -1 && jumpTouchBeginIsValid(thisPoint) && + (!_unusedTouches.count(thisPointId) || _unusedTouches[thisPointId] == JUMP )) { + idxJumpStartingPointCandidate = i; + continue; + } + if (moveTouchBeginIsValid(thisPoint)) { unusedTouchesInEvent[thisPointId] = MOVE; + } else if (jumpTouchBeginIsValid(thisPoint)) { + unusedTouchesInEvent[thisPointId] = JUMP; } else if (viewTouchBeginIsValid(thisPoint)) { unusedTouchesInEvent[thisPointId] = VIEW; } @@ -330,23 +350,58 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { viewTouchEnd(); } } + if (!jumpTouchFound) { + if (idxJumpStartingPointCandidate != -1) { + _jumpCurrentTouchId = tPoints[idxJumpStartingPointCandidate].id(); + _unusedTouches.erase(_jumpCurrentTouchId); + jumpTouchBegin(thisPoint); + } else { + if (_jumpHasValidTouch) { + jumpTouchEnd(); + } + } + } } bool TouchscreenVirtualPadDevice::viewTouchBeginIsValid(glm::vec2 touchPoint) { - return !moveTouchBeginIsValid(touchPoint); + return !moveTouchBeginIsValid(touchPoint) && !jumpTouchBeginIsValid(touchPoint); } bool TouchscreenVirtualPadDevice::moveTouchBeginIsValid(glm::vec2 touchPoint) { if (_fixedPosition) { // inside circle - return pow(touchPoint.x - _fixedCenterPosition.x,2.0) + pow(touchPoint.y - _fixedCenterPosition.y, 2.0) < pow(_fixedRadius, 2.0); + return glm::distance2(touchPoint, _fixedCenterPosition) < _fixedRadius * _fixedRadius; } else { // left side return touchPoint.x < _screenWidthCenter; } } +bool TouchscreenVirtualPadDevice::jumpTouchBeginIsValid(glm::vec2 touchPoint) { + // position of button and boundaries + return glm::distance2(touchPoint, _jumpButtonPosition) < _jumpButtonRadius * _jumpButtonRadius; +} + +void TouchscreenVirtualPadDevice::jumpTouchBegin(glm::vec2 touchPoint) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { + _jumpHasValidTouch = true; + + _inputDevice->_buttonPressedMap.insert(TouchButtonChannel::JUMP_BUTTON_PRESS); + } +} + +void TouchscreenVirtualPadDevice::jumpTouchUpdate(glm::vec2 touchPoint) {} + +void TouchscreenVirtualPadDevice::jumpTouchEnd() { + if (_jumpHasValidTouch) { + _jumpHasValidTouch = false; + + _inputDevice->_buttonPressedMap.erase(TouchButtonChannel::JUMP_BUTTON_PRESS); + } +} + void TouchscreenVirtualPadDevice::moveTouchBegin(glm::vec2 touchPoint) { auto& virtualPadManager = VirtualPad::Manager::instance(); if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { @@ -376,12 +431,14 @@ void TouchscreenVirtualPadDevice::viewTouchBegin(glm::vec2 touchPoint) { if (virtualPadManager.isEnabled() && !virtualPadManager.isHidden()) { _viewRefTouchPoint = touchPoint; _viewCurrentTouchPoint = touchPoint; + _viewTouchUpdateCount++; _viewHasValidTouch = true; } } void TouchscreenVirtualPadDevice::viewTouchUpdate(glm::vec2 touchPoint) { _viewCurrentTouchPoint = touchPoint; + _viewTouchUpdateCount++; } void TouchscreenVirtualPadDevice::viewTouchEnd() { @@ -403,13 +460,22 @@ void TouchscreenVirtualPadDevice::touchGestureEvent(const QGestureEvent* event) } } +controller::Input TouchscreenVirtualPadDevice::InputDevice::makeInput(TouchscreenVirtualPadDevice::TouchAxisChannel axis) const { + return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); +} + +controller::Input TouchscreenVirtualPadDevice::InputDevice::makeInput(TouchscreenVirtualPadDevice::TouchButtonChannel button) const { + return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); +} + controller::Input::NamedVector TouchscreenVirtualPadDevice::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ - makePair(LX, "LX"), - makePair(LY, "LY"), - makePair(RX, "RX"), - makePair(RY, "RY") + Input::NamedPair(makeInput(TouchAxisChannel::LX), "LX"), + Input::NamedPair(makeInput(TouchAxisChannel::LY), "LY"), + Input::NamedPair(makeInput(TouchAxisChannel::RX), "RX"), + Input::NamedPair(makeInput(TouchAxisChannel::RY), "RY"), + Input::NamedPair(makeInput(TouchButtonChannel::JUMP_BUTTON_PRESS), "JUMP_BUTTON_PRESS") }; return availableInputs; } diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h index 3540c6d909..212b7633ec 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -41,6 +41,18 @@ public: static const char* NAME; + int _viewTouchUpdateCount; + enum TouchAxisChannel { + LX, + LY, + RX, + RY + }; + + enum TouchButtonChannel { + JUMP_BUTTON_PRESS + }; + protected: class InputDevice : public controller::InputDevice { @@ -54,6 +66,9 @@ protected: virtual void focusOutEvent() override; friend class TouchscreenVirtualPadDevice; + + controller::Input makeInput(TouchAxisChannel axis) const; + controller::Input makeInput(TouchButtonChannel button) const; }; public: @@ -63,7 +78,8 @@ protected: enum TouchType { MOVE = 1, - VIEW + VIEW, + JUMP }; float _lastPinchScale; @@ -82,6 +98,9 @@ protected: glm::vec2 _viewCurrentTouchPoint; int _viewCurrentTouchId; + bool _jumpHasValidTouch; + int _jumpCurrentTouchId; + std::map _unusedTouches; int _touchPointCount; @@ -94,7 +113,8 @@ protected: float _fixedRadiusForCalc; int _extraBottomMargin {0}; - float _viewStickRadiusInches {0.1333f}; // agreed default + glm::vec2 _jumpButtonPosition; + float _jumpButtonRadius; void moveTouchBegin(glm::vec2 touchPoint); void moveTouchUpdate(glm::vec2 touchPoint); @@ -106,7 +126,12 @@ protected: void viewTouchEnd(); bool viewTouchBeginIsValid(glm::vec2 touchPoint); - void setupFixedCenter(VirtualPad::Manager& virtualPadManager, bool force = false); + void jumpTouchBegin(glm::vec2 touchPoint); + void jumpTouchUpdate(glm::vec2 touchPoint); + void jumpTouchEnd(); + bool jumpTouchBeginIsValid(glm::vec2 touchPoint); + + void setupControlsPositions(VirtualPad::Manager& virtualPadManager, bool force = false); void processInputDeviceForMove(VirtualPad::Manager& virtualPadManager); glm::vec2 clippedPointInCircle(float radius, glm::vec2 origin, glm::vec2 touchPoint); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 7d7c2e682b..3c24cc796c 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include "AddressManager.h" #include "NodeList.h" @@ -77,6 +76,17 @@ QUrl AddressManager::currentShareableAddress(bool domainOnly) const { } } +QUrl AddressManager::currentPublicAddress(bool domainOnly) const { + // return an address that can be used by others to visit this client's current location. If + // in a serverless domain (which can't be visited) return an empty URL. + QUrl shareableAddress = currentShareableAddress(domainOnly); + if (shareableAddress.scheme() != URL_SCHEME_HIFI) { + return QUrl(); // file: urls aren't public + } + return shareableAddress; +} + + QUrl AddressManager::currentFacingShareableAddress() const { auto hifiURL = currentShareableAddress(); if (hifiURL.scheme() == URL_SCHEME_HIFI) { @@ -86,6 +96,17 @@ QUrl AddressManager::currentFacingShareableAddress() const { return hifiURL; } +QUrl AddressManager::currentFacingPublicAddress() const { + // return an address that can be used by others to visit this client's current location. If + // in a serverless domain (which can't be visited) return an empty URL. + QUrl shareableAddress = currentFacingShareableAddress(); + if (shareableAddress.scheme() != URL_SCHEME_HIFI) { + return QUrl(); // file: urls aren't public + } + return shareableAddress; +} + + void AddressManager::loadSettings(const QString& lookupString) { #if defined(USE_GLES) && defined(Q_OS_WIN) handleUrl(QUrl("hifi://127.0.0.0"), LookupTrigger::StartupFromSettings); @@ -288,8 +309,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { // lookupUrl.scheme() == URL_SCHEME_HTTP || // lookupUrl.scheme() == URL_SCHEME_HTTPS || _previousLookup.clear(); - QUrl domainURL = PathUtils::expandToLocalDataAbsolutePath(lookupUrl); - setDomainInfo(domainURL, trigger); + _shareablePlaceName.clear(); + setDomainInfo(lookupUrl, trigger); emit lookupResultsFinished(); handlePath(DOMAIN_SPAWNING_POINT, LookupTrigger::Internal, false); return true; @@ -747,14 +768,6 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16 return false; } -QString AddressManager::getHost() const { - if (isPossiblePlaceName(_domainURL.host())) { - return QString(); - } - - return _domainURL.host(); -} - bool AddressManager::setDomainInfo(const QUrl& domainURL, LookupTrigger trigger) { const QString hostname = domainURL.host(); quint16 port = domainURL.port(); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index dc1046bf51..b42aec2771 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -150,7 +150,9 @@ public: QUrl currentAddress(bool domainOnly = false) const; QUrl currentFacingAddress() const; QUrl currentShareableAddress(bool domainOnly = false) const; + QUrl currentPublicAddress(bool domainOnly = false) const; QUrl currentFacingShareableAddress() const; + QUrl currentFacingPublicAddress() const; QString currentPath(bool withOrientation = true) const; QString currentFacingPath() const; @@ -158,7 +160,7 @@ public: QString getPlaceName() const; QString getDomainID() const; - QString getHost() const; + QString getHost() const { return _domainURL.host(); } void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; } void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; } diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 7a5ecb2602..c20d6d73be 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -9,8 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainHandler.h" + #include +#include + #include #include @@ -25,8 +29,6 @@ #include "UserActivityLogger.h" #include "NetworkLogging.h" -#include "DomainHandler.h" - DomainHandler::DomainHandler(QObject* parent) : QObject(parent), _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), @@ -157,6 +159,11 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { if (domainURL.scheme() != URL_SCHEME_HIFI) { _sockAddr.clear(); + + // if this is a file URL we need to see if it has a ~ for us to expand + if (domainURL.scheme() == URL_SCHEME_FILE) { + domainURL = PathUtils::expandToLocalDataAbsolutePath(domainURL); + } } if (_domainURL != domainURL || _sockAddr.getPort() != domainURL.port()) { diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 7c5b7eb45c..e6c28f75e8 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -192,17 +192,12 @@ bool OctreePersistThread::process() { QString lockFileName = _filename + ".lock"; std::ifstream lockFile(qPrintable(lockFileName), std::ios::in | std::ios::binary | std::ios::ate); if (lockFile.is_open()) { - qCDebug(octree) << "WARNING: Octree lock file detected at startup:" << lockFileName - << "-- Attempting to restore from previous backup file."; - - // This is where we should attempt to find the most recent backup and restore from - // that file as our persist file. - restoreFromMostRecentBackup(); + qCDebug(octree) << "WARNING: Octree lock file detected at startup:" << lockFileName; lockFile.close(); - qCDebug(octree) << "Loading Octree... lock file closed:" << lockFileName; + qCDebug(octree) << "Removing lock file:" << lockFileName; remove(qPrintable(lockFileName)); - qCDebug(octree) << "Loading Octree... lock file removed:" << lockFileName; + qCDebug(octree) << "Lock file removed:" << lockFileName; } persistentFileRead = _tree->readFromFile(qPrintable(_filename.toLocal8Bit())); diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index d66f0f1dab..d593169d94 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -37,9 +37,8 @@ static const int MIN_TIMER_MS = 5; using namespace hifi::qml; using namespace hifi::qml::impl; -TextureCache offscreenTextures; - TextureCache& SharedObject::getTextureCache() { + static TextureCache offscreenTextures; return offscreenTextures; } @@ -243,7 +242,7 @@ void SharedObject::releaseTextureAndFence() { QMutexLocker lock(&_mutex); // If the most recent texture was unused, we can directly recycle it if (_latestTextureAndFence.first) { - offscreenTextures.releaseTexture(_latestTextureAndFence); + getTextureCache().releaseTexture(_latestTextureAndFence); _latestTextureAndFence = TextureAndFence{ 0, 0 }; } } @@ -307,7 +306,10 @@ bool SharedObject::preRender() { void SharedObject::shutdownRendering(OffscreenGLCanvas& canvas, const QSize& size) { QMutexLocker locker(&_mutex); if (size != QSize(0, 0)) { - offscreenTextures.releaseSize(size); + getTextureCache().releaseSize(size); + if (_latestTextureAndFence.first) { + getTextureCache().releaseTexture(_latestTextureAndFence); + } } _renderControl->invalidate(); canvas.doneCurrent(); @@ -403,7 +405,7 @@ void SharedObject::onRender() { } void SharedObject::onTimer() { - offscreenTextures.report(); + getTextureCache().report(); if (!_renderRequested) { return; } @@ -436,7 +438,7 @@ void SharedObject::updateTextureAndFence(const TextureAndFence& newTextureAndFen QMutexLocker locker(&_mutex); // If the most recent texture was unused, we can directly recycle it if (_latestTextureAndFence.first) { - offscreenTextures.releaseTexture(_latestTextureAndFence); + getTextureCache().releaseTexture(_latestTextureAndFence); _latestTextureAndFence = { 0, 0 }; } diff --git a/libraries/qml/src/qml/impl/TextureCache.cpp b/libraries/qml/src/qml/impl/TextureCache.cpp index c649a36594..7af8fa1ac9 100644 --- a/libraries/qml/src/qml/impl/TextureCache.cpp +++ b/libraries/qml/src/qml/impl/TextureCache.cpp @@ -11,10 +11,6 @@ using namespace hifi::qml::impl; -#if defined(Q_OS_ANDROID) -#define USE_GLES 1 -#endif - uint64_t uvec2ToUint64(const QSize& size) { uint64_t result = size.width(); result <<= 32; @@ -31,26 +27,23 @@ void TextureCache::acquireSize(const QSize& size) { void TextureCache::releaseSize(const QSize& size) { auto sizeKey = uvec2ToUint64(size); - ValueList texturesToDelete; { Lock lock(_mutex); assert(_textures.count(sizeKey)); auto& textureSet = _textures[sizeKey]; if (0 == --textureSet.clientCount) { - texturesToDelete.swap(textureSet.returnedTextures); + for (const auto& textureAndFence : textureSet.returnedTextures) { + destroy(textureAndFence); + } _textures.erase(sizeKey); } } - for (const auto& textureAndFence : texturesToDelete) { - destroy(textureAndFence); - } } uint32_t TextureCache::acquireTexture(const QSize& size) { Lock lock(_mutex); recycle(); - ++_activeTextureCount; auto sizeKey = uvec2ToUint64(size); assert(_textures.count(sizeKey)); @@ -83,7 +76,12 @@ void TextureCache::report() { } size_t TextureCache::getUsedTextureMemory() { - return _totalTextureUsage; + size_t toReturn; + { + Lock lock(_mutex); + toReturn = _totalTextureUsage; + } + return toReturn; } size_t TextureCache::getMemoryForSize(const QSize& size) { @@ -122,8 +120,6 @@ uint32_t TextureCache::createTexture(const QSize& size) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); #if !defined(USE_GLES) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.2f); #endif diff --git a/libraries/qml/src/qml/impl/TextureCache.h b/libraries/qml/src/qml/impl/TextureCache.h index 572e1cadea..c146d0bdbf 100644 --- a/libraries/qml/src/qml/impl/TextureCache.h +++ b/libraries/qml/src/qml/impl/TextureCache.h @@ -41,7 +41,6 @@ public: ValueList returnedTextures; }; - void releaseSize(const QSize& size); void acquireSize(const QSize& size); uint32_t acquireTexture(const QSize& size); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ef4b0a5683..a3abb24afe 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -32,6 +32,7 @@ #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" #include "model_translucent_vert.h" +#include "model_translucent_normal_map_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" #include "skin_model_fade_dq_vert.h" @@ -68,11 +69,13 @@ #include "model_lightmap_normal_map_frag.h" #include "model_translucent_frag.h" #include "model_translucent_unlit_frag.h" +#include "model_translucent_normal_map_frag.h" #include "model_lightmap_fade_frag.h" #include "model_lightmap_normal_map_fade_frag.h" #include "model_translucent_fade_frag.h" #include "model_translucent_unlit_fade_frag.h" +#include "model_translucent_normal_map_fade_frag.h" #include "overlay3D_vert.h" #include "overlay3D_frag.h" @@ -187,6 +190,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelLightmapVertex = model_lightmap_vert::getShader(); auto modelLightmapNormalMapVertex = model_lightmap_normal_map_vert::getShader(); auto modelTranslucentVertex = model_translucent_vert::getShader(); + auto modelTranslucentNormalMapVertex = model_translucent_normal_map_vert::getShader(); auto modelShadowVertex = model_shadow_vert::getShader(); auto modelLightmapFadeVertex = model_lightmap_fade_vert::getShader(); @@ -227,6 +231,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelNormalMapPixel = model_normal_map_frag::getShader(); auto modelTranslucentPixel = model_translucent_frag::getShader(); auto modelTranslucentUnlitPixel = model_translucent_unlit_frag::getShader(); + auto modelTranslucentNormalMapPixel = model_translucent_normal_map_frag::getShader(); auto modelShadowPixel = model_shadow_frag::getShader(); auto modelLightmapPixel = model_lightmap_frag::getShader(); auto modelLightmapNormalMapPixel = model_lightmap_normal_map_frag::getShader(); @@ -239,6 +244,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelShadowFadePixel = model_shadow_fade_frag::getShader(); auto modelTranslucentFadePixel = model_translucent_fade_frag::getShader(); auto modelTranslucentUnlitFadePixel = model_translucent_unlit_fade_frag::getShader(); + auto modelTranslucentNormalMapFadePixel = model_translucent_normal_map_fade_frag::getShader(); auto simpleFadePixel = simple_textured_fade_frag::getShader(); auto simpleUnlitFadePixel = simple_textured_unlit_fade_frag::getShader(); auto simpleTranslucentFadePixel = simple_transparent_textured_fade_frag::getShader(); @@ -296,7 +302,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), @@ -316,7 +322,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), @@ -358,14 +364,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); // dual quaternion skinned addPipeline( @@ -388,14 +394,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withFade(), skinModelFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); // Depth-only addPipeline( diff --git a/libraries/ui/src/VirtualPadManager.cpp b/libraries/ui/src/VirtualPadManager.cpp index cb3ef20e67..c786110bdf 100644 --- a/libraries/ui/src/VirtualPadManager.cpp +++ b/libraries/ui/src/VirtualPadManager.cpp @@ -35,9 +35,13 @@ namespace VirtualPad { } const float Manager::DPI = 534.0f; - const float Manager::PIXEL_SIZE = 512.0f; - const float Manager::STICK_RADIUS = 105.0f; - const float Manager::BASE_MARGIN = 59.0f; + const float Manager::BASE_DIAMETER_PIXELS = 512.0f; + const float Manager::BASE_MARGIN_PIXELS = 59.0f; + const float Manager::STICK_RADIUS_PIXELS = 105.0f; + const float Manager::JUMP_BTN_TRIMMED_RADIUS_PIXELS = 67.0f; + const float Manager::JUMP_BTN_FULL_PIXELS = 134.0f; + const float Manager::JUMP_BTN_BOTTOM_MARGIN_PIXELS = 67.0f; + const float Manager::JUMP_BTN_LEFT_MARGIN_PIXELS = 547.0f; Manager::Manager() { @@ -72,6 +76,14 @@ namespace VirtualPad { _extraBottomMargin = margin; } + glm::vec2 Manager::getJumpButtonPosition() { + return _jumpButtonPosition; + } + + void Manager::setJumpButtonPosition(glm::vec2 point) { + _jumpButtonPosition = point; + } + Instance* Manager::getLeftVirtualPad() { return &_leftVPadInstance; } diff --git a/libraries/ui/src/VirtualPadManager.h b/libraries/ui/src/VirtualPadManager.h index 6b68af3acd..68b3d4f10f 100644 --- a/libraries/ui/src/VirtualPadManager.h +++ b/libraries/ui/src/VirtualPadManager.h @@ -44,16 +44,23 @@ namespace VirtualPad { void hide(bool hide); int extraBottomMargin(); void setExtraBottomMargin(int margin); + glm::vec2 getJumpButtonPosition(); + void setJumpButtonPosition(glm::vec2 point); static const float DPI; - static const float PIXEL_SIZE; - static const float STICK_RADIUS; - static const float BASE_MARGIN; + static const float BASE_DIAMETER_PIXELS; + static const float BASE_MARGIN_PIXELS; + static const float STICK_RADIUS_PIXELS; + static const float JUMP_BTN_TRIMMED_RADIUS_PIXELS; + static const float JUMP_BTN_FULL_PIXELS; + static const float JUMP_BTN_BOTTOM_MARGIN_PIXELS; + static const float JUMP_BTN_LEFT_MARGIN_PIXELS; private: Instance _leftVPadInstance; bool _enabled; bool _hidden; + glm::vec2 _jumpButtonPosition; int _extraBottomMargin {0}; }; } diff --git a/scripts/developer/utilities/render/debugHighlight.js b/scripts/developer/utilities/render/debugHighlight.js index c2173f6e2a..664af836a9 100644 --- a/scripts/developer/utilities/render/debugHighlight.js +++ b/scripts/developer/utilities/render/debugHighlight.js @@ -157,7 +157,7 @@ }) function cleanup() { - Pointers.removePointer(ray); + Pointers.removePointer(laser); Selection.disableListHighlight(HoveringList) Selection.removeListFromMap(HoveringList) diff --git a/scripts/system/help.js b/scripts/system/help.js index e29fc59e59..aaeb82721c 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -40,7 +40,7 @@ } function onScreenChanged(type, url) { - onHelpScreen = type === "Web" && url.startsWith(HELP_URL); + onHelpScreen = type === "Web" && (url.indexOf(HELP_URL) === 0); button.editProperties({ isActive: onHelpScreen }); } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index ae8ef52a15..658d1c3ced 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -411,8 +411,6 @@ function snapshotUploaded(isError, reply) { } else { print('Ignoring snapshotUploaded() callback for stale ' + (isGif ? 'GIF' : 'Still' ) + ' snapshot. Stale story ID:', storyID); } - } else { - print(reply); } isUploadingPrintableStill = false; } diff --git a/tools/bake-tools/bake.py b/tools/bake-tools/bake.py index 0c8d5e1048..cad638c911 100644 --- a/tools/bake-tools/bake.py +++ b/tools/bake-tools/bake.py @@ -1,6 +1,16 @@ import os, json, sys, shutil, subprocess, shlex, time EXE = os.environ['HIFI_OVEN'] +def getRelativePath(path1, path2, stop): + parts1 = path1.split('/'); + parts2 = path2.split('/'); + if len(parts1) <= len(parts2): + for part in parts1: + if part != stop and part != '': + index = parts2.index(part) + parts2.pop(index) + return os.path.join(*parts2) + def listFiles(directory, extension): items = os.listdir(directory) fileList = [] @@ -44,18 +54,20 @@ def bakeFile(filePath, outputDirectory): groupKTXFiles(outputDirectory, bakedFile) def bakeFilesInDirectory(directory, outputDirectory): + rootDirectory = os.path.basename(os.path.normpath(directory)) for root, subFolders, filenames in os.walk(directory): for filename in filenames: + appendPath = getRelativePath(directory, root, rootDirectory); if filename.endswith('.fbx'): filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) - outputFolder = os.path.join(outputDirectory, os.path.relpath(root)) + outputFolder = os.path.join(outputDirectory, appendPath) print "Baking file: " + filename bakeFile(absFilePath, outputFolder) else: filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) - outputFolder = os.path.join(outputDirectory, os.path.relpath(root)) + outputFolder = os.path.join(outputDirectory, appendPath) newFilePath = os.sep.join([outputFolder, filename]) createDirectory(outputFolder) print "moving file: " + filename + " to: " + outputFolder