diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt
index f2690e0a7d..7bf6f05d9f 100644
--- a/cmake/externals/quazip/CMakeLists.txt
+++ b/cmake/externals/quazip/CMakeLists.txt
@@ -41,6 +41,9 @@ if (APPLE)
elseif (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library")
+elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml
index 8e7db44b7d..943f15e1de 100644
--- a/interface/resources/qml/controls/FlickableWebViewCore.qml
+++ b/interface/resources/qml/controls/FlickableWebViewCore.qml
@@ -21,6 +21,7 @@ Item {
signal newViewRequestedCallback(var request)
signal loadingChangedCallback(var loadRequest)
+
width: parent.width
property bool interactive: false
@@ -29,6 +30,10 @@ Item {
id: hifi
}
+ function stop() {
+ webViewCore.stop();
+ }
+
function unfocus() {
webViewCore.runJavaScript("if (document.activeElement) document.activeElement.blur();", function(result) {
console.log('unfocus completed: ', result);
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index 931c64e1ef..71bf69fdc8 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -21,6 +21,10 @@ Item {
property bool passwordField: false
property alias flickable: webroot.interactive
+ function stop() {
+ webroot.stop();
+ }
+
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
// or provide HMDinfo object to QML in RenderableWebEntityItem and do the following.
/*
diff --git a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
index b1b6de4644..aadd7c88ae 100644
--- a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
@@ -254,7 +254,7 @@ ModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml
index 008ed5b860..0c86b93c4b 100644
--- a/interface/resources/qml/dialogs/CustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml
@@ -254,7 +254,7 @@ ModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
index 623388e9b3..81a2c5c1e0 100644
--- a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
@@ -282,7 +282,7 @@ TabletModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index 08e3e7a552..6b48f8d51d 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -124,6 +124,14 @@ Rectangle {
root.numUpdatesAvailable = result.data.updates.length;
}
}
+
+ onAppInstalled: {
+ root.installedApps = Commerce.getInstalledApps();
+ }
+
+ onAppUninstalled: {
+ root.installedApps = Commerce.getInstalledApps();
+ }
}
Timer {
@@ -249,6 +257,145 @@ Rectangle {
Commerce.getWalletStatus();
}
}
+
+ Item {
+ id: installedAppsContainer;
+ z: 998;
+ visible: false;
+ anchors.top: titleBarContainer.bottom;
+ anchors.topMargin: -titleBarContainer.additionalDropdownHeight;
+ anchors.left: parent.left;
+ anchors.bottom: parent.bottom;
+ width: parent.width;
+
+ RalewayRegular {
+ id: installedAppsHeader;
+ anchors.top: parent.top;
+ anchors.topMargin: 10;
+ anchors.left: parent.left;
+ anchors.leftMargin: 12;
+ height: 80;
+ width: paintedWidth;
+ text: "All Installed Marketplace Apps";
+ color: hifi.colors.black;
+ size: 22;
+ }
+
+ ListView {
+ id: installedAppsList;
+ clip: true;
+ model: installedAppsModel;
+ snapMode: ListView.SnapToItem;
+ // Anchors
+ anchors.top: installedAppsHeader.bottom;
+ anchors.left: parent.left;
+ anchors.bottom: sideloadAppButton.top;
+ width: parent.width;
+ delegate: Item {
+ width: parent.width;
+ height: 40;
+
+ RalewayRegular {
+ text: model.appUrl;
+ // Text size
+ size: 16;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.leftMargin: 12;
+ height: parent.height;
+ anchors.right: sideloadAppOpenButton.left;
+ anchors.rightMargin: 8;
+ elide: Text.ElideRight;
+ // Style
+ color: hifi.colors.black;
+ // Alignment
+ verticalAlignment: Text.AlignVCenter;
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: {
+ Window.copyToClipboard((model.appUrl).slice(0, -9));
+ }
+ }
+ }
+
+ HifiControlsUit.Button {
+ id: sideloadAppOpenButton;
+ text: "OPEN";
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: parent.top;
+ anchors.topMargin: 2;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 2;
+ anchors.right: uninstallGlyph.left;
+ anchors.rightMargin: 8;
+ width: 80;
+ onClicked: {
+ Commerce.openApp(model.appUrl);
+ }
+ }
+
+ HiFiGlyphs {
+ id: uninstallGlyph;
+ text: hifi.glyphs.close;
+ color: hifi.colors.black;
+ size: 22;
+ anchors.top: parent.top;
+ anchors.right: parent.right;
+ anchors.rightMargin: 6;
+ width: 35;
+ height: parent.height;
+ horizontalAlignment: Text.AlignHCenter;
+ MouseArea {
+ anchors.fill: parent;
+ hoverEnabled: true;
+ onEntered: {
+ parent.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ parent.text = hifi.glyphs.close;
+ }
+ onClicked: {
+ Commerce.uninstallApp(model.appUrl);
+ }
+ }
+ }
+ }
+ }
+ HifiControlsUit.Button {
+ id: sideloadAppButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 8;
+ anchors.left: parent.left;
+ anchors.leftMargin: 8;
+ anchors.right: closeAppListButton.left;
+ anchors.rightMargin: 8;
+ height: 40;
+ text: "SIDELOAD APP FROM LOCAL DISK";
+ onClicked: {
+ Window.browseChanged.connect(onFileOpenChanged);
+ Window.browseAsync("Locate your app's .app.json file", "", "*.app.json");
+ }
+ }
+ HifiControlsUit.Button {
+ id: closeAppListButton;
+ color: hifi.buttons.white;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 8;
+ anchors.right: parent.right;
+ anchors.rightMargin: 8;
+ width: 100;
+ height: 40;
+ text: "BACK";
+ onClicked: {
+ installedAppsContainer.visible = false;
+ }
+ }
+ }
HifiWallet.NeedsLogIn {
id: needsLogIn;
@@ -317,7 +464,7 @@ Rectangle {
//
Item {
id: purchasesContentsContainer;
- visible: root.activeView === "purchasesMain";
+ visible: root.activeView === "purchasesMain" && !installedAppsList.visible;
// Anchors
anchors.left: parent.left;
anchors.right: parent.right;
@@ -959,6 +1106,39 @@ Rectangle {
}
}
+ Keys.onPressed: {
+ if ((event.key == Qt.Key_F) && (event.modifiers & Qt.ControlModifier)) {
+ installedAppsContainer.visible = !installedAppsContainer.visible;
+ console.log("User changed visibility of installedAppsContainer to " + installedAppsContainer.visible);
+ }
+ }
+ function onFileOpenChanged(filename) {
+ // disconnect the event, otherwise the requests will stack up
+ try { // Not all calls to onFileOpenChanged() connect an event.
+ Window.browseChanged.disconnect(onFileOpenChanged);
+ } catch (e) {
+ console.log('Purchases.qml ignoring', e);
+ }
+ if (filename) {
+ Commerce.installApp(filename);
+ }
+ }
+ ListModel {
+ id: installedAppsModel;
+ }
+ onInstalledAppsChanged: {
+ installedAppsModel.clear();
+ var installedAppsArray = root.installedApps.split(",");
+ var installedAppsObject = [];
+ // "- 1" because the last app string ends with ","
+ for (var i = 0; i < installedAppsArray.length - 1; i++) {
+ installedAppsObject[i] = {
+ "appUrl": installedAppsArray[i]
+ }
+ }
+ installedAppsModel.append(installedAppsObject);
+ }
+
//
// Function Name: fromScript()
//
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index c38caca090..cd4562da54 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -145,6 +145,16 @@
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include "AudioClient.h"
#include "audio/AudioScope.h"
#include "avatar/AvatarManager.h"
@@ -1060,6 +1070,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
if (steamClient) {
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
}
+ setCrashAnnotation("steam", property(hifi::properties::STEAM).toBool() ? "1" : "0");
+
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION;
qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION;
@@ -1145,6 +1157,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
const DomainHandler& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
+ connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){
+ setCrashAnnotation("domain", domainURL.toString().toStdString());
+ });
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
@@ -1190,6 +1205,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
auto dialogsManager = DependencyManager::get();
connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
+ connect(accountManager.data(), &AccountManager::usernameChanged, [](QString username){
+ setCrashAnnotation("username", username.toStdString());
+ });
// set the account manager's root URL and trigger a login request if we don't have the access token
accountManager->setIsAgent(true);
@@ -1207,6 +1225,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount);
connect(this, &Application::activeDisplayPluginChanged, this, [](){
qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode());
+ auto displayPlugin = qApp->getActiveDisplayPlugin();
+ setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString());
+ setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
});
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode);
@@ -1214,6 +1235,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(myAvatar.get(), &MyAvatar::positionGoneTo,
DependencyManager::get().data(), &AddressManager::storeCurrentAddress);
+ connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, [](){
+ QUrl avatarURL = qApp->getMyAvatar()->getSkeletonModelURL();
+ setCrashAnnotation("avatar", avatarURL.toString().toStdString());
+ });
+
+
// Inititalize sample before registering
_sampleSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/sample.wav"));
@@ -1306,6 +1333,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Needs to happen AFTER the render engine initialization to access its configuration
initializeUi();
+ updateVerboseLogging();
+
init();
qCDebug(interfaceapp, "init() complete.");
@@ -1376,6 +1405,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
userActivityLogger.disable(false);
}
+ QString machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
+
if (userActivityLogger.isEnabled()) {
// sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
// The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
@@ -1425,11 +1456,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["first_run"] = firstRun.get();
// add the user's machine ID to the launch event
- properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
+ properties["machine_fingerprint"] = machineFingerPrint;
userActivityLogger.logAction("launch", properties);
}
+ setCrashAnnotation("machine_fingerprint", machineFingerPrint.toStdString());
+
_entityEditSender.setMyAvatar(myAvatar.get());
// The entity octree will have to know about MyAvatar for the parentJointName import
@@ -2174,6 +2207,46 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
}
+void Application::updateVerboseLogging() {
+ bool enable = Menu::getInstance()->isOptionChecked(MenuOption::VerboseLogging);
+
+ const_cast(&animation())->setEnabled(QtDebugMsg, enable);
+ const_cast(&animation())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&avatars())->setEnabled(QtDebugMsg, enable);
+ const_cast(&avatars())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&scriptengine())->setEnabled(QtDebugMsg, enable);
+ const_cast(&scriptengine())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&modelformat())->setEnabled(QtDebugMsg, enable);
+ const_cast(&modelformat())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&controllers())->setEnabled(QtDebugMsg, enable);
+ const_cast(&controllers())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&resourceLog())->setEnabled(QtDebugMsg, enable);
+ const_cast(&resourceLog())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&networking())->setEnabled(QtDebugMsg, enable);
+ const_cast(&networking())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&asset_client())->setEnabled(QtDebugMsg, enable);
+ const_cast(&asset_client())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&messages_client())->setEnabled(QtDebugMsg, enable);
+ const_cast(&messages_client())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&storagelogging())->setEnabled(QtDebugMsg, enable);
+ const_cast(&storagelogging())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&uiLogging())->setEnabled(QtDebugMsg, enable);
+ const_cast(&uiLogging())->setEnabled(QtInfoMsg, enable);
+
+ const_cast(&glLogging())->setEnabled(QtDebugMsg, enable);
+ const_cast(&glLogging())->setEnabled(QtInfoMsg, enable);
+}
+
void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
DomainHandler::ConnectionRefusedReason reasonCode = static_cast(reasonCodeInt);
@@ -3042,7 +3115,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
PROFILE_RANGE(render, __FUNCTION__);
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
- qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
enum HandControllerType {
Vive,
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 74b0e5a110..6d611bc8e2 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -399,6 +399,8 @@ public slots:
Q_INVOKABLE bool askBeforeSetAvatarUrl(const QString& avatarUrl) { return askToSetAvatarUrl(avatarUrl); }
+ void updateVerboseLogging();
+
private slots:
void onDesktopRootItemCreated(QQuickItem* qmlContext);
void onDesktopRootContextCreated(QQmlContext* qmlContext);
diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp
index fcb1908994..8deddbda82 100644
--- a/interface/src/ConnectionMonitor.cpp
+++ b/interface/src/ConnectionMonitor.cpp
@@ -43,12 +43,10 @@ void ConnectionMonitor::init() {
}
void ConnectionMonitor::startTimer() {
- qDebug() << "ConnectionMonitor: Starting timer";
_timer.start(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS);
}
void ConnectionMonitor::stopTimer() {
- qDebug() << "ConnectionMonitor: Stopping timer";
_timer.stop();
DependencyManager::get()->setDomainConnectionFailureVisibility(false);
}
diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp
index ae2f341337..e39cd42d81 100644
--- a/interface/src/Crashpad.cpp
+++ b/interface/src/Crashpad.cpp
@@ -15,6 +15,8 @@
#if HAS_CRASHPAD
+#include
+
#include
#include
@@ -23,8 +25,8 @@
#include
#include
#include
-// #include
-// #include
+#include
+#include
using namespace crashpad;
@@ -35,7 +37,8 @@ static std::wstring gIPCPipe;
extern QString qAppFileName();
-// crashpad::AnnotationList* crashpadAnnotations { nullptr };
+std::mutex annotationMutex;
+crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr };
#include
@@ -102,12 +105,14 @@ bool startCrashHandler() {
}
void setCrashAnnotation(std::string name, std::string value) {
- // if (!crashpadAnnotations) {
- // crashpadAnnotations = new crashpad::AnnotationList(); // don't free this, let it leak
- // crashpad::CrashpadInfo* crashpad_info = crashpad::GetCrashpadInfo();
- // crashpad_info->set_simple_annotations(crashpadAnnotations);
- // }
- // crashpadAnnotations->SetKeyValue(name, value);
+ std::lock_guard guard(annotationMutex);
+ if (!crashpadAnnotations) {
+ crashpadAnnotations = new crashpad::SimpleStringDictionary(); // don't free this, let it leak
+ crashpad::CrashpadInfo* crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo();
+ crashpad_info->set_simple_annotations(crashpadAnnotations);
+ }
+ std::replace(value.begin(), value.end(), ',', ';');
+ crashpadAnnotations->SetKeyValue(name, value);
}
#else
diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp
index 33cfc481d7..b3c059de7f 100644
--- a/interface/src/DiscoverabilityManager.cpp
+++ b/interface/src/DiscoverabilityManager.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include "Crashpad.h"
#include "DiscoverabilityManager.h"
#include "Menu.h"
@@ -127,10 +128,12 @@ void DiscoverabilityManager::updateLocation() {
QNetworkAccessManager::PutOperation, callbackParameters);
}
- // Update Steam
+ // Update Steam and crash logger
+ QUrl currentAddress = addressManager->currentFacingPublicAddress();
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
- steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingPublicAddress());
+ steamClient->updateLocation(domainHandler.getHostname(), currentAddress);
}
+ setCrashAnnotation("address", currentAddress.toString().toStdString());
}
void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) {
diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h
index e8737d92ae..96d92e91e9 100644
--- a/interface/src/LODManager.h
+++ b/interface/src/LODManager.h
@@ -9,11 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-/**jsdoc
- * The LOD class manages your Level of Detail functions within interface
- * @namespace LODManager
- */
-
#ifndef hifi_LODManager_h
#define hifi_LODManager_h
@@ -39,10 +34,32 @@ const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.04f;
class AABox;
+/**jsdoc
+ * The LOD class manages your Level of Detail functions within Interface.
+ * @namespace LODManager
+ * @property {number} presentTime Read-only.
+ * @property {number} engineRunTime Read-only.
+ * @property {number} gpuTime Read-only.
+ * @property {number} avgRenderTime Read-only.
+ * @property {number} fps Read-only.
+ * @property {number} lodLevel Read-only.
+ * @property {number} lodDecreaseFPS Read-only.
+ * @property {number} lodIncreaseFPS Read-only.
+ */
+
class LODManager : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
+ Q_PROPERTY(float presentTime READ getPresentTime)
+ Q_PROPERTY(float engineRunTime READ getEngineRunTime)
+ Q_PROPERTY(float gpuTime READ getGPUTime)
+ Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
+ Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
+ Q_PROPERTY(float lodLevel READ getLODLevel)
+ Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
+ Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
+
public:
/**jsdoc
@@ -138,28 +155,6 @@ public:
*/
Q_INVOKABLE float getLODIncreaseFPS() const;
- /**jsdoc
- * @namespace LODManager
- * @property {number} presentTime Read-only.
- * @property {number} engineRunTime Read-only.
- * @property {number} gpuTime Read-only.
- * @property {number} avgRenderTime Read-only.
- * @property {number} fps Read-only.
- * @property {number} lodLevel Read-only.
- * @property {number} lodDecreaseFPS Read-only.
- * @property {number} lodIncreaseFPS Read-only.
- */
-
- Q_PROPERTY(float presentTime READ getPresentTime)
- Q_PROPERTY(float engineRunTime READ getEngineRunTime)
- Q_PROPERTY(float gpuTime READ getGPUTime)
- Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
- Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
- Q_PROPERTY(float lodLevel READ getLODLevel)
-
- Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
- Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
-
float getPresentTime() const { return _presentTime; }
float getEngineRunTime() const { return _engineRunTime; }
float getGPUTime() const { return _gpuTime; }
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 4384635147..50ff65ad1a 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -810,6 +810,9 @@ Menu::Menu() {
scriptEngines->loadScript(defaultScriptsLoc.toString());
});
+ addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false,
+ qApp, SLOT(updateVerboseLogging()));
+
#if 0 /// -------------- REMOVED FOR NOW --------------
addDisabledActionAndSeparator(navigateMenu, "History");
QAction* backAction = addActionToQMenuAndActionHash(navigateMenu, MenuOption::Back, 0, addressManager.data(), SLOT(goBack()));
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index bba70a6a89..c8c8ee42df 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -142,6 +142,7 @@ namespace MenuOption {
const QString Pair = "Pair";
const QString PhysicsShowHulls = "Draw Collision Shapes";
const QString PhysicsShowOwned = "Highlight Simulation Ownership";
+ const QString VerboseLogging = "Verbose Logging";
const QString PipelineWarnings = "Log Render Pipeline Warnings";
const QString Preferences = "General...";
const QString Quit = "Quit";
diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp
index 3e0e4adf18..35e6ca1c92 100644
--- a/interface/src/commerce/Wallet.cpp
+++ b/interface/src/commerce/Wallet.cpp
@@ -615,9 +615,15 @@ void Wallet::updateImageProvider() {
securityImageProvider->setSecurityImage(_securityImage);
// inform tablet security image provider
- QQmlEngine* tabletEngine = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")->getTabletSurface()->getSurfaceContext()->engine();
- securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
- securityImageProvider->setSecurityImage(_securityImage);
+ TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system");
+ if (tablet) {
+ OffscreenQmlSurface* tabletSurface = tablet->getTabletSurface();
+ if (tabletSurface) {
+ QQmlEngine* tabletEngine = tabletSurface->getSurfaceContext()->engine();
+ securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
+ securityImageProvider->setSecurityImage(_securityImage);
+ }
+ }
}
void Wallet::chooseSecurityImage(const QString& filename) {
diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp
index ee615cde20..a3c80bf1b6 100644
--- a/interface/src/scripting/AudioDevices.cpp
+++ b/interface/src/scripting/AudioDevices.cpp
@@ -108,11 +108,9 @@ AudioDeviceList::~AudioDeviceList() {
// store the selected device
foreach(std::shared_ptr adevice, _devices) {
if (adevice->selectedDesktop) {
- qDebug() << "Saving Desktop for" << _mode << "name" << adevice->info.deviceName();
settingDesktop.set(adevice->info.deviceName());
}
if (adevice->selectedHMD) {
- qDebug() << "Saving HMD for" << _mode << "name" << adevice->info.deviceName();
settingHMD.set(adevice->info.deviceName());
}
}
@@ -311,7 +309,6 @@ void AudioDeviceList::onDevicesChanged(const QList& devices) {
}
}
- qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode;
newDevices.push_back(newDevice(device));
}
diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h
index f19caa8478..4fceda3b04 100644
--- a/interface/src/scripting/ControllerScriptingInterface.h
+++ b/interface/src/scripting/ControllerScriptingInterface.h
@@ -28,7 +28,7 @@ class ScriptEngine;
/**jsdoc
* The Controller API provides facilities to interact with computer and controller hardware.
*
- * Functions:
+ * Functions
*
* Properties
*
@@ -143,6 +143,61 @@ class ScriptEngine;
* - {@link Controller.stopInputPlayback|stopInputPlayback}
*
*
+ * Entity Methods:
+ *
+ * The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script
+ * methods, if present in the entity being interacted with.
+ *
+ *
+ *
+ * Method Name | Description | Example |
+ *
+ *
+ *
+ * startFarTrigger
continueFarTrigger
stopFarTrigger |
+ * These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger. |
+ *
+ * A light switch that can be toggled on and off from a distance. |
+ *
+ *
+ * startNearTrigger
continueNearTrigger
stopNearTrigger |
+ * These methods are called when a user is less than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger. |
+ * A doorbell that can be rung when a user is near. |
+ *
+ *
+ * startDistanceGrab
continueDistanceGrab
|
+ * These methods are called when a user is more than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger. |
+ * A comet that emits icy particle trails when a user is dragging it through the sky. |
+ *
+ *
+ * startNearGrab
continueNearGrab
|
+ * These methods are called when a user is less than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger. |
+ * A ball that glows when it's being held close. |
+ *
+ *
+ * releaseGrab |
+ * This method is called when a user releases the trigger when having been either distance or near grabbing an
+ * entity. |
+ * Turn off the ball glow or comet trail with the user finishes grabbing it. |
+ *
+ *
+ * startEquip
continueEquip
releaseEquip |
+ * These methods are called when a user starts, continues, or stops equipping an entity. |
+ * A glass that stays in the user's hand after the trigger is clicked. |
+ *
+ *
+ *
+ * All the entity methods are called with the following two arguments:
+ *
+ * - The entity ID.
+ * - A string,
"hand,userID"
— where "hand" is "left"
or "right"
, and "userID"
+ * is the user's {@link MyAvatar|MyAvatar.sessionUUID}.
+ *
+ *
* @namespace Controller
*
* @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end
diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp
index 310a4cc1cd..d01e7d6671 100644
--- a/interface/src/ui/DialogsManager.cpp
+++ b/interface/src/ui/DialogsManager.cpp
@@ -80,7 +80,6 @@ void DialogsManager::showFeed() {
}
void DialogsManager::setDomainConnectionFailureVisibility(bool visible) {
- qDebug() << "DialogsManager::setDomainConnectionFailureVisibility: visible" << visible;
auto tabletScriptingInterface = DependencyManager::get();
auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
diff --git a/libraries/animation/src/AnimExpression.cpp b/libraries/animation/src/AnimExpression.cpp
index 79004a72a6..9777e9c6af 100644
--- a/libraries/animation/src/AnimExpression.cpp
+++ b/libraries/animation/src/AnimExpression.cpp
@@ -588,6 +588,7 @@ void AnimExpression::evalUnaryMinus(const AnimVariantMap& map, std::stack
#include
#include
diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
index 86a43c0c13..3c3858e2ba 100644
--- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
@@ -39,7 +39,9 @@ class UserInputMapper;
* methods.
* Use {@link Controller.parseMapping} or {@link Controller.loadMapping} to load a {@link Controller.MappingJSON}.
*
- * Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect.
+ *
+ *
Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take
+ * effect.
*
* Mappings and their routes are applied according to the following rules:
*
@@ -49,7 +51,7 @@ class UserInputMapper;
* output that already has a route the new route is ignored.
* - New mappings override previous mappings: each output is processed using the route in the most recently enabled
* mapping that contains that output.
- *
+ *
*
* @class MappingObject
*/
diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
index 0336638068..d33f3e3383 100644
--- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
@@ -29,7 +29,8 @@ class ScriptingInterface;
* A route in a {@link MappingObject} used by the {@link Controller} API.
*
* Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with
- * {@link RouteObject#to} to apply it to a Standard
control, action, or script function.
+ * {@link RouteObject#to} to apply it to a Standard
control, action, or script function. Note: Loops are not
+ * permitted.
*
* Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route
* types.
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index f333e805ce..693e3d0cf4 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -308,12 +308,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
item->setProperty(URL_PROPERTY, _lastSourceUrl);
});
} else if (_contentType == ContentType::QmlContent) {
- _webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) {
- if (item && item->objectName() == "tabletRoot") {
- auto tabletScriptingInterface = DependencyManager::get();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
- }
- });
+ _webSurface->load(_lastSourceUrl);
}
_fadeStartTime = usecTimestampNow();
_webSurface->resume();
@@ -323,32 +318,21 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
void WebEntityRenderer::destroyWebSurface() {
QSharedPointer webSurface;
+ ContentType contentType{ ContentType::NoContent };
withWriteLock([&] {
webSurface.swap(_webSurface);
+ std::swap(contentType, _contentType);
});
if (webSurface) {
--_currentWebCount;
QQuickItem* rootItem = webSurface->getRootItem();
- // Explicitly set the web URL to an empty string, in an effort to get a
- // faster shutdown of any chromium processes interacting with audio
- if (rootItem && _contentType == ContentType::HtmlContent) {
- rootItem->setProperty(URL_PROPERTY, "");
- }
-
- if (rootItem && rootItem->objectName() == "tabletRoot") {
- auto tabletScriptingInterface = DependencyManager::get();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr);
- }
// Fix for crash in QtWebEngineCore when rapidly switching domains
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
- if (rootItem) {
- QObject* obj = rootItem->findChild("webEngineView");
- if (obj) {
- // stop loading
- QMetaObject::invokeMethod(obj, "stop");
- }
+ if (rootItem && contentType == ContentType::HtmlContent) {
+ // stop loading
+ QMetaObject::invokeMethod(rootItem, "stop");
}
webSurface->pause();
diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h
index d4a8b11453..5e76d18515 100644
--- a/libraries/entities/src/EntityScriptingInterface.h
+++ b/libraries/entities/src/EntityScriptingInterface.h
@@ -390,17 +390,18 @@ public slots:
/**jsdoc
* Find all entities of a particular name that intersect a sphere defined by a center point and radius.
* @function Entities.findEntitiesByName
- * @param {Entities.EntityType} entityName - The name of the entity to search for.
+ * @param {string} entityName - The name of the entity to search for.
* @param {Vec3} center - The point about which to search.
* @param {number} radius - The radius within which to search.
- * @param {boolean} caseSensitiveSearch - Choose whether to to return case sensitive results back.
- * @returns {Uuid[]} An array of entity IDs of the specified type that intersect the search sphere. The array is empty if
- * no entities could be found.
- * @example Get back a list of entities
+ * @param {boolean} [caseSensitive=false] - If true
then the search is case-sensitive.
+ * @returns {Uuid[]} An array of entity IDs that have the specified name and intersect the search sphere. The array is empty
+ * if no entities could be found.
+ * @example Report the number of entities with the name, "Light-Target".
* var entityIDs = Entities.findEntitiesByName("Light-Target", MyAvatar.position, 10, false);
- * print("Number of Entities with the name Light-Target " + entityIDs.length);
+ * print("Number of entities with the name "Light-Target": " + entityIDs.length);
*/
- Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch = false ) const;
+ Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius,
+ bool caseSensitiveSearch = false ) const;
/**jsdoc
* Find the first entity intersected by a {@link PickRay}. Light
and Zone
entities are not
diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp
index 1e59646795..86422ef70c 100644
--- a/libraries/fbx/src/FBXReader.cpp
+++ b/libraries/fbx/src/FBXReader.cpp
@@ -996,14 +996,12 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
QByteArray filename = subobject.properties.at(0).toByteArray();
QByteArray filepath = filename.replace('\\', '/');
filename = fileOnUrl(filepath, url);
- qDebug() << "Filename" << filepath << filename;
_textureFilepaths.insert(getID(object.properties), filepath);
_textureFilenames.insert(getID(object.properties), filename);
} else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) {
// trim the name from the timestamp
QString name = QString(subobject.properties.at(0).toByteArray());
name = name.left(name.indexOf('['));
- qDebug() << "Filename" << name;
_textureNames.insert(getID(object.properties), name);
} else if (subobject.name == "Texture_Alpha_Source" && subobject.properties.length() >= TEXTURE_ALPHA_SOURCE_MIN_SIZE) {
tex.assign(tex.alphaSource, subobject.properties.at(0).value());
diff --git a/libraries/networking/src/EntityScriptClient.cpp b/libraries/networking/src/EntityScriptClient.cpp
index 75ae7369fb..1eab5bf2d7 100644
--- a/libraries/networking/src/EntityScriptClient.cpp
+++ b/libraries/networking/src/EntityScriptClient.cpp
@@ -192,8 +192,6 @@ void EntityScriptClient::handleNodeClientConnectionReset(SharedNodePointer node)
return;
}
- //qCDebug(entity_script_client) << "EntityScriptClient detected client connection reset handshake with Asset Server - failing any pending requests";
-
forceFailureOfPendingRequests(node);
}
diff --git a/libraries/networking/src/NetworkLogging.h b/libraries/networking/src/NetworkLogging.h
index 518c600efe..30116ff405 100644
--- a/libraries/networking/src/NetworkLogging.h
+++ b/libraries/networking/src/NetworkLogging.h
@@ -17,7 +17,6 @@
Q_DECLARE_LOGGING_CATEGORY(resourceLog)
Q_DECLARE_LOGGING_CATEGORY(networking)
Q_DECLARE_LOGGING_CATEGORY(asset_client)
-Q_DECLARE_LOGGING_CATEGORY(entity_script_client)
Q_DECLARE_LOGGING_CATEGORY(messages_client)
#endif // hifi_NetworkLogging_h
diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp
index 35db43e5e7..2efd32f2e8 100644
--- a/libraries/octree/src/Octree.cpp
+++ b/libraries/octree/src/Octree.cpp
@@ -795,9 +795,10 @@ QString getMarketplaceID(const QString& urlString) {
}
bool Octree::readFromURL(const QString& urlString) {
- QString marketplaceID = getMarketplaceID(urlString);
+ QString trimmedUrl = urlString.trimmed();
+ QString marketplaceID = getMarketplaceID(trimmedUrl);
auto request =
- std::unique_ptr(DependencyManager::get()->createResourceRequest(this, urlString));
+ std::unique_ptr(DependencyManager::get()->createResourceRequest(this, trimmedUrl));
if (!request) {
return false;
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index ab7c2ec252..3ea3616b15 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -153,6 +153,8 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// remove the objects (aka MotionStates) from physics
_physicsEngine->removeSetOfObjects(_physicalObjects);
+ clearOwnershipData();
+
// delete the MotionStates
for (auto stateItr : _physicalObjects) {
EntityMotionState* motionState = static_cast(&(*stateItr));
@@ -165,7 +167,6 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
_physicalObjects.clear();
// clear all other lists specific to this derived class
- clearOwnershipData();
_entitiesToRemoveFromPhysics.clear();
_entitiesToAddToPhysics.clear();
_incomingChanges.clear();
diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp
index 9253c41b39..2fde057ca8 100644
--- a/libraries/qml/src/qml/impl/SharedObject.cpp
+++ b/libraries/qml/src/qml/impl/SharedObject.cpp
@@ -90,19 +90,23 @@ SharedObject::~SharedObject() {
_renderControl = nullptr;
}
+ if (_rootItem) {
+ delete _rootItem;
+ _rootItem = nullptr;
+ }
+
if (_quickWindow) {
_quickWindow->destroy();
delete _quickWindow;
_quickWindow = nullptr;
}
- // _rootItem is parented to the quickWindow, so needs no explicit destruction
- //if (_rootItem) {
- // delete _rootItem;
- // _rootItem = nullptr;
- //}
-
- releaseEngine(_qmlContext->engine());
+ if (_qmlContext) {
+ auto engine = _qmlContext->engine();
+ delete _qmlContext;
+ _qmlContext = nullptr;
+ releaseEngine(engine);
+ }
}
void SharedObject::create(OffscreenSurface* surface) {
@@ -210,9 +214,9 @@ QQmlEngine* SharedObject::acquireEngine(OffscreenSurface* surface) {
if (!globalEngine) {
Q_ASSERT(0 == globalEngineRefCount);
globalEngine = new QQmlEngine();
- surface->initializeQmlEngine(result);
- ++globalEngineRefCount;
+ surface->initializeEngine(result);
}
+ ++globalEngineRefCount;
result = globalEngine;
#else
result = new QQmlEngine();
diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp
index 90424b04b2..7086b65f4c 100644
--- a/libraries/render-utils/src/AnimDebugDraw.cpp
+++ b/libraries/render-utils/src/AnimDebugDraw.cpp
@@ -16,6 +16,7 @@
#include "AbstractViewStateInterface.h"
#include "RenderUtilsLogging.h"
#include "DebugDraw.h"
+#include "StencilMaskPass.h"
#include "animdebugdraw_vert.h"
#include "animdebugdraw_frag.h"
@@ -70,7 +71,7 @@ public:
typedef render::Payload AnimDebugDrawPayload;
namespace render {
- template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::opaqueShape() : ItemKey::Builder::opaqueShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); }
+ template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::transparentShape() : ItemKey::Builder::transparentShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); }
template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return data->_bound; }
template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) {
data->render(args);
@@ -104,6 +105,7 @@ AnimDebugDraw::AnimDebugDraw() :
state->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD,
gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA,
gpu::State::BLEND_OP_ADD, gpu::State::ONE);
+ PrepareStencil::testMaskDrawShape(*state.get());
auto vertShader = animdebugdraw_vert::getShader();
auto fragShader = animdebugdraw_frag::getShader();
auto program = gpu::Shader::createProgram(vertShader, fragShader);
diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp
index e620fc2d61..dd4bda2e37 100644
--- a/libraries/render-utils/src/AntialiasingEffect.cpp
+++ b/libraries/render-utils/src/AntialiasingEffect.cpp
@@ -198,7 +198,7 @@ Antialiasing::~Antialiasing() {
_antialiasingTextures[1].reset();
}
-const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
+const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline(const render::RenderContextPointer& renderContext) {
if (!_antialiasingPipeline) {
@@ -207,17 +207,6 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
- slotBindings.insert(gpu::Shader::Binding(std::string("taaParamsBuffer"), AntialiasingPass_ParamsSlot));
-
- slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), AntialiasingPass_FrameTransformSlot));
-
- slotBindings.insert(gpu::Shader::Binding(std::string("historyMap"), AntialiasingPass_HistoryMapSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), AntialiasingPass_SourceMapSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("velocityMap"), AntialiasingPass_VelocityMapSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), AntialiasingPass_DepthMapSlot));
-
-
- gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
@@ -225,6 +214,21 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
// Good to go add the brand new pipeline
_antialiasingPipeline = gpu::Pipeline::create(program, state);
+
+ gpu::doInBatch("SurfaceGeometryPass::CurvaturePipeline", renderContext->args->_context, [program](gpu::Batch& batch) {
+ batch.runLambda([program]() {
+ gpu::Shader::BindingSet slotBindings;
+ slotBindings.insert(gpu::Shader::Binding(std::string("taaParamsBuffer"), AntialiasingPass_ParamsSlot));
+
+ slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), AntialiasingPass_FrameTransformSlot));
+
+ slotBindings.insert(gpu::Shader::Binding(std::string("historyMap"), AntialiasingPass_HistoryMapSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), AntialiasingPass_SourceMapSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("velocityMap"), AntialiasingPass_VelocityMapSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), AntialiasingPass_DepthMapSlot));
+ gpu::Shader::makeProgram(*program, slotBindings);
+ });
+ });
}
return _antialiasingPipeline;
@@ -347,7 +351,7 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
batch.setViewportTransform(args->_viewport);
// TAA step
- getAntialiasingPipeline();
+ getAntialiasingPipeline(renderContext);
batch.setResourceFramebufferSwapChainTexture(AntialiasingPass_HistoryMapSlot, _antialiasingBuffers, 0);
batch.setResourceTexture(AntialiasingPass_SourceMapSlot, sourceBuffer->getRenderBuffer(0));
batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, velocityBuffer->getVelocityTexture());
@@ -358,7 +362,7 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
batch.setUniformBuffer(AntialiasingPass_FrameTransformSlot, deferredFrameTransform->getFrameTransformBuffer());
batch.setFramebufferSwapChain(_antialiasingBuffers, 1);
- batch.setPipeline(getAntialiasingPipeline());
+ batch.setPipeline(getAntialiasingPipeline(renderContext));
batch.draw(gpu::TRIANGLE_STRIP, 4);
// Blend step
diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h
index a89666f58b..9f62fd76c1 100644
--- a/libraries/render-utils/src/AntialiasingEffect.h
+++ b/libraries/render-utils/src/AntialiasingEffect.h
@@ -174,7 +174,7 @@ public:
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
- const gpu::PipelinePointer& getAntialiasingPipeline();
+ const gpu::PipelinePointer& getAntialiasingPipeline(const render::RenderContextPointer& renderContext);
const gpu::PipelinePointer& getBlendPipeline();
const gpu::PipelinePointer& getDebugBlendPipeline();
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp
index d3bf3ab198..51046f10b3 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.cpp
+++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp
@@ -168,7 +168,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
outputs.edit4() = halfNormalTexture;
auto linearDepthPipeline = getLinearDepthPipeline(renderContext);
- auto downsamplePipeline = getDownsamplePipeline();
+ auto downsamplePipeline = getDownsamplePipeline(renderContext);
auto depthViewport = args->_viewport;
auto halfViewport = depthViewport >> 1;
@@ -241,19 +241,12 @@ const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline(const render
}
-const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() {
+const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline(const render::RenderContextPointer& renderContext) {
if (!_downsamplePipeline) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto ps = surfaceGeometry_downsampleDepthNormal_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
- gpu::Shader::BindingSet slotBindings;
- slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DepthLinearPass_FrameTransformSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), DepthLinearPass_DepthMapSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DepthLinearPass_NormalMapSlot));
- gpu::Shader::makeProgram(*program, slotBindings);
-
-
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testShape(*state);
@@ -261,6 +254,16 @@ const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() {
// Good to go add the brand new pipeline
_downsamplePipeline = gpu::Pipeline::create(program, state);
+
+ gpu::doInBatch("LinearDepthPass::run", renderContext->args->_context, [program](gpu::Batch& batch) {
+ batch.runLambda([program]() {
+ gpu::Shader::BindingSet slotBindings;
+ slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", DepthLinearPass_FrameTransformSlot));
+ slotBindings.insert(gpu::Shader::Binding("linearDepthMap", DepthLinearPass_DepthMapSlot));
+ slotBindings.insert(gpu::Shader::Binding("normalMap", DepthLinearPass_NormalMapSlot));
+ gpu::Shader::makeProgram(*program, slotBindings);
+ });
+ });
}
return _downsamplePipeline;
diff --git a/libraries/render-utils/src/SurfaceGeometryPass.h b/libraries/render-utils/src/SurfaceGeometryPass.h
index 501cf3fa87..367f599f67 100644
--- a/libraries/render-utils/src/SurfaceGeometryPass.h
+++ b/libraries/render-utils/src/SurfaceGeometryPass.h
@@ -84,7 +84,7 @@ private:
const gpu::PipelinePointer& getLinearDepthPipeline(const render::RenderContextPointer& renderContext);
gpu::PipelinePointer _linearDepthPipeline;
- const gpu::PipelinePointer& getDownsamplePipeline();
+ const gpu::PipelinePointer& getDownsamplePipeline(const render::RenderContextPointer& renderContext);
gpu::PipelinePointer _downsamplePipeline;
gpu::RangeTimerPointer _gpuTimer;
diff --git a/libraries/render-utils/src/VelocityBufferPass.cpp b/libraries/render-utils/src/VelocityBufferPass.cpp
index 78471d48af..3f7da4cdcd 100644
--- a/libraries/render-utils/src/VelocityBufferPass.cpp
+++ b/libraries/render-utils/src/VelocityBufferPass.cpp
@@ -113,7 +113,7 @@ void VelocityBufferPass::run(const render::RenderContextPointer& renderContext,
outputs.edit1() = velocityFBO;
outputs.edit2() = velocityTexture;
- auto cameraMotionPipeline = getCameraMotionPipeline();
+ auto cameraMotionPipeline = getCameraMotionPipeline(renderContext);
auto fullViewport = args->_viewport;
@@ -143,18 +143,12 @@ void VelocityBufferPass::run(const render::RenderContextPointer& renderContext,
}
-const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline() {
+const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline(const render::RenderContextPointer& renderContext) {
if (!_cameraMotionPipeline) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto ps = velocityBuffer_cameraMotion_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
- gpu::Shader::BindingSet slotBindings;
- slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), VelocityBufferPass_FrameTransformSlot));
- slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), VelocityBufferPass_DepthMapSlot));
- gpu::Shader::makeProgram(*program, slotBindings);
-
-
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// Stencil test the curvature pass for objects pixels only, not the background
@@ -164,6 +158,16 @@ const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline() {
// Good to go add the brand new pipeline
_cameraMotionPipeline = gpu::Pipeline::create(program, state);
+
+ gpu::doInBatch("VelocityBufferPass::CameraMotionPipeline", renderContext->args->_context,
+ [program](gpu::Batch& batch) {
+ batch.runLambda([program]() {
+ gpu::Shader::BindingSet slotBindings;
+ slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), VelocityBufferPass_FrameTransformSlot));
+ slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), VelocityBufferPass_DepthMapSlot));
+ gpu::Shader::makeProgram(*program, slotBindings);
+ });
+ });
}
return _cameraMotionPipeline;
diff --git a/libraries/render-utils/src/VelocityBufferPass.h b/libraries/render-utils/src/VelocityBufferPass.h
index fb2b729368..50b994f6db 100644
--- a/libraries/render-utils/src/VelocityBufferPass.h
+++ b/libraries/render-utils/src/VelocityBufferPass.h
@@ -79,7 +79,7 @@ private:
VelocityFramebufferPointer _velocityFramebuffer;
- const gpu::PipelinePointer& getCameraMotionPipeline();
+ const gpu::PipelinePointer& getCameraMotionPipeline(const render::RenderContextPointer& renderContext);
gpu::PipelinePointer _cameraMotionPipeline;
gpu::RangeTimerPointer _gpuTimer;
diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index c79ffffec7..f0a13cc62b 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -2161,6 +2161,32 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
}, forceRedownload);
}
+/**jsdoc
+ * Triggered when the script starts for a user.
+ * Note: Can only be connected to via this.preload = function (...) { ... }
in the entity script.
+ * Available in: | Client Entity Scripts | Server Entity Scripts |
---|
+ * @function Entities.preload
+ * @param {Uuid} entityID - The ID of the entity that the script is running in.
+ * @returns {Signal}
+ * @example Get the ID of the entity that a client entity script is running in.
+ * var entityScript = (function () {
+ * this.entityID = Uuid.NULL;
+ *
+ * this.preload = function (entityID) {
+ * this.entityID = entityID;
+ * print("Entity ID: " + this.entityID);
+ * };
+ * );
+ *
+ * var entityID = Entities.addEntity({
+ * type: "Box",
+ * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
+ * dimensions: { x: 0.5, y: 0.5, z: 0.5 },
+ * color: { red: 255, green: 0, blue: 0 },
+ * script: "(" + entityScript + ")", // Could host the script on a Web server instead.
+ * lifetime: 300 // Delete after 5 minutes.
+ * });
+ */
// since all of these operations can be asynch we will always do the actual work in the response handler
// for the download
void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success , const QString& status) {
@@ -2345,6 +2371,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
processDeferredEntityLoads(entityScript, entityID);
}
+/**jsdoc
+ * Triggered when the script terminates for a user.
+ * Note: Can only be connected to via this.unoad = function () { ... }
in the entity script.
+ * Available in: | Client Entity Scripts | Server Entity Scripts |
---|
+ * @function Entities.unload
+ * @returns {Signal}
+ */
void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp
index 871705d74b..a788cd9f0e 100644
--- a/libraries/script-engine/src/ScriptEngines.cpp
+++ b/libraries/script-engine/src/ScriptEngines.cpp
@@ -273,9 +273,9 @@ QVariantList ScriptEngines::getRunning() {
} else {
displayURLString = displayURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded));
}
- resultNode.insert("url", displayURLString);
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
- resultNode.insert("path", normalizeScriptURL(runningScript).toString());
+ resultNode.insert("path", displayURLString);
+ resultNode.insert("url", normalizeScriptURL(runningScript).toString());
resultNode.insert("local", runningScriptURL.isLocalFile());
result.append(resultNode);
}
@@ -538,7 +538,6 @@ int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) {
int ii=0;
for (auto initializer : _scriptInitializers) {
ii++;
- qDebug() << "initializer" << ii;
initializer(scriptEngine);
}
return ii;
diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp
index b1ceab4149..c7ad4a790d 100644
--- a/libraries/shared/src/OctalCode.cpp
+++ b/libraries/shared/src/OctalCode.cpp
@@ -213,7 +213,7 @@ void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectio
int byteForSection = (BITS_IN_OCTAL * section / BITS_IN_BYTE);
unsigned char* byteAt = octalCode + 1 + byteForSection;
char bitInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE;
- char shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL;
+ int8_t shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL;
const unsigned char UNSHIFTED_MASK = 0x07;
unsigned char shiftedMask;
unsigned char shiftedValue;
diff --git a/libraries/shared/src/Trace.h b/libraries/shared/src/Trace.h
index 93e2c6c4c2..1e1326968f 100644
--- a/libraries/shared/src/Trace.h
+++ b/libraries/shared/src/Trace.h
@@ -102,6 +102,9 @@ private:
};
inline void traceEvent(const QLoggingCategory& category, const QString& name, EventType type, const QString& id = "", const QVariantMap& args = {}, const QVariantMap& extra = {}) {
+ if (!DependencyManager::isSet()) {
+ return;
+ }
const auto& tracer = DependencyManager::get();
if (tracer) {
tracer->traceEvent(category, name, type, id, args, extra);
diff --git a/libraries/shared/src/shared/MiniPromises.cpp b/libraries/shared/src/shared/MiniPromises.cpp
index bb78852c29..21a3f44d50 100644
--- a/libraries/shared/src/shared/MiniPromises.cpp
+++ b/libraries/shared/src/shared/MiniPromises.cpp
@@ -22,6 +22,5 @@ namespace {
}
void MiniPromise::registerMetaTypes(QObject* engine) {
auto scriptEngine = qobject_cast(engine);
- qDebug() << "----------------------- MiniPromise::registerMetaTypes ------------" << scriptEngine;
qScriptRegisterMetaType(scriptEngine, promiseToScriptValue, promiseFromScriptValue);
}
diff --git a/libraries/shared/src/shared/Storage.cpp b/libraries/shared/src/shared/Storage.cpp
index 8fe1454242..b983213e4a 100644
--- a/libraries/shared/src/shared/Storage.cpp
+++ b/libraries/shared/src/shared/Storage.cpp
@@ -10,7 +10,7 @@
#include
#include
-#include
+#include "StorageLogging.h"
Q_LOGGING_CATEGORY(storagelogging, "hifi.core.storage")
@@ -102,4 +102,4 @@ FileStorage::~FileStorage() {
if (_file.isOpen()) {
_file.close();
}
-}
\ No newline at end of file
+}
diff --git a/libraries/shared/src/shared/StorageLogging.h b/libraries/shared/src/shared/StorageLogging.h
new file mode 100644
index 0000000000..33d89411bd
--- /dev/null
+++ b/libraries/shared/src/shared/StorageLogging.h
@@ -0,0 +1,18 @@
+//
+// StorageLogging.h
+//
+// Created by Seth Alves on 2018-4-20
+// Copyright 2018 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_StorageLogging_h
+#define hifi_StorageLogging_h
+
+#include
+
+Q_DECLARE_LOGGING_CATEGORY(storagelogging)
+
+#endif // hifi_StorageLogging_h
diff --git a/libraries/ui/src/ui/Logging.h b/libraries/ui/src/ui/Logging.h
index 6d31b0e86a..dd14268dba 100644
--- a/libraries/ui/src/ui/Logging.h
+++ b/libraries/ui/src/ui/Logging.h
@@ -6,8 +6,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-#ifndef hifi_Controllers_Logging_h
-#define hifi_Controllers_Logging_h
+#ifndef hifi_UI_Logging_h
+#define hifi_UI_Logging_h
#include
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index 43b573a169..48e778c063 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -102,7 +102,7 @@ class AudioHandler : public QObject, QRunnable {
public:
AudioHandler(OffscreenQmlSurface* surface, const QString& deviceName, QObject* parent = nullptr);
- virtual ~AudioHandler() { qDebug() << "Audio Handler Destroyed"; }
+ virtual ~AudioHandler() { }
void run() override;
@@ -115,6 +115,7 @@ private:
class UrlHandler : public QObject {
Q_OBJECT
public:
+ UrlHandler(QObject* parent = nullptr) : QObject(parent) {}
Q_INVOKABLE bool canHandleUrl(const QString& url) {
static auto handler = dynamic_cast(qApp);
return handler && handler->canAcceptURL(url);
@@ -223,6 +224,17 @@ void AudioHandler::run() {
qDebug() << "QML Audio changed to " << _newTargetDevice;
}
+OffscreenQmlSurface::~OffscreenQmlSurface() {
+ clearFocusItem();
+}
+
+void OffscreenQmlSurface::clearFocusItem() {
+ if (_currentFocusItem) {
+ disconnect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed);
+ }
+ _currentFocusItem = nullptr;
+}
+
void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) {
Parent::initializeEngine(engine);
new QQmlFileSelector(engine);
@@ -246,7 +258,7 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) {
auto rootContext = engine->rootContext();
rootContext->setContextProperty("GL", ::getGLContextData());
- rootContext->setContextProperty("urlHandler", new UrlHandler());
+ rootContext->setContextProperty("urlHandler", new UrlHandler(rootContext));
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
rootContext->setContextProperty("ApplicationInterface", qApp);
auto javaScriptToInject = getEventBridgeJavascript();
@@ -545,17 +557,15 @@ bool OffscreenQmlSurface::handlePointerEvent(const PointerEvent& event, class QT
}
void OffscreenQmlSurface::focusDestroyed(QObject* obj) {
- if (_currentFocusItem) {
- disconnect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed);
- }
- _currentFocusItem = nullptr;
+ clearFocusItem();
}
void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) {
+ clearFocusItem();
+
QQuickItem* item = static_cast(object);
if (!item) {
setFocusText(false);
- _currentFocusItem = nullptr;
return;
}
@@ -563,10 +573,6 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) {
qApp->sendEvent(object, &query);
setFocusText(query.value(Qt::ImEnabled).toBool());
- if (_currentFocusItem) {
- disconnect(_currentFocusItem, &QObject::destroyed, this, 0);
- }
-
// Raise and lower keyboard for QML text fields.
// HTML text fields are handled in emitWebEvent() methods - testing READ_ONLY_PROPERTY prevents action for HTML files.
const char* READ_ONLY_PROPERTY = "readOnly";
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h
index 9fa86f12a3..b95a8f117d 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.h
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.h
@@ -22,7 +22,8 @@ class OffscreenQmlSurface : public hifi::qml::OffscreenSurface {
Q_OBJECT
Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged)
public:
-
+ ~OffscreenQmlSurface();
+
static void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback);
static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); };
@@ -58,6 +59,7 @@ public slots:
void sendToQml(const QVariant& message);
protected:
+ void clearFocusItem();
void setFocusText(bool newFocusText);
void initializeEngine(QQmlEngine* engine) override;
void onRootContextCreated(QQmlContext* qmlContext) override;
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 6d2b1f129b..c99c8d401a 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -1291,6 +1291,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
+ Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE);
}
Script.scriptEnding.connect(function () {
diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js
index 3598f30ee0..099c4be9e3 100644
--- a/scripts/system/particle_explorer/particleExplorer.js
+++ b/scripts/system/particle_explorer/particleExplorer.js
@@ -321,7 +321,8 @@
{
id: "alpha",
name: "Alpha",
- type: "SliderFloat"
+ type: "SliderFloat",
+ max: 1.0
},
{
type: "Row"
@@ -329,7 +330,8 @@
{
id: "alphaSpread",
name: "Alpha Spread",
- type: "SliderFloat"
+ type: "SliderFloat",
+ max: 1.0
},
{
type: "Row"
@@ -337,7 +339,8 @@
{
id: "alphaStart",
name: "Alpha Start",
- type: "SliderFloat"
+ type: "SliderFloat",
+ max: 1.0
},
{
type: "Row"
@@ -345,7 +348,8 @@
{
id: "alphaFinish",
name: "Alpha Finish",
- type: "SliderFloat"
+ type: "SliderFloat",
+ max: 1.0
},
{
type: "Row"
diff --git a/tests/controllers/CMakeLists.txt b/tests/controllers/CMakeLists.txt
index b5e866ccce..ce1c150ed4 100644
--- a/tests/controllers/CMakeLists.txt
+++ b/tests/controllers/CMakeLists.txt
@@ -23,5 +23,9 @@ if (WIN32)
add_dependency_external_projects(wasapi)
endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ target_link_libraries(${TARGET_NAME} atomic)
+endif()
+
package_libraries_for_deployment()
-endif()
\ No newline at end of file
+endif()
diff --git a/tests/qml/qml/controls/WebEntityView.qml b/tests/qml/qml/controls/WebEntityView.qml
new file mode 100644
index 0000000000..5bd29ef457
--- /dev/null
+++ b/tests/qml/qml/controls/WebEntityView.qml
@@ -0,0 +1,47 @@
+//
+// WebEntityView.qml
+//
+// Created by Kunal Gosar on 16 March 2017
+// Copyright 2017 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
+//
+
+import QtQuick 2.5
+import QtWebEngine 1.5
+import Hifi 1.0
+
+/*
+TestItem {
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ color: "blue"
+ property string url: ""
+ ColorAnimation on color {
+ loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000
+ }
+ }
+}
+*/
+
+WebEngineView {
+ id: webViewCore
+ objectName: "webEngineView"
+ width: parent !== null ? parent.width : undefined
+ height: parent !== null ? parent.height : undefined
+
+ onFeaturePermissionRequested: {
+ grantFeaturePermission(securityOrigin, feature, true);
+ }
+
+ //disable popup
+ onContextMenuRequested: {
+ request.accepted = true;
+ }
+
+ onNewViewRequested: {
+ newViewRequestedCallback(request)
+ }
+}
diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp
index 022f7290f4..349ac55d88 100644
--- a/tests/qml/src/main.cpp
+++ b/tests/qml/src/main.cpp
@@ -28,52 +28,87 @@
#include
#include
#include
-
+#include
#include
#include
+#include
+
#include
-#include
#include
#include
#include
#include
#include
#include
+#include
+#include
+namespace gl {
+extern void initModuleGl();
+}
-class OffscreenQmlSurface : public hifi::qml::OffscreenSurface {
+class QTestItem : public QQuickItem {
+ Q_OBJECT
+public:
+ QTestItem(QQuickItem* parent = nullptr) : QQuickItem(parent) { qDebug() << __FUNCTION__; }
+ ~QTestItem() { qDebug() << __FUNCTION__; }
+};
+
+QUrl getTestResource(const QString& relativePath) {
+ static QString dir;
+ if (dir.isEmpty()) {
+ QDir path(__FILE__);
+ path.cdUp();
+ dir = path.cleanPath(path.absoluteFilePath("../")) + "/";
+ qDebug() << "Resources Path: " << dir;
+ }
+ return QUrl::fromLocalFile(dir + relativePath);
+}
+
+#define DIVISIONS_X 5
+#define DIVISIONS_Y 5
+
+using QmlPtr = QSharedPointer;
+using TextureAndFence = hifi::qml::OffscreenSurface::TextureAndFence;
+
+struct QmlInfo {
+ QmlPtr surface;
+ GLuint texture{ 0 };
+ uint64_t lifetime{ 0 };
};
class TestWindow : public QWindow {
-
public:
TestWindow();
-
private:
- using TextureAndFence = hifi::qml::OffscreenSurface::TextureAndFence;
QOpenGLContext _glContext;
OffscreenGLCanvas _sharedContext;
- OffscreenQmlSurface _offscreenQml;
+ std::array, DIVISIONS_X> _surfaces;
+
QOpenGLFunctions_4_5_Core _glf;
- uint32_t _currentTexture{ 0 };
- GLsync _readFence{ 0 };
std::function _discardLamdba;
QSize _size;
+ size_t _surfaceCount{ 0 };
GLuint _fbo{ 0 };
const QSize _qmlSize{ 640, 480 };
bool _aboutToQuit{ false };
+ uint64_t _createStopTime;
void initGl();
+ void updateSurfaces();
+ void buildSurface(QmlInfo& qmlInfo, bool allowVideo);
+ void destroySurface(QmlInfo& qmlInfo);
void resizeWindow(const QSize& size);
void draw();
void resizeEvent(QResizeEvent* ev) override;
};
TestWindow::TestWindow() {
- setSurfaceType(QSurface::OpenGLSurface);
+ Setting::init();
+ setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
@@ -83,13 +118,16 @@ TestWindow::TestWindow() {
QSurfaceFormat::setDefaultFormat(format);
setFormat(format);
+ qmlRegisterType("Hifi", 1, 0, "TestItem");
+
show();
+ _createStopTime = usecTimestampNow() + (3000u * USECS_PER_SECOND);
resize(QSize(800, 600));
auto timer = new QTimer(this);
timer->setTimerType(Qt::PreciseTimer);
- timer->setInterval(5);
+ timer->setInterval(30);
connect(timer, &QTimer::timeout, [&] { draw(); });
timer->start();
@@ -97,7 +135,6 @@ TestWindow::TestWindow() {
timer->stop();
_aboutToQuit = true;
});
-
}
void TestWindow::initGl() {
@@ -105,6 +142,7 @@ void TestWindow::initGl() {
if (!_glContext.create() || !_glContext.makeCurrent(this)) {
qFatal("Unable to intialize Window GL context");
}
+ gl::initModuleGl();
_glf.initializeOpenGLFunctions();
_glf.glCreateFramebuffers(1, &_fbo);
@@ -113,15 +151,97 @@ void TestWindow::initGl() {
qFatal("Unable to intialize Shared GL context");
}
hifi::qml::OffscreenSurface::setSharedContext(_sharedContext.getContext());
- _discardLamdba = _offscreenQml.getDiscardLambda();
- _offscreenQml.resize({ 640, 480 });
- _offscreenQml.load(QUrl::fromLocalFile("C:/Users/bdavi/Git/hifi/tests/qml/qml/main.qml"));
+ _discardLamdba = hifi::qml::OffscreenSurface::getDiscardLambda();
}
void TestWindow::resizeWindow(const QSize& size) {
_size = size;
}
+static const int DEFAULT_MAX_FPS = 10;
+static const QString CONTROL_URL{ "/qml/controls/WebEntityView.qml" };
+static const char* URL_PROPERTY{ "url" };
+
+QString getSourceUrl(bool video) {
+ static const std::vector SOURCE_URLS{
+ "https://www.reddit.com/wiki/random",
+ "https://en.wikipedia.org/wiki/Wikipedia:Random",
+ "https://slashdot.org/",
+ };
+
+ static const std::vector VIDEO_SOURCE_URLS{
+ "https://www.youtube.com/watch?v=gDXwhHm4GhM",
+ "https://www.youtube.com/watch?v=Ch_hoYPPeGc",
+ };
+
+ const auto& sourceUrls = video ? VIDEO_SOURCE_URLS : SOURCE_URLS;
+ auto index = rand() % sourceUrls.size();
+ return sourceUrls[index];
+}
+
+void TestWindow::buildSurface(QmlInfo& qmlInfo, bool video) {
+ ++_surfaceCount;
+ auto lifetimeSecs = (uint32_t)(5.0f + (randFloat() * 10.0f));
+ auto lifetimeUsecs = (USECS_PER_SECOND * lifetimeSecs);
+ qmlInfo.lifetime = lifetimeUsecs + usecTimestampNow();
+ qmlInfo.texture = 0;
+ qmlInfo.surface.reset(new hifi::qml::OffscreenSurface());
+ qmlInfo.surface->load(getTestResource(CONTROL_URL), [video](QQmlContext* context, QQuickItem* item) {
+ item->setProperty(URL_PROPERTY, getSourceUrl(video));
+ });
+ qmlInfo.surface->setMaxFps(DEFAULT_MAX_FPS);
+ qmlInfo.surface->resize(_qmlSize);
+ qmlInfo.surface->resume();
+}
+
+void TestWindow::destroySurface(QmlInfo& qmlInfo) {
+ auto& surface = qmlInfo.surface;
+ auto webView = surface->getRootItem();
+ if (webView) {
+ // stop loading
+ QMetaObject::invokeMethod(webView, "stop");
+ webView->setProperty(URL_PROPERTY, "about:blank");
+ }
+ surface->pause();
+ surface.reset();
+}
+
+void TestWindow::updateSurfaces() {
+ auto now = usecTimestampNow();
+ // Fetch any new textures
+ for (size_t x = 0; x < DIVISIONS_X; ++x) {
+ for (size_t y = 0; y < DIVISIONS_Y; ++y) {
+ auto& qmlInfo = _surfaces[x][y];
+ if (!qmlInfo.surface) {
+ if (now < _createStopTime && randFloat() > 0.99f) {
+ buildSurface(qmlInfo, x == 0 && y == 0);
+ } else {
+ continue;
+ }
+ }
+
+ if (now > qmlInfo.lifetime) {
+ destroySurface(qmlInfo);
+ continue;
+ }
+
+ auto& surface = qmlInfo.surface;
+ auto& currentTexture = qmlInfo.texture;
+
+ TextureAndFence newTextureAndFence;
+ if (surface->fetchTexture(newTextureAndFence)) {
+ if (currentTexture != 0) {
+ auto readFence = _glf.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ _discardLamdba(currentTexture, readFence);
+ }
+ currentTexture = newTextureAndFence.first;
+ _glf.glWaitSync((GLsync)newTextureAndFence.second, 0, GL_TIMEOUT_IGNORED);
+ }
+ }
+ }
+}
+
void TestWindow::draw() {
if (_aboutToQuit) {
return;
@@ -140,38 +260,30 @@ void TestWindow::draw() {
return;
}
+ updateSurfaces();
+
+ auto size = this->geometry().size();
+ auto incrementX = size.width() / DIVISIONS_X;
+ auto incrementY = size.height() / DIVISIONS_Y;
+ _glf.glViewport(0, 0, size.width(), size.height());
_glf.glClearColor(1, 0, 0, 1);
_glf.glClear(GL_COLOR_BUFFER_BIT);
-
- TextureAndFence newTextureAndFence;
- if (_offscreenQml.fetchTexture(newTextureAndFence)) {
- if (_currentTexture) {
- _discardLamdba(_currentTexture, _readFence);
- _readFence = 0;
+ for (uint32_t x = 0; x < DIVISIONS_X; ++x) {
+ for (uint32_t y = 0; y < DIVISIONS_Y; ++y) {
+ auto& qmlInfo = _surfaces[x][y];
+ if (!qmlInfo.surface || !qmlInfo.texture) {
+ continue;
+ }
+ _glf.glNamedFramebufferTexture(_fbo, GL_COLOR_ATTACHMENT0, qmlInfo.texture, 0);
+ _glf.glBlitNamedFramebuffer(_fbo, 0,
+ // src coordinates
+ 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1,
+ // dst coordinates
+ incrementX * x, incrementY * y, incrementX * (x + 1), incrementY * (y + 1),
+ // blit mask and filter
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
-
- _currentTexture = newTextureAndFence.first;
- _glf.glWaitSync((GLsync)newTextureAndFence.second, 0, GL_TIMEOUT_IGNORED);
- _glf.glNamedFramebufferTexture(_fbo, GL_COLOR_ATTACHMENT0, _currentTexture, 0);
}
-
- auto diff = _size - _qmlSize;
- diff /= 2;
- auto qmlExtent = diff + _qmlSize;
-
- if (_currentTexture) {
- _glf.glBlitNamedFramebuffer(_fbo, 0,
- 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1,
- diff.width(), diff.height(), qmlExtent.width() - 1, qmlExtent.height() - 2,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
-
- if (_readFence) {
- _glf.glDeleteSync(_readFence);
- }
- _readFence = _glf.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- _glf.glFlush();
-
_glContext.swapBuffers(this);
}
@@ -180,11 +292,9 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
}
int main(int argc, char** argv) {
- setupHifiApplication("QML Test");
-
QGuiApplication app(argc, argv);
TestWindow window;
- app.exec();
- return 0;
+ return app.exec();
}
+#include "main.moc"
diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt
index fd4d8d88dd..d688474379 100644
--- a/tests/render-perf/CMakeLists.txt
+++ b/tests/render-perf/CMakeLists.txt
@@ -27,6 +27,10 @@ if (WIN32)
add_dependency_external_projects(wasapi)
endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ target_link_libraries(${TARGET_NAME} atomic)
+endif()
+
package_libraries_for_deployment()
diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js
index 7c643d398c..5092e8b809 100644
--- a/tools/jsdoc/plugins/hifi.js
+++ b/tools/jsdoc/plugins/hifi.js
@@ -94,20 +94,20 @@ exports.handlers = {
if (e.doclet.hifiInterface) {
rows.push("Interface Scripts");
}
- if (e.doclet.hifiAssignmentClient) {
- rows.push("Assignment Client Scripts");
- }
if (e.doclet.hifiClientEntity) {
rows.push("Client Entity Scripts");
}
if (e.doclet.hifiServerEntity) {
rows.push("Server Entity Scripts");
}
+ if (e.doclet.hifiAssignmentClient) {
+ rows.push("Assignment Client Scripts");
+ }
// Append an Available In: table at the end of the namespace description.
if (rows.length > 0) {
- var table = "
Available In: | " + rows.join(" | ") + " |
";
- e.doclet.description = e.doclet.description + table;
+ var table = "
Available in: | " + rows.join(" | ") + " |
---|
";
+ e.doclet.description = (e.doclet.description ? e.doclet.description : "") + table;
}
}
}
@@ -124,7 +124,7 @@ exports.defineTags = function (dictionary) {
});
// @hifi-assignment-client
- dictionary.defineTag("hifi-assigment-client", {
+ dictionary.defineTag("hifi-assignment-client", {
onTagged: function (doclet, tag) {
doclet.hifiAssignmentClient = true;
}