diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp
index f09caac4b6..f3da74ce5e 100644
--- a/assignment-client/src/avatars/AvatarMixer.cpp
+++ b/assignment-client/src/avatars/AvatarMixer.cpp
@@ -200,7 +200,7 @@ void AvatarMixer::manageDisplayName(const SharedNodePointer& node) {
QString baseName = avatar.getDisplayName().trimmed();
const QRegularExpression curses { "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
- const QRegularExpression trailingDigits { "\\s*_\\d+$" }; // whitespace "_123"
+ const QRegularExpression trailingDigits { "\\s*(_\\d+\\s*)?(\\s*\\n[^$]*)?$" }; // trailing whitespace "_123" and any subsequent lines
baseName = baseName.remove(trailingDigits);
if (baseName.isEmpty()) {
baseName = "anonymous";
diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml
index c4e0c85642..47fb610469 100644
--- a/interface/resources/qml/Browser.qml
+++ b/interface/resources/qml/Browser.qml
@@ -2,6 +2,7 @@ import QtQuick 2.5
import QtQuick.Controls 1.2
import QtWebChannel 1.0
import QtWebEngine 1.2
+import FileTypeProfile 1.0
import "controls-uit"
import "styles" as HifiStyles
@@ -216,6 +217,11 @@ ScrollingWindow {
WebChannel.id: "eventBridgeWrapper"
property var eventBridge;
}
+
+ profile: FileTypeProfile {
+ id: webviewProfile
+ storageName: "qmlWebEngine"
+ }
webChannel.registeredObjects: [eventBridgeWrapper]
diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml
index 17e6578e4d..d6459afd08 100644
--- a/interface/resources/qml/Stats.qml
+++ b/interface/resources/qml/Stats.qml
@@ -130,7 +130,7 @@ Item {
id: pingCol
spacing: 4; x: 4; y: 4;
StatText {
- text: "Audio ping: " + root.audioPing
+ text: "Audio ping/loss: " + root.audioPing + "/" + root.audioPacketLoss + "%"
}
StatText {
text: "Avatar ping: " + root.avatarPing
diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml
index 2650102b27..74318a165e 100644
--- a/interface/resources/qml/TabletBrowser.qml
+++ b/interface/resources/qml/TabletBrowser.qml
@@ -104,6 +104,7 @@ Item {
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
+ urlAppend(loadRequest.url.toString())
var url = loadRequest.url.toString();
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
@@ -113,12 +114,6 @@ Item {
}
}
- onNavigationRequested: {
- if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) {
- pagesModel.append({webUrl: request.url.toString()})
- }
- }
-
onNewViewRequested: {
request.openIn(webView);
}
diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml
index 50d6e1c504..ee26a32a85 100644
--- a/interface/resources/qml/controls/TabletWebView.qml
+++ b/interface/resources/qml/controls/TabletWebView.qml
@@ -117,7 +117,7 @@ Item {
}
function gotoPage(url) {
- pagesModel.append({webUrl: url})
+ urlAppend(url)
}
function reloadPage() {
@@ -126,9 +126,20 @@ Item {
view.setEnabled(true);
}
+ function urlAppend(url) {
+ var lurl = decodeURIComponent(url)
+ if (lurl[lurl.length - 1] !== "/")
+ lurl = lurl + "/"
+ if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== lurl) {
+ pagesModel.append({webUrl: lurl})
+ }
+ }
+
onCurrentPageChanged: {
if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
loader.item.url = pagesModel.get(currentPage).webUrl
+ web.url = loader.item.url
+ web.address = loader.item.url
}
}
@@ -160,6 +171,7 @@ Item {
if (currentPage >= 0) {
//we got something to load already
item.url = pagesModel.get(currentPage).webUrl
+ web.address = loader.item.url
}
}
}
diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml
new file mode 100644
index 0000000000..a3d5fe903b
--- /dev/null
+++ b/interface/resources/qml/controls/WebEntityView.qml
@@ -0,0 +1,22 @@
+//
+// 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 "."
+import FileTypeProfile 1.0
+
+WebView {
+ viewProfile: FileTypeProfile {
+ id: webviewProfile
+ storageName: "qmlWebEngine"
+ }
+
+ urlTag: "noDownload=true";
+}
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index a3badd7e1f..52f277520f 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -10,6 +10,7 @@ Item {
property alias eventBridge: eventBridgeWrapper.eventBridge
property alias canGoBack: root.canGoBack;
property var goBack: root.goBack;
+ property alias urlTag: root.urlTag
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
property bool keyboardRaised: false
property bool punctuationMode: false
@@ -27,6 +28,8 @@ Item {
WebChannel.id: "eventBridgeWrapper"
property var eventBridge;
}
+
+ property alias viewProfile: root.profile
WebEngineView {
id: root
@@ -66,6 +69,8 @@ Item {
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
worldId: WebEngineScript.MainWorld
}
+
+ property string urlTag: "noDownload=false";
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
@@ -94,6 +99,7 @@ Item {
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
var url = loadRequest.url.toString();
+ url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
root.stop();
diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml
index 217cfec707..b72901fbdf 100644
--- a/interface/resources/qml/hifi/Card.qml
+++ b/interface/resources/qml/hifi/Card.qml
@@ -243,12 +243,7 @@ Rectangle {
}
}
}
- DropShadow {
- anchors.fill: actionIcon
- radius: 8.0
- color: "#80000000"
- source: actionIcon
- }
+
MouseArea {
id: messageArea;
width: rectIcon.width;
diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml
index 8905ed9c17..e328805d74 100644
--- a/interface/resources/qml/hifi/ComboDialog.qml
+++ b/interface/resources/qml/hifi/ComboDialog.qml
@@ -12,6 +12,7 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import "../styles-uit"
+import "../controls-uit"
Item {
property var dialogTitleText : "";
@@ -67,6 +68,29 @@ Item {
verticalAlignment: Text.AlignTop;
}
+ HiFiGlyphs {
+ id: closeGlyphButton;
+ text: hifi.glyphs.close;
+ size: 32;
+ anchors.verticalCenter: dialogTitle.verticalCenter;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ MouseArea {
+ anchors.fill: closeGlyphButton;
+ hoverEnabled: true;
+ onEntered: {
+ parent.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ parent.text = hifi.glyphs.close;
+ }
+ onClicked: {
+ combo.visible = false;
+ }
+ }
+ }
+
+
ListModel {
id: comboListViewModel;
}
@@ -92,8 +116,7 @@ Item {
color: selectedOptionIndex === index ? '#cee6ff' : 'white';
Rectangle {
id: comboOptionSelected;
- visible: selectedOptionIndex === index ? true : false;
- color: hifi.colors.blueAccent;
+ color: selectedOptionIndex == index ? hifi.colors.blueAccent : 'white';
anchors.left: parent.left;
anchors.leftMargin: 20;
anchors.top: parent.top;
@@ -102,7 +125,7 @@ Item {
height: width;
radius: width;
border.width: 3;
- border.color: hifi.colors.blueHighlight;
+ border.color: selectedOptionIndex === index ? hifi.colors.blueHighlight: hifi.colors.lightGrayText;
}
diff --git a/interface/resources/qml/hifi/LetterboxMessage.qml b/interface/resources/qml/hifi/LetterboxMessage.qml
index e50d1de547..754876b2c1 100644
--- a/interface/resources/qml/hifi/LetterboxMessage.qml
+++ b/interface/resources/qml/hifi/LetterboxMessage.qml
@@ -85,6 +85,28 @@ Item {
wrapMode: Text.WordWrap
textFormat: Text.StyledText
}
+ HiFiGlyphs {
+ id: closeGlyphButton
+ text: hifi.glyphs.close
+ size: headerTextPixelSize
+ anchors.top: parent.top
+ anchors.topMargin: -20
+ anchors.right: parent.right
+ anchors.rightMargin: -25
+ MouseArea {
+ anchors.fill: closeGlyphButton
+ hoverEnabled: true
+ onEntered: {
+ parent.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ parent.text = hifi.glyphs.close;
+ }
+ onClicked: {
+ letterbox.visible = false;
+ }
+ }
+ }
}
// Popup Text
Text {
diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml
index fe27f40190..d785a8582c 100644
--- a/interface/resources/qml/hifi/Pal.qml
+++ b/interface/resources/qml/hifi/Pal.qml
@@ -310,9 +310,9 @@ Rectangle {
hoverEnabled: true;
onClicked: letterbox(hifi.glyphs.question,
"Connections and Friends",
- "Purple borders around profile pictures are Connections.
" +
+ "Purple borders around profile pictures represent Connections.
" +
"When your availability is set to Everyone, Connections can see your username and location.
" +
- "Green borders around profile pictures are Friends.
" +
+ "Green borders around profile pictures represent Friends.
" +
"When your availability is set to Friends, only Friends can see your username and location.");
onEntered: connectionsHelpText.color = hifi.colors.blueHighlight;
onExited: connectionsHelpText.color = hifi.colors.blueAccent;
diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
index 489fbdb3c9..39892f27a4 100644
--- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
+++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
@@ -33,14 +33,25 @@ StackView {
property int cardHeight: 320;
property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/";
+ property var tablet: null;
+ property bool isDesktop: false;
+
Component { id: tabletStoryCard; TabletStoryCard {} }
Component.onCompleted: {
root.currentItem.focus = true;
root.currentItem.forceActiveFocus();
+ addressLine.focus = true;
+ addressLine.forceActiveFocus();
fillDestinations();
updateLocationText(false);
root.parentChanged.connect(center);
center();
+ isDesktop = (typeof desktop !== "undefined");
+ tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+
+ if (desktop) {
+ root.title = "GOTO";
+ }
}
Component.onDestruction: {
root.parentChanged.disconnect(center);
@@ -108,6 +119,8 @@ StackView {
onClicked: {
addressBarDialog.loadHome();
tabletRoot.shown = false;
+ tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+ tablet.gotoHomeScreen();
}
anchors {
left: parent.left
@@ -294,6 +307,7 @@ StackView {
right: parent.right
leftMargin: 10
}
+
model: suggestions
orientation: ListView.Vertical
@@ -547,6 +561,13 @@ StackView {
if (addressLine.text !== "") {
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
}
+
+ if (isDesktop) {
+ tablet.gotoHomeScreen();
+ } else {
+ HMD.closeTablet();
+ }
+
tabletRoot.shown = false;
}
diff --git a/interface/resources/qml/hifi/toolbars/StateImage.qml b/interface/resources/qml/hifi/toolbars/StateImage.qml
index e0389c5e02..ebf1544f2b 100644
--- a/interface/resources/qml/hifi/toolbars/StateImage.qml
+++ b/interface/resources/qml/hifi/toolbars/StateImage.qml
@@ -12,7 +12,10 @@ Item {
property bool pinned: false
clip: true
- function updateYOffset() { yOffset = size * buttonState; }
+ function updateYOffset() {
+ //make sure offset not set outside image
+ yOffset = (size * buttonState >= image.height) ? image.height - size : size * buttonState
+ }
onButtonStateChanged: updateYOffset();
Component.onCompleted: {
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 778df09588..1717039423 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -142,6 +142,7 @@
#include "ModelPackager.h"
#include "networking/HFWebEngineProfile.h"
#include "networking/HFTabletWebEngineProfile.h"
+#include "networking/FileTypeProfile.h"
#include "scripting/TestScriptingInterface.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AssetMappingsScriptingInterface.h"
@@ -218,6 +219,7 @@ static const QString FST_EXTENSION = ".fst";
static const QString FBX_EXTENSION = ".fbx";
static const QString OBJ_EXTENSION = ".obj";
static const QString AVA_JSON_EXTENSION = ".ava.json";
+static const QString WEB_VIEW_TAG = "noDownload=true";
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
@@ -1934,6 +1936,7 @@ void Application::initializeUi() {
qmlRegisterType("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
qmlRegisterType("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
+ qmlRegisterType("FileTypeProfile", 1, 0, "FileTypeProfile");
auto offscreenUi = DependencyManager::get();
offscreenUi->create(_glWidget->qglContext());
@@ -2010,6 +2013,7 @@ void Application::initializeUi() {
rootContext->setContextProperty("SoundCache", DependencyManager::get().data());
rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
+ rootContext->setContextProperty("Tablet", DependencyManager::get().data());
rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
rootContext->setContextProperty("FaceTracker", DependencyManager::get().data());
@@ -5545,7 +5549,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
bool Application::canAcceptURL(const QString& urlString) const {
QUrl url(urlString);
- if (urlString.startsWith(HIFI_URL_SCHEME)) {
+ if (url.query().contains(WEB_VIEW_TAG)) {
+ return false;
+ } else if (urlString.startsWith(HIFI_URL_SCHEME)) {
return true;
}
QHashIterator i(_acceptedExtensions);
@@ -5653,7 +5659,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
QUrl scriptURL { scriptFilenameOrURL };
if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
- shortName = shortName.mid(shortName.lastIndexOf('/') + 1);
+ int startIndex = shortName.lastIndexOf('/') + 1;
+ int endIndex = shortName.lastIndexOf('?');
+ shortName = shortName.mid(startIndex, endIndex - startIndex);
}
QString message = "Would you like to run this script:\n" + shortName;
diff --git a/interface/src/networking/FileTypeProfile.cpp b/interface/src/networking/FileTypeProfile.cpp
new file mode 100644
index 0000000000..6fcd8df669
--- /dev/null
+++ b/interface/src/networking/FileTypeProfile.cpp
@@ -0,0 +1,26 @@
+//
+// FileTypeProfile.cpp
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#include "FileTypeProfile.h"
+
+#include "FileTypeRequestInterceptor.h"
+
+static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine";
+
+FileTypeProfile::FileTypeProfile(QObject* parent) :
+ QQuickWebEngineProfile(parent)
+{
+ static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
+ setHttpUserAgent(WEB_ENGINE_USER_AGENT);
+
+ auto requestInterceptor = new FileTypeRequestInterceptor(this);
+ setRequestInterceptor(requestInterceptor);
+}
diff --git a/interface/src/networking/FileTypeProfile.h b/interface/src/networking/FileTypeProfile.h
new file mode 100644
index 0000000000..f922fd66de
--- /dev/null
+++ b/interface/src/networking/FileTypeProfile.h
@@ -0,0 +1,25 @@
+//
+// FileTypeProfile.h
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#pragma once
+
+#ifndef hifi_FileTypeProfile_h
+#define hifi_FileTypeProfile_h
+
+#include
+
+class FileTypeProfile : public QQuickWebEngineProfile {
+public:
+ FileTypeProfile(QObject* parent = Q_NULLPTR);
+};
+
+
+#endif // hifi_FileTypeProfile_h
diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/interface/src/networking/FileTypeRequestInterceptor.cpp
new file mode 100644
index 0000000000..91bacd46a6
--- /dev/null
+++ b/interface/src/networking/FileTypeRequestInterceptor.cpp
@@ -0,0 +1,21 @@
+//
+// FileTypeRequestInterceptor.cpp
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#include "FileTypeRequestInterceptor.h"
+
+#include
+
+#include "RequestFilters.h"
+
+void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
+ RequestFilters::interceptHFWebEngineRequest(info);
+ RequestFilters::interceptFileType(info);
+}
diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/interface/src/networking/FileTypeRequestInterceptor.h
new file mode 100644
index 0000000000..be971daf7a
--- /dev/null
+++ b/interface/src/networking/FileTypeRequestInterceptor.h
@@ -0,0 +1,26 @@
+//
+// FileTypeRequestInterceptor.h
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#pragma once
+
+#ifndef hifi_FileTypeRequestInterceptor_h
+#define hifi_FileTypeRequestInterceptor_h
+
+#include
+
+class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor {
+public:
+ FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {};
+
+ virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override;
+};
+
+#endif // hifi_FileTypeRequestInterceptor_h
diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp
index f6b0914f08..59897d427f 100644
--- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp
+++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp
@@ -10,35 +10,12 @@
//
#include "HFWebEngineRequestInterceptor.h"
-#include "NetworkingConstants.h"
#include
#include
-
-bool isAuthableHighFidelityURL(const QUrl& url) {
- static const QStringList HF_HOSTS = {
- "highfidelity.com", "highfidelity.io",
- "metaverse.highfidelity.com", "metaverse.highfidelity.io"
- };
- const auto& scheme = url.scheme();
- const auto& host = url.host();
-
- return (scheme == "https" && HF_HOSTS.contains(host)) ||
- ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
-}
+#include "RequestFilters.h"
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
- // check if this is a request to a highfidelity URL
- if (isAuthableHighFidelityURL(info.requestUrl())) {
- // if we have an access token, add it to the right HTTP header for authorization
- auto accountManager = DependencyManager::get();
-
- if (accountManager->hasValidAccessToken()) {
- static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
-
- QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
- info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
- }
- }
+ RequestFilters::interceptHFWebEngineRequest(info);
}
diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp
new file mode 100644
index 0000000000..fedde94f15
--- /dev/null
+++ b/interface/src/networking/RequestFilters.cpp
@@ -0,0 +1,65 @@
+//
+// RequestFilters.cpp
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#include "RequestFilters.h"
+#include "NetworkingConstants.h"
+
+#include
+
+#include
+
+namespace {
+
+ bool isAuthableHighFidelityURL(const QUrl& url) {
+ static const QStringList HF_HOSTS = {
+ "highfidelity.com", "highfidelity.io",
+ "metaverse.highfidelity.com", "metaverse.highfidelity.io"
+ };
+ const auto& scheme = url.scheme();
+ const auto& host = url.host();
+
+ return (scheme == "https" && HF_HOSTS.contains(host)) ||
+ ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
+ }
+
+ bool isScript(const QString filename) {
+ return filename.endsWith(".js", Qt::CaseInsensitive);
+ }
+
+ bool isJSON(const QString filename) {
+ return filename.endsWith(".json", Qt::CaseInsensitive);
+ }
+
+}
+
+void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) {
+ // check if this is a request to a highfidelity URL
+ if (isAuthableHighFidelityURL(info.requestUrl())) {
+ // if we have an access token, add it to the right HTTP header for authorization
+ auto accountManager = DependencyManager::get();
+
+ if (accountManager->hasValidAccessToken()) {
+ static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
+
+ QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
+ info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
+ }
+ }
+}
+
+void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) {
+ QString filename = info.requestUrl().fileName();
+ if (isScript(filename) || isJSON(filename)) {
+ static const QString CONTENT_HEADER = "Accept";
+ static const QString TYPE_VALUE = "text/plain,text/html";
+ info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit());
+ }
+}
diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h
new file mode 100644
index 0000000000..0d7d66e155
--- /dev/null
+++ b/interface/src/networking/RequestFilters.h
@@ -0,0 +1,28 @@
+//
+// RequestFilters.h
+// interface/src/networking
+//
+// Created by Kunal Gosar on 2017-03-10.
+// 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
+//
+
+#pragma once
+
+#ifndef hifi_RequestFilters_h
+#define hifi_RequestFilters_h
+
+#include
+#include
+
+class RequestFilters : public QObject {
+ Q_OBJECT
+
+public:
+ static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info);
+ static void interceptFileType(QWebEngineUrlRequestInfo& info);
+};
+
+#endif // hifi_RequestFilters_h
diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp
index 402e27e256..a95ac8d91f 100644
--- a/interface/src/ui/DialogsManager.cpp
+++ b/interface/src/ui/DialogsManager.cpp
@@ -31,6 +31,7 @@
#include "TabletScriptingInterface.h"
#include "scripting/HMDScriptingInterface.h"
+static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml";
template
void DialogsManager::maybeCreateDialog(QPointer& member) {
if (!member) {
@@ -46,12 +47,48 @@ void DialogsManager::maybeCreateDialog(QPointer& member) {
}
void DialogsManager::toggleAddressBar() {
- AddressBarDialog::toggle();
- emit addressBarToggled();
+ auto hmd = DependencyManager::get();
+ auto tabletScriptingInterface = DependencyManager::get();
+ auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
+ if (tablet->getToolbarMode()) {
+ if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) {
+ tablet->gotoHomeScreen();
+ emit addressBarToggled();
+ } else {
+ tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
+ emit addressBarToggled();
+ }
+ } else {
+ if (hmd->getShouldShowTablet()) {
+ if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG) && _closeAddressBar) {
+ tablet->gotoHomeScreen();
+ hmd->closeTablet();
+ _closeAddressBar = false;
+ emit addressBarToggled();
+ } else {
+ tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
+ _closeAddressBar = true;
+ emit addressBarToggled();
+ }
+ } else {
+ tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
+ hmd->openTablet();
+ _closeAddressBar = true;
+ emit addressBarToggled();
+ }
+
+ }
}
void DialogsManager::showAddressBar() {
- AddressBarDialog::show();
+ auto hmd = DependencyManager::get();
+ auto tabletScriptingInterface = DependencyManager::get();
+ auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
+ tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
+
+ if (!hmd->getShouldShowTablet()) {
+ hmd->openTablet();
+ }
}
void DialogsManager::showFeed() {
diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h
index 608195aca7..24b9078baf 100644
--- a/interface/src/ui/DialogsManager.h
+++ b/interface/src/ui/DialogsManager.h
@@ -79,6 +79,7 @@ private:
QPointer _octreeStatsDialog;
QPointer _testingDialog;
QPointer _domainConnectionDialog;
+ bool _closeAddressBar { false };
};
#endif // hifi_DialogsManager_h
diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp
index cedcb923d9..dc612b0129 100644
--- a/interface/src/ui/Stats.cpp
+++ b/interface/src/ui/Stats.cpp
@@ -126,7 +126,7 @@ void Stats::updateStats(bool force) {
STAT_UPDATE(updatedAvatarCount, avatarManager->getNumAvatarsUpdated());
STAT_UPDATE(notUpdatedAvatarCount, avatarManager->getNumAvatarsNotUpdated());
STAT_UPDATE(serverCount, (int)nodeList->size());
- STAT_UPDATE(framerate, qApp->getFps());
+ STAT_UPDATE_FLOAT(framerate, qApp->getFps(), 0.1f);
if (qApp->getActiveDisplayPlugin()) {
auto displayPlugin = qApp->getActiveDisplayPlugin();
auto stats = displayPlugin->getHardwareStats();
@@ -134,11 +134,11 @@ void Stats::updateStats(bool force) {
STAT_UPDATE(longrenders, stats["long_render_count"].toInt());
STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt());
STAT_UPDATE(longframes, stats["long_frame_count"].toInt());
- STAT_UPDATE(renderrate, displayPlugin->renderRate());
- STAT_UPDATE(presentrate, displayPlugin->presentRate());
- STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
- STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate());
- STAT_UPDATE(stutterrate, displayPlugin->stutterRate());
+ STAT_UPDATE_FLOAT(renderrate, displayPlugin->renderRate(), 0.1f);
+ STAT_UPDATE_FLOAT(presentrate, displayPlugin->presentRate(), 0.1f);
+ STAT_UPDATE_FLOAT(presentnewrate, displayPlugin->newFramePresentRate(), 0.1f);
+ STAT_UPDATE_FLOAT(presentdroprate, displayPlugin->droppedFrameRate(), 0.1f);
+ STAT_UPDATE_FLOAT(stutterrate, displayPlugin->stutterRate(), 0.1f);
} else {
STAT_UPDATE(appdropped, -1);
STAT_UPDATE(longrenders, -1);
@@ -151,8 +151,8 @@ void Stats::updateStats(bool force) {
STAT_UPDATE(avatarSimrate, (int)qApp->getAvatarSimrate());
auto bandwidthRecorder = DependencyManager::get();
- STAT_UPDATE(packetInCount, bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond());
- STAT_UPDATE(packetOutCount, bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond());
+ STAT_UPDATE(packetInCount, (int)bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond());
+ STAT_UPDATE(packetOutCount, (int)bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond());
STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f);
STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 1000.0f, 0.01f);
@@ -164,7 +164,11 @@ void Stats::updateStats(bool force) {
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer);
SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer);
- STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1);
+ STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1);
+ const int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f);
+ const int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f);
+ const int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate;
+ STAT_UPDATE(audioPacketLoss, audioMixerNode ? largestLossRate : -1);
STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1);
STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1);
STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1);
@@ -196,36 +200,36 @@ void Stats::updateStats(bool force) {
if (_expanded || force) {
SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer);
if (avatarMixer) {
- STAT_UPDATE(avatarMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
- STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
- STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
- STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
+ STAT_UPDATE(avatarMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
+ STAT_UPDATE(avatarMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
+ STAT_UPDATE(avatarMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
+ STAT_UPDATE(avatarMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
} else {
STAT_UPDATE(avatarMixerInKbps, -1);
STAT_UPDATE(avatarMixerInPps, -1);
STAT_UPDATE(avatarMixerOutKbps, -1);
STAT_UPDATE(avatarMixerOutPps, -1);
}
- STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate());
+ STAT_UPDATE_FLOAT(myAvatarSendRate, avatarManager->getMyAvatarSendRate(), 0.1f);
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
auto audioClient = DependencyManager::get();
if (audioMixerNode || force) {
- STAT_UPDATE(audioMixerKbps, roundf(
+ STAT_UPDATE(audioMixerKbps, (int)roundf(
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +
bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioMixerPps, roundf(
+ STAT_UPDATE(audioMixerPps, (int)roundf(
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) +
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
- STAT_UPDATE(audioAudioInboundPPS, audioClient->getAudioInboundPPS());
- STAT_UPDATE(audioSilentInboundPPS, audioClient->getSilentInboundPPS());
- STAT_UPDATE(audioOutboundPPS, audioClient->getAudioOutboundPPS());
- STAT_UPDATE(audioSilentOutboundPPS, audioClient->getSilentOutboundPPS());
+ STAT_UPDATE(audioMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
+ STAT_UPDATE(audioMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
+ STAT_UPDATE(audioMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
+ STAT_UPDATE(audioMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
+ STAT_UPDATE(audioAudioInboundPPS, (int)audioClient->getAudioInboundPPS());
+ STAT_UPDATE(audioSilentInboundPPS, (int)audioClient->getSilentInboundPPS());
+ STAT_UPDATE(audioOutboundPPS, (int)audioClient->getAudioOutboundPPS());
+ STAT_UPDATE(audioSilentOutboundPPS, (int)audioClient->getSilentOutboundPPS());
} else {
STAT_UPDATE(audioMixerKbps, -1);
STAT_UPDATE(audioMixerPps, -1);
diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h
index a93a255a06..85cf2caab9 100644
--- a/interface/src/ui/Stats.h
+++ b/interface/src/ui/Stats.h
@@ -81,6 +81,7 @@ class Stats : public QQuickItem {
STATS_PROPERTY(int, audioSilentOutboundPPS, 0)
STATS_PROPERTY(int, audioAudioInboundPPS, 0)
STATS_PROPERTY(int, audioSilentInboundPPS, 0)
+ STATS_PROPERTY(int, audioPacketLoss, 0)
STATS_PROPERTY(QString, audioCodec, QString())
STATS_PROPERTY(QString, audioNoiseGate, QString())
@@ -204,6 +205,7 @@ signals:
void audioSilentOutboundPPSChanged();
void audioAudioInboundPPSChanged();
void audioSilentInboundPPSChanged();
+ void audioPacketLossChanged();
void audioCodecChanged();
void audioNoiseGateChanged();
@@ -263,4 +265,3 @@ private:
};
#endif // hifi_Stats_h
-
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index 0cd5b718af..91a4fc2ff9 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -277,10 +277,11 @@ bool RenderableModelEntityItem::getAnimationFrame() {
return false;
}
- if (_animation && _animation->isLoaded()) {
+ auto animation = getAnimation();
+ if (animation && animation->isLoaded()) {
- const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
- auto& fbxJoints = _animation->getGeometry().joints;
+ const QVector& frames = animation->getFramesReference(); // NOTE: getFrames() is too heavy
+ auto& fbxJoints = animation->getGeometry().joints;
int frameCount = frames.size();
if (frameCount > 0) {
@@ -566,7 +567,7 @@ void RenderableModelEntityItem::update(const quint64& now) {
}
// make a copy of the animation properites
- _renderAnimationProperties = _animationProperties;
+ _renderAnimationProperties = getAnimationProperties();
ModelEntityItem::update(now);
}
@@ -608,11 +609,11 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
void RenderableModelEntityItem::setShapeType(ShapeType type) {
ModelEntityItem::setShapeType(type);
- if (_shapeType == SHAPE_TYPE_COMPOUND) {
- if (!_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
+ if (getShapeType() == SHAPE_TYPE_COMPOUND) {
+ if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
_compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL());
}
- } else if (_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
+ } else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
// the compoundURL has been set but the shapeType does not agree
_compoundShapeResource.reset();
}
@@ -627,7 +628,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
}
- if (_shapeType == SHAPE_TYPE_COMPOUND) {
+ if (getShapeType() == SHAPE_TYPE_COMPOUND) {
_compoundShapeResource = DependencyManager::get()->getGeometryResource(url);
}
}
@@ -637,7 +638,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
ShapeType type = getShapeType();
if (type == SHAPE_TYPE_COMPOUND) {
- if (!_model || _compoundShapeURL.isEmpty()) {
+ if (!_model || getCompoundShapeURL().isEmpty()) {
EntityTreePointer tree = getTree();
if (tree) {
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
@@ -659,8 +660,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
doInitialModelSimulation();
}
return true;
- } else if (!_compoundShapeURL.isEmpty()) {
- _compoundShapeResource = DependencyManager::get()->getGeometryResource(_compoundShapeURL);
+ } else if (!getCompoundShapeURL().isEmpty()) {
+ _compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL());
}
}
@@ -775,7 +776,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset;
}
}
- shapeInfo.setParams(type, dimensions, _compoundShapeURL);
+ shapeInfo.setParams(type, dimensions, getCompoundShapeURL());
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
// should never fall in here when model not fully loaded
assert(_model && _model->isLoaded());
@@ -1001,7 +1002,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
}
}
- shapeInfo.setParams(type, 0.5f * dimensions, _modelURL);
+ shapeInfo.setParams(type, 0.5f * dimensions, getModelURL());
} else {
ModelEntityItem::computeShapeInfo(shapeInfo);
shapeInfo.setParams(type, 0.5f * dimensions);
diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp
index b8093d85d0..ee3b068af9 100644
--- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp
@@ -660,22 +660,22 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
});
}
-void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) {
- if (xTextureURL != _xTextureURL) {
+void RenderablePolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) {
+ if (xTextureURL != getXTextureURL()) {
_xTexture.clear();
PolyVoxEntityItem::setXTextureURL(xTextureURL);
}
}
-void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) {
- if (yTextureURL != _yTextureURL) {
+void RenderablePolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) {
+ if (yTextureURL != getYTextureURL()) {
_yTexture.clear();
PolyVoxEntityItem::setYTextureURL(yTextureURL);
}
}
-void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) {
- if (zTextureURL != _zTextureURL) {
+void RenderablePolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) {
+ if (zTextureURL != getZTextureURL()) {
_zTexture.clear();
PolyVoxEntityItem::setZTextureURL(zTextureURL);
}
diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h
index ecb1817e94..c0bc8ba610 100644
--- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h
+++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h
@@ -101,9 +101,9 @@ public:
virtual bool setAll(uint8_t toValue) override;
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
- virtual void setXTextureURL(QString xTextureURL) override;
- virtual void setYTextureURL(QString yTextureURL) override;
- virtual void setZTextureURL(QString zTextureURL) override;
+ virtual void setXTextureURL(const QString& xTextureURL) override;
+ virtual void setYTextureURL(const QString& yTextureURL) override;
+ virtual void setZTextureURL(const QString& zTextureURL) override;
virtual bool addToScene(EntityItemPointer self,
std::shared_ptr scene,
diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
index 9c98e699f1..a58ed8bbff 100644
--- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
@@ -77,14 +77,16 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true);
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
- float scale = _lineHeight / _textRenderer->getFontSize();
+ float lineheight = getLineHeight();
+ float scale = lineheight / _textRenderer->getFontSize();
transformToTopLeft.setScale(scale); // Scale to have the correct line height
batch.setModelTransform(transformToTopLeft);
- float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
+ float leftMargin = 0.1f * lineheight, topMargin = 0.1f * lineheight;
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
dimensions.y - 2.0f * topMargin);
- _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale);
+ auto text = getText();
+ _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale);
}
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index c4ae0db1aa..109c4cbfe9 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() {
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
}
- _webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) {
+ _webSurface->load("WebEntityView.qml", [&](QQmlContext* context, QObject* obj) {
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject));
});
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index 0bb085459e..3f732e26cb 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -683,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
if (overwriteLocalData) weOwnSimulation = false;
} else if (_simulationOwner.set(newSimOwner)) {
- _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
// recompute weOwnSimulation for later
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
@@ -695,19 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
weOwnSimulation = true;
if (!_simulationOwner.isNull()) {
// someone else really did own it
- _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
_simulationOwner.clearCurrentOwner();
}
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
// this could happen when the user reloads the cache and entity tree.
- _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
_simulationOwner.clearCurrentOwner();
weOwnSimulation = false;
} else if (_simulationOwner.set(newSimOwner)) {
- _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
// recompute weOwnSimulation for later
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
@@ -909,19 +909,23 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk
float EntityItem::computeMass() const {
glm::vec3 dimensions = getDimensions();
- return _density * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z;
+ return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z;
}
void EntityItem::setDensity(float density) {
- _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
+ withWriteLock([&] {
+ _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
+ });
}
void EntityItem::updateDensity(float density) {
float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
- if (_density != clampedDensity) {
- _density = clampedDensity;
- _dirtyFlags |= Simulation::DIRTY_MASS;
- }
+ withWriteLock([&] {
+ if (_density != clampedDensity) {
+ _density = clampedDensity;
+ _dirtyFlags |= Simulation::DIRTY_MASS;
+ }
+ });
}
void EntityItem::setMass(float mass) {
@@ -941,10 +945,12 @@ void EntityItem::setMass(float mass) {
} else {
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
}
- if (_density != newDensity) {
- _density = newDensity;
- _dirtyFlags |= Simulation::DIRTY_MASS;
- }
+ withWriteLock([&] {
+ if (_density != newDensity) {
+ _density = newDensity;
+ _dirtyFlags |= Simulation::DIRTY_MASS;
+ }
+ });
}
void EntityItem::setHref(QString value) {
@@ -952,32 +958,47 @@ void EntityItem::setHref(QString value) {
if (! (value.toLower().startsWith("hifi://")) ) {
return;
}
- _href = value;
+ withWriteLock([&] {
+ _href = value;
+ });
}
void EntityItem::setCollisionSoundURL(const QString& value) {
- if (_collisionSoundURL != value) {
- _collisionSoundURL = value;
-
+ bool modified = false;
+ withWriteLock([&] {
+ if (_collisionSoundURL != value) {
+ _collisionSoundURL = value;
+ modified = true;
+ }
+ });
+ if (modified) {
if (auto myTree = getTree()) {
- myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID());
+ myTree->notifyNewCollisionSoundURL(value, getEntityItemID());
}
}
}
SharedSoundPointer EntityItem::getCollisionSound() {
- if (!_collisionSound) {
- _collisionSound = DependencyManager::get()->getSound(_collisionSoundURL);
+ SharedSoundPointer result;
+ withReadLock([&] {
+ result = _collisionSound;
+ });
+
+ if (!result) {
+ result = DependencyManager::get()->getSound(_collisionSoundURL);
+ withWriteLock([&] {
+ _collisionSound = result;
+ });
}
- return _collisionSound;
+ return result;
}
void EntityItem::simulate(const quint64& now) {
- if (_lastSimulated == 0) {
- _lastSimulated = now;
+ if (getLastSimulated() == 0) {
+ setLastSimulated(now);
}
- float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
+ float timeElapsed = (float)(now - getLastSimulated()) / (float)(USECS_PER_SECOND);
#ifdef WANT_DEBUG
qCDebug(entities) << "********** EntityItem::simulate()";
@@ -1021,10 +1042,10 @@ void EntityItem::simulate(const quint64& now) {
if (!stepKinematicMotion(timeElapsed)) {
// this entity is no longer moving
// flag it to transition from KINEMATIC to STATIC
- _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;
+ markDirtyFlags(Simulation::DIRTY_MOTION_TYPE);
setAcceleration(Vectors::ZERO);
}
- _lastSimulated = now;
+ setLastSimulated(now);
}
bool EntityItem::stepKinematicMotion(float timeElapsed) {
@@ -1056,9 +1077,10 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED);
if (isSpinning) {
+ float angularDamping = getAngularDamping();
// angular damping
- if (_angularDamping > 0.0f) {
- angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
+ if (angularDamping > 0.0f) {
+ angularVelocity *= powf(1.0f - angularDamping, timeElapsed);
}
const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED =
@@ -1086,15 +1108,17 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
glm::vec3 deltaVelocity = Vectors::ZERO;
// linear damping
- if (_damping > 0.0f) {
- deltaVelocity = (powf(1.0f - _damping, timeElapsed) - 1.0f) * linearVelocity;
+ float damping = getDamping();
+ if (damping > 0.0f) {
+ deltaVelocity = (powf(1.0f - damping, timeElapsed) - 1.0f) * linearVelocity;
}
const float MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED = 1.0e-4f; // 0.01 m/sec^2
- if (glm::length2(_acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) {
+ vec3 acceleration = getAcceleration();
+ if (glm::length2(acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) {
// yes acceleration
// acceleration is in world-frame but we need it in local-frame
- glm::vec3 linearAcceleration = _acceleration;
+ glm::vec3 linearAcceleration = acceleration;
bool success;
Transform parentTransform = getParentTransform(success);
if (success) {
@@ -1180,7 +1204,7 @@ bool EntityItem::lifetimeHasExpired() const {
}
quint64 EntityItem::getExpiry() const {
- return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND);
+ return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND);
}
EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
@@ -1189,10 +1213,10 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
EntityItemProperties properties(propertyFlags);
properties._id = getID();
properties._idSet = true;
- properties._created = _created;
- properties._lastEdited = _lastEdited;
- properties.setClientOnly(_clientOnly);
- properties.setOwningAvatarID(_owningAvatarID);
+ properties._created = getCreated();
+ properties._lastEdited = getLastEdited();
+ properties.setClientOnly(getClientOnly());
+ properties.setOwningAvatarID(getOwningAvatarID());
properties._type = getType();
@@ -1259,7 +1283,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
properties._angularVelocity = getLocalAngularVelocity();
}
if (!properties._accelerationChanged) {
- properties._acceleration = _acceleration;
+ properties._acceleration = getAcceleration();
}
properties._positionChanged = true;
@@ -1270,7 +1294,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
}
void EntityItem::pokeSimulationOwnership() {
- _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE;
+ markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE);
auto nodeList = DependencyManager::get();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it
@@ -1282,7 +1306,7 @@ void EntityItem::pokeSimulationOwnership() {
}
void EntityItem::grabSimulationOwnership() {
- _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB;
+ markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
auto nodeList = DependencyManager::get();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it
@@ -1575,18 +1599,18 @@ float EntityItem::getVolumeEstimate() const {
void EntityItem::updateRegistrationPoint(const glm::vec3& value) {
if (value != _registrationPoint) {
setRegistrationPoint(value);
- _dirtyFlags |= Simulation::DIRTY_SHAPE;
+ markDirtyFlags(Simulation::DIRTY_SHAPE);
}
}
void EntityItem::updatePosition(const glm::vec3& value) {
if (getLocalPosition() != value) {
setLocalPosition(value);
- _dirtyFlags |= Simulation::DIRTY_POSITION;
+ markDirtyFlags(Simulation::DIRTY_POSITION);
forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer entity = std::static_pointer_cast(object);
- entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
+ entity->markDirtyFlags(Simulation::DIRTY_POSITION);
}
});
}
@@ -1595,8 +1619,9 @@ void EntityItem::updatePosition(const glm::vec3& value) {
void EntityItem::updateParentID(const QUuid& value) {
if (getParentID() != value) {
setParentID(value);
- _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; // children are forced to be kinematic
- _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
+ // children are forced to be kinematic
+ // may need to not collide with own avatar
+ markDirtyFlags(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_COLLISION_GROUP);
}
}
@@ -1610,7 +1635,7 @@ void EntityItem::updatePositionFromNetwork(const glm::vec3& value) {
void EntityItem::updateDimensions(const glm::vec3& value) {
if (getDimensions() != value) {
setDimensions(value);
- _dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
+ markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
}
}
@@ -1621,8 +1646,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer entity = std::static_pointer_cast(object);
- entity->_dirtyFlags |= Simulation::DIRTY_ROTATION;
- entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
+ entity->markDirtyFlags(Simulation::DIRTY_ROTATION | Simulation::DIRTY_POSITION);
}
});
}
@@ -1777,20 +1801,26 @@ void EntityItem::updateRestitution(float value) {
void EntityItem::updateFriction(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
- if (_friction != clampedValue) {
- _friction = clampedValue;
- _dirtyFlags |= Simulation::DIRTY_MATERIAL;
- }
+ withWriteLock([&] {
+ if (_friction != clampedValue) {
+ _friction = clampedValue;
+ _dirtyFlags |= Simulation::DIRTY_MATERIAL;
+ }
+ });
}
void EntityItem::setRestitution(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION);
- _restitution = clampedValue;
+ withWriteLock([&] {
+ _restitution = clampedValue;
+ });
}
void EntityItem::setFriction(float value) {
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
- _friction = clampedValue;
+ withWriteLock([&] {
+ _friction = clampedValue;
+ });
}
void EntityItem::updateLifetime(float value) {
@@ -1883,7 +1913,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) {
}
if (_simulationOwner.set(owner)) {
- _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
}
}
@@ -1896,7 +1926,7 @@ void EntityItem::clearSimulationOwnership() {
// don't bother setting the DIRTY_SIMULATOR_ID flag because:
// (a) when entity-server calls clearSimulationOwnership() the dirty-flags are meaningless (only used by interface)
// (b) the interface only calls clearSimulationOwnership() in a context that already knows best about dirty flags
- //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
+ //markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
}
@@ -2103,7 +2133,7 @@ void EntityItem::deserializeActionsInternal() {
static QString repeatedMessage =
LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*");
qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for"
- << getID() << getName();
+ << getID() << _name; // getName();
removeActionInternal(actionID, nullptr);
}
}
@@ -2327,3 +2357,443 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const {
// the json filter syntax did not match what we expected, return a match
return true;
}
+
+quint64 EntityItem::getLastSimulated() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _lastSimulated;
+ });
+ return result;
+}
+
+void EntityItem::setLastSimulated(quint64 now) {
+ withWriteLock([&] {
+ _lastSimulated = now;
+ });
+}
+
+quint64 EntityItem::getLastEdited() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _lastEdited;
+ });
+ return result;
+}
+
+void EntityItem::setLastEdited(quint64 lastEdited) {
+ withWriteLock([&] {
+ _lastEdited = _lastUpdated = lastEdited;
+ _changedOnServer = glm::max(lastEdited, _changedOnServer);
+ });
+}
+
+quint64 EntityItem::getLastBroadcast() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _lastBroadcast;
+ });
+ return result;
+}
+
+void EntityItem::setLastBroadcast(quint64 lastBroadcast) {
+ withWriteLock([&] {
+ _lastBroadcast = lastBroadcast;
+ });
+}
+
+void EntityItem::markAsChangedOnServer() {
+ withWriteLock([&] {
+ _changedOnServer = usecTimestampNow();
+ });
+}
+
+quint64 EntityItem::getLastChangedOnServer() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _changedOnServer;
+ });
+ return result;
+}
+
+void EntityItem::update(const quint64& now) {
+ withWriteLock([&] {
+ _lastUpdated = now;
+ });
+}
+
+quint64 EntityItem::getLastUpdated() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _lastUpdated;
+ });
+ return result;
+}
+
+void EntityItem::requiresRecalcBoxes() {
+ withWriteLock([&] {
+ _recalcAABox = true;
+ _recalcMinAACube = true;
+ _recalcMaxAACube = true;
+ });
+}
+
+QString EntityItem::getHref() const {
+ QString result;
+ withReadLock([&] {
+ result = _href;
+ });
+ return result;
+}
+
+QString EntityItem::getDescription() const {
+ QString result;
+ withReadLock([&] {
+ result = _description;
+ });
+ return result;
+}
+
+void EntityItem::setDescription(const QString& value) {
+ withWriteLock([&] {
+ _description = value;
+ });
+}
+
+float EntityItem::getLocalRenderAlpha() const {
+ float result;
+ withReadLock([&] {
+ result = _localRenderAlpha;
+ });
+ return result;
+}
+
+void EntityItem::setLocalRenderAlpha(float localRenderAlpha) {
+ withWriteLock([&] {
+ _localRenderAlpha = localRenderAlpha;
+ });
+}
+
+glm::vec3 EntityItem::getGravity() const {
+ glm::vec3 result;
+ withReadLock([&] {
+ result = _gravity;
+ });
+ return result;
+}
+
+void EntityItem::setGravity(const glm::vec3& value) {
+ withWriteLock([&] {
+ _gravity = value;
+ });
+}
+
+glm::vec3 EntityItem::getAcceleration() const {
+ glm::vec3 result;
+ withReadLock([&] {
+ result = _acceleration;
+ });
+ return result;
+}
+
+void EntityItem::setAcceleration(const glm::vec3& value) {
+ withWriteLock([&] {
+ _acceleration = value;
+ });
+}
+
+float EntityItem::getDamping() const {
+ float result;
+ withReadLock([&] {
+ result = _damping;
+ });
+ return result;
+}
+void EntityItem::setDamping(float value) {
+ withWriteLock([&] {
+ _damping = value;
+ });
+}
+
+float EntityItem::getRestitution() const {
+ float result;
+ withReadLock([&] {
+ result = _restitution;
+ });
+ return result;
+}
+
+float EntityItem::getFriction() const {
+ float result;
+ withReadLock([&] {
+ result = _friction;
+ });
+ return result;
+}
+
+// lifetime related properties.
+float EntityItem::getLifetime() const {
+ float result;
+ withReadLock([&] {
+ result = _lifetime;
+ });
+ return result;
+}
+
+void EntityItem::setLifetime(float value) {
+ withWriteLock([&] {
+ _lifetime = value;
+ });
+}
+
+quint64 EntityItem::getCreated() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _created;
+ });
+ return result;
+}
+
+void EntityItem::setCreated(quint64 value) {
+ withWriteLock([&] {
+ _created = value;
+ });
+}
+
+QString EntityItem::getScript() const {
+ QString result;
+ withReadLock([&] {
+ result = _script;
+ });
+ return result;
+}
+
+void EntityItem::setScript(const QString& value) {
+ withWriteLock([&] {
+ _script = value;
+ });
+}
+
+quint64 EntityItem::getScriptTimestamp() const {
+ quint64 result;
+ withReadLock([&] {
+ result = _scriptTimestamp;
+ });
+ return result;
+}
+
+void EntityItem::setScriptTimestamp(const quint64 value) {
+ withWriteLock([&] {
+ _scriptTimestamp = value;
+ });
+}
+
+QString EntityItem::getServerScripts() const {
+ QString result;
+ withReadLock([&] {
+ result = _serverScripts;
+ });
+ return result;
+}
+
+void EntityItem::setServerScripts(const QString& serverScripts) {
+ withWriteLock([&] {
+ _serverScripts = serverScripts;
+ _serverScriptsChangedTimestamp = usecTimestampNow();
+ });
+}
+
+QString EntityItem::getCollisionSoundURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _collisionSoundURL;
+ });
+ return result;
+}
+
+void EntityItem::setCollisionSound(SharedSoundPointer sound) {
+ withWriteLock([&] {
+ _collisionSound = sound;
+ });
+}
+
+glm::vec3 EntityItem::getRegistrationPoint() const {
+ glm::vec3 result;
+ withReadLock([&] {
+ result = _registrationPoint;
+ });
+ return result;
+}
+
+void EntityItem::setRegistrationPoint(const glm::vec3& value) {
+ withWriteLock([&] {
+ _registrationPoint = glm::clamp(value, 0.0f, 1.0f);
+ });
+ dimensionsChanged(); // Registration Point affects the bounding box
+}
+
+float EntityItem::getAngularDamping() const {
+ float result;
+ withReadLock([&] {
+ result = _angularDamping;
+ });
+ return result;
+}
+
+void EntityItem::setAngularDamping(float value) {
+ withWriteLock([&] {
+ _angularDamping = value;
+ });
+}
+
+QString EntityItem::getName() const {
+ QString result;
+ withReadLock([&] {
+ result = _name;
+ });
+ return result;
+}
+
+void EntityItem::setName(const QString& value) {
+ withWriteLock([&] {
+ _name = value;
+ });
+}
+
+QString EntityItem::getDebugName() {
+ QString result = getName();
+ if (result.isEmpty()) {
+ result = getID().toString();
+ }
+ return result;
+}
+
+bool EntityItem::getVisible() const {
+ bool result;
+ withReadLock([&] {
+ result = _visible;
+ });
+ return result;
+}
+
+void EntityItem::setVisible(bool value) {
+ withWriteLock([&] {
+ _visible = value;
+ });
+}
+
+bool EntityItem::getCollisionless() const {
+ bool result;
+ withReadLock([&] {
+ result = _collisionless;
+ });
+ return result;
+}
+
+void EntityItem::setCollisionless(bool value) {
+ withWriteLock([&] {
+ _collisionless = value;
+ });
+}
+
+uint8_t EntityItem::getCollisionMask() const {
+ uint8_t result;
+ withReadLock([&] {
+ result = _collisionMask;
+ });
+ return result;
+}
+
+void EntityItem::setCollisionMask(uint8_t value) {
+ withWriteLock([&] {
+ _collisionMask = value;
+ });
+}
+
+bool EntityItem::getDynamic() const {
+ if (SHAPE_TYPE_STATIC_MESH == getShapeType()) {
+ return false;
+ }
+ bool result;
+ withReadLock([&] {
+ result = _dynamic;
+ });
+ return result;
+}
+
+void EntityItem::setDynamic(bool value) {
+ withWriteLock([&] {
+ _dynamic = value;
+ });
+}
+
+bool EntityItem::getLocked() const {
+ bool result;
+ withReadLock([&] {
+ result = _locked;
+ });
+ return result;
+}
+
+void EntityItem::setLocked(bool value) {
+ withWriteLock([&] {
+ _locked = value;
+ });
+}
+
+QString EntityItem::getUserData() const {
+ QString result;
+ withReadLock([&] {
+ result = _userData;
+ });
+ return result;
+}
+
+void EntityItem::setUserData(const QString& value) {
+ withWriteLock([&] {
+ _userData = value;
+ });
+}
+
+QString EntityItem::getMarketplaceID() const {
+ QString result;
+ withReadLock([&] {
+ result = _marketplaceID;
+ });
+ return result;
+}
+
+void EntityItem::setMarketplaceID(const QString& value) {
+ withWriteLock([&] {
+ _marketplaceID = value;
+ });
+}
+
+uint32_t EntityItem::getDirtyFlags() const {
+ uint32_t result;
+ withReadLock([&] {
+ result = _dirtyFlags;
+ });
+ return result;
+}
+
+
+void EntityItem::markDirtyFlags(uint32_t mask) {
+ withWriteLock([&] {
+ _dirtyFlags |= mask;
+ });
+}
+
+void EntityItem::clearDirtyFlags(uint32_t mask) {
+ withWriteLock([&] {
+ _dirtyFlags &= ~mask;
+ });
+}
+
+float EntityItem::getDensity() const {
+ float result;
+ withReadLock([&] {
+ result = _density;
+ });
+ return result;
+}
+
diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h
index 74d2daccbf..766ebfb4dc 100644
--- a/libraries/entities/src/EntityItem.h
+++ b/libraries/entities/src/EntityItem.h
@@ -110,22 +110,21 @@ public:
virtual void somethingChangedNotification() { }
void recordCreationTime(); // set _created to 'now'
- quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs
- void setLastSimulated(quint64 now) { _lastSimulated = now; }
+ quint64 getLastSimulated() const; /// Last simulated time of this entity universal usecs
+ void setLastSimulated(quint64 now);
/// Last edited time of this entity universal usecs
- quint64 getLastEdited() const { return _lastEdited; }
- void setLastEdited(quint64 lastEdited)
- { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
+ quint64 getLastEdited() const;
+ void setLastEdited(quint64 lastEdited);
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
/// Last time we sent out an edit packet for this entity
- quint64 getLastBroadcast() const { return _lastBroadcast; }
- void setLastBroadcast(quint64 lastBroadcast) { _lastBroadcast = lastBroadcast; }
+ quint64 getLastBroadcast() const;
+ void setLastBroadcast(quint64 lastBroadcast);
- void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); }
- quint64 getLastChangedOnServer() const { return _changedOnServer; }
+ void markAsChangedOnServer();
+ quint64 getLastChangedOnServer() const;
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
@@ -163,8 +162,8 @@ public:
static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew);
// perform update
- virtual void update(const quint64& now) { _lastUpdated = now; }
- quint64 getLastUpdated() const { return _lastUpdated; }
+ virtual void update(const quint64& now);
+ quint64 getLastUpdated() const;
// perform linear extrapolation for SimpleEntitySimulation
void simulate(const quint64& now);
@@ -188,63 +187,63 @@ public:
const Transform getTransformToCenter(bool& success) const;
- inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
+ inline void requiresRecalcBoxes();
// Hyperlink related getters and setters
- QString getHref() const { return _href; }
+ QString getHref() const;
void setHref(QString value);
- QString getDescription() const { return _description; }
- void setDescription(QString value) { _description = value; }
+ QString getDescription() const;
+ void setDescription(const QString& value);
/// Dimensions in meters (0.0 - TREE_SCALE)
inline const glm::vec3 getDimensions() const { return getScale(); }
virtual void setDimensions(const glm::vec3& value);
- float getLocalRenderAlpha() const { return _localRenderAlpha; }
- void setLocalRenderAlpha(float localRenderAlpha) { _localRenderAlpha = localRenderAlpha; }
+ float getLocalRenderAlpha() const;
+ void setLocalRenderAlpha(float localRenderAlpha);
void setDensity(float density);
float computeMass() const;
void setMass(float mass);
- float getDensity() const { return _density; }
+ float getDensity() const;
bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; }
bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; }
- const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters
- void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters
- bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; }
+ glm::vec3 getGravity() const; /// get gravity in meters
+ void setGravity(const glm::vec3& value); /// gravity in meters
+ bool hasGravity() const { return getGravity() != ENTITY_ITEM_ZERO_VEC3; }
- const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second
- void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second
- bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; }
+ glm::vec3 getAcceleration() const; /// get acceleration in meters/second/second
+ void setAcceleration(const glm::vec3& value); /// acceleration in meters/second/second
+ bool hasAcceleration() const { return getAcceleration() != ENTITY_ITEM_ZERO_VEC3; }
- float getDamping() const { return _damping; }
- void setDamping(float value) { _damping = value; }
+ float getDamping() const;
+ void setDamping(float value);
- float getRestitution() const { return _restitution; }
+ float getRestitution() const;
void setRestitution(float value);
- float getFriction() const { return _friction; }
+ float getFriction() const;
void setFriction(float value);
// lifetime related properties.
- float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
- void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity
+ float getLifetime() const; /// get the lifetime in seconds for the entity
+ void setLifetime(float value); /// set the lifetime in seconds for the entity
- quint64 getCreated() const { return _created; } /// get the created-time in useconds for the entity
- void setCreated(quint64 value) { _created = value; } /// set the created-time in useconds for the entity
+ quint64 getCreated() const; /// get the created-time in useconds for the entity
+ void setCreated(quint64 value); /// set the created-time in useconds for the entity
/// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted
- bool isImmortal() const { return _lifetime == ENTITY_ITEM_IMMORTAL_LIFETIME; }
+ bool isImmortal() const { return getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires
- bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; }
+ bool isMortal() const { return getLifetime() != ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// age of this entity in seconds
- float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
+ float getAge() const { return (float)(usecTimestampNow() - getCreated()) / (float)USECS_PER_SECOND; }
bool lifetimeHasExpired() const;
quint64 getExpiry() const;
@@ -256,63 +255,61 @@ public:
using SpatiallyNestable::getQueryAACube;
virtual AACube getQueryAACube(bool& success) const override;
- QString getScript() const { return _script; }
- void setScript(const QString& value) { _script = value; }
+ QString getScript() const;
+ void setScript(const QString& value);
- quint64 getScriptTimestamp() const { return _scriptTimestamp; }
- void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
+ quint64 getScriptTimestamp() const;
+ void setScriptTimestamp(const quint64 value);
- QString getServerScripts() const { return _serverScripts; }
- void setServerScripts(const QString& serverScripts)
- { _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); }
+ QString getServerScripts() const;
+ void setServerScripts(const QString& serverScripts);
- const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
+ QString getCollisionSoundURL() const;
void setCollisionSoundURL(const QString& value);
SharedSoundPointer getCollisionSound();
- void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; }
+ void setCollisionSound(SharedSoundPointer sound);
- const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
+ glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity
/// registration point as ratio of entity
- void setRegistrationPoint(const glm::vec3& value) {
- _registrationPoint = glm::clamp(value, 0.0f, 1.0f); dimensionsChanged(); // Registration Point affects the bounding box
- }
+ void setRegistrationPoint(const glm::vec3& value);
bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
- float getAngularDamping() const { return _angularDamping; }
- void setAngularDamping(float value) { _angularDamping = value; }
+ float getAngularDamping() const;
+ void setAngularDamping(float value);
- QString getName() const { return _name; }
- void setName(const QString& value) { _name = value; }
- QString getDebugName() { return _name != "" ? _name : getID().toString(); }
+ QString getName() const;
+ void setName(const QString& value);
+ QString getDebugName();
- bool getVisible() const { return _visible; }
- void setVisible(bool value) { _visible = value; }
- bool isVisible() const { return _visible; }
- bool isInvisible() const { return !_visible; }
+ bool getVisible() const;
+ void setVisible(bool value);
+ inline bool isVisible() const { return getVisible(); }
+ inline bool isInvisible() const { return !getVisible(); }
- bool getCollisionless() const { return _collisionless; }
- void setCollisionless(bool value) { _collisionless = value; }
+ bool getCollisionless() const;
+ void setCollisionless(bool value);
- uint8_t getCollisionMask() const { return _collisionMask; }
- void setCollisionMask(uint8_t value) { _collisionMask = value; }
+ uint8_t getCollisionMask() const;
+ void setCollisionMask(uint8_t value);
void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const;
- bool getDynamic() const { return SHAPE_TYPE_STATIC_MESH == getShapeType() ? false : _dynamic; }
- void setDynamic(bool value) { _dynamic = value; }
+ bool getDynamic() const;
+ void setDynamic(bool value);
virtual bool shouldBePhysical() const { return false; }
- bool getLocked() const { return _locked; }
- void setLocked(bool value) { _locked = value; }
+ bool getLocked() const;
+ void setLocked(bool value);
- const QString& getUserData() const { return _userData; }
- virtual void setUserData(const QString& value) { _userData = value; }
+ QString getUserData() const;
+ virtual void setUserData(const QString& value);
+ // FIXME not thread safe?
const SimulationOwner& getSimulationOwner() const { return _simulationOwner; }
void setSimulationOwner(const QUuid& id, quint8 priority);
void setSimulationOwner(const SimulationOwner& owner);
@@ -325,8 +322,8 @@ public:
void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
void rememberHasSimulationOwnershipBid() const;
- const QString& getMarketplaceID() const { return _marketplaceID; }
- void setMarketplaceID(const QString& value) { _marketplaceID = value; }
+ QString getMarketplaceID() const;
+ void setMarketplaceID(const QString& value);
// TODO: get rid of users of getRadius()...
float getRadius() const;
@@ -369,8 +366,9 @@ public:
void updateCreated(uint64_t value);
virtual void setShapeType(ShapeType type) { /* do nothing */ }
- uint32_t getDirtyFlags() const { return _dirtyFlags; }
- void clearDirtyFlags(uint32_t mask = 0xffffffff) { _dirtyFlags &= ~mask; }
+ uint32_t getDirtyFlags() const;
+ void markDirtyFlags(uint32_t mask);
+ void clearDirtyFlags(uint32_t mask = 0xffffffff);
bool isMoving() const;
bool isMovingRelativeToParent() const;
diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp
index e09822f028..753ff1d3c8 100644
--- a/libraries/entities/src/LightEntityItem.cpp
+++ b/libraries/entities/src/LightEntityItem.cpp
@@ -69,38 +69,59 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP
}
void LightEntityItem::setFalloffRadius(float value) {
- _falloffRadius = glm::max(value, 0.0f);
- _lightPropertiesChanged = true;
+ value = glm::max(value, 0.0f);
+ if (value == getFalloffRadius()) {
+ return;
+ }
+ withWriteLock([&] {
+ _falloffRadius = value;
+ _lightPropertiesChanged = true;
+ });
}
void LightEntityItem::setIsSpotlight(bool value) {
- if (value != _isSpotlight) {
- _isSpotlight = value;
-
- glm::vec3 dimensions = getDimensions();
- if (_isSpotlight) {
- const float length = dimensions.z;
- const float width = length * glm::sin(glm::radians(_cutoff));
- setDimensions(glm::vec3(width, width, length));
- } else {
- float maxDimension = glm::compMax(dimensions);
- setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension));
- }
- _lightPropertiesChanged = true;
+ if (value == getIsSpotlight()) {
+ return;
}
+
+ glm::vec3 dimensions = getDimensions();
+ glm::vec3 newDimensions;
+ if (value) {
+ const float length = dimensions.z;
+ const float width = length * glm::sin(glm::radians(getCutoff()));
+ newDimensions = glm::vec3(width, width, length);
+ } else {
+ newDimensions = glm::vec3(glm::compMax(dimensions));
+ }
+
+ withWriteLock([&] {
+ _isSpotlight = value;
+ _lightPropertiesChanged = true;
+ });
+ setDimensions(newDimensions);
}
void LightEntityItem::setCutoff(float value) {
- _cutoff = glm::clamp(value, 0.0f, 90.0f);
+ value = glm::clamp(value, 0.0f, 90.0f);
+ if (value == getCutoff()) {
+ return;
+ }
- if (_isSpotlight) {
+ withWriteLock([&] {
+ _cutoff = value;
+ });
+
+ if (getIsSpotlight()) {
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
// so update the dimensions to reflect this.
const float length = getDimensions().z;
const float width = length * glm::sin(glm::radians(_cutoff));
setDimensions(glm::vec3(width, width, length));
}
- _lightPropertiesChanged = true;
+
+ withWriteLock([&] {
+ _lightPropertiesChanged = true;
+ });
}
bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
@@ -205,5 +226,86 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
void LightEntityItem::somethingChangedNotification() {
EntityItem::somethingChangedNotification();
- _lightPropertiesChanged = false;
+ withWriteLock([&] {
+ _lightPropertiesChanged = false;
+ });
}
+
+const rgbColor& LightEntityItem::getColor() const {
+ return _color;
+}
+
+xColor LightEntityItem::getXColor() const {
+ xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
+}
+
+void LightEntityItem::setColor(const rgbColor& value) {
+ withWriteLock([&] {
+ memcpy(_color, value, sizeof(_color));
+ _lightPropertiesChanged = true;
+ });
+}
+
+void LightEntityItem::setColor(const xColor& value) {
+ withWriteLock([&] {
+ _color[RED_INDEX] = value.red;
+ _color[GREEN_INDEX] = value.green;
+ _color[BLUE_INDEX] = value.blue;
+ _lightPropertiesChanged = true;
+ });
+}
+
+bool LightEntityItem::getIsSpotlight() const {
+ bool result;
+ withReadLock([&] {
+ result = _isSpotlight;
+ });
+ return result;
+}
+
+float LightEntityItem::getIntensity() const {
+ float result;
+ withReadLock([&] {
+ result = _intensity;
+ });
+ return result;
+}
+
+void LightEntityItem::setIntensity(float value) {
+ withWriteLock([&] {
+ _intensity = value;
+ _lightPropertiesChanged = true;
+ });
+}
+
+float LightEntityItem::getFalloffRadius() const {
+ float result;
+ withReadLock([&] {
+ result = _falloffRadius;
+ });
+ return result;
+}
+
+float LightEntityItem::getExponent() const {
+ float result;
+ withReadLock([&] {
+ result = _exponent;
+ });
+ return result;
+}
+
+void LightEntityItem::setExponent(float value) {
+ withWriteLock([&] {
+ _exponent = value;
+ _lightPropertiesChanged = true;
+ });
+}
+
+float LightEntityItem::getCutoff() const {
+ float result;
+ withReadLock([&] {
+ result = _cutoff;
+ });
+ return result;
+}
+
diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h
index 3444b11cae..b3cadcf0c7 100644
--- a/libraries/entities/src/LightEntityItem.h
+++ b/libraries/entities/src/LightEntityItem.h
@@ -57,47 +57,33 @@ public:
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
- const rgbColor& getColor() const { return _color; }
- xColor getXColor() const {
- xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
- }
+ const rgbColor& getColor() const;
+ xColor getXColor() const;
- void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
- void setColor(const xColor& value) {
- _color[RED_INDEX] = value.red;
- _color[GREEN_INDEX] = value.green;
- _color[BLUE_INDEX] = value.blue;
- _lightPropertiesChanged = true;
- }
+ void setColor(const rgbColor& value);
+ void setColor(const xColor& value);
- bool getIsSpotlight() const { return _isSpotlight; }
+ bool getIsSpotlight() const;
void setIsSpotlight(bool value);
void setIgnoredColor(const rgbColor& value) { }
void setIgnoredAttenuation(float value) { }
- float getIntensity() const { return _intensity; }
- void setIntensity(float value) {
- _intensity = value;
- _lightPropertiesChanged = true;
- }
-
- float getFalloffRadius() const { return _falloffRadius; }
+ float getIntensity() const;
+ void setIntensity(float value);
+ float getFalloffRadius() const;
void setFalloffRadius(float value);
- float getExponent() const { return _exponent; }
- void setExponent(float value) {
- _exponent = value;
- _lightPropertiesChanged = true;
- }
+ float getExponent() const;
+ void setExponent(float value);
- float getCutoff() const { return _cutoff; }
+ float getCutoff() const;
void setCutoff(float value);
static bool getLightsArePickable() { return _lightsArePickable; }
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
-protected:
+private:
// properties of a light
@@ -108,6 +94,7 @@ protected:
float _exponent { DEFAULT_EXPONENT };
float _cutoff { DEFAULT_CUTOFF };
+protected:
// Dirty flag turn true when either light properties is changing values.
// This gets back to false in the somethingChangedNotification() call
// Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity.
diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp
index 8ace665616..58cdb1cd7b 100644
--- a/libraries/entities/src/LineEntityItem.cpp
+++ b/libraries/entities/src/LineEntityItem.cpp
@@ -34,8 +34,8 @@ EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const En
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
EntityItem(entityItemID),
_lineWidth(DEFAULT_LINE_WIDTH),
- _pointsChanged(true),
- _points(QVector(0))
+ _points(QVector(0)),
+ _pointsChanged(true)
{
_type = EntityTypes::Line;
}
@@ -88,8 +88,10 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) {
qCDebug(entities) << "Point is outside entity's bounding box";
return false;
}
- _points << point;
- _pointsChanged = true;
+ withWriteLock([&] {
+ _points << point;
+ _pointsChanged = true;
+ });
return true;
}
@@ -105,8 +107,11 @@ bool LineEntityItem::setLinePoints(const QVector& points) {
return false;
}
}
- _points = points;
- _pointsChanged = true;
+
+ withWriteLock([&] {
+ _points = points;
+ _pointsChanged = true;
+ });
return true;
}
@@ -159,3 +164,51 @@ void LineEntityItem::debugDump() const {
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}
+
+const rgbColor& LineEntityItem::getColor() const {
+ return _color;
+}
+
+xColor LineEntityItem::getXColor() const {
+ xColor result;
+ withReadLock([&] {
+ result = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] };
+ });
+ return result;
+}
+
+void LineEntityItem::setColor(const rgbColor& value) {
+ withWriteLock([&] {
+ memcpy(_color, value, sizeof(_color));
+ });
+}
+
+void LineEntityItem::setColor(const xColor& value) {
+ withWriteLock([&] {
+ _color[RED_INDEX] = value.red;
+ _color[GREEN_INDEX] = value.green;
+ _color[BLUE_INDEX] = value.blue;
+ });
+}
+
+void LineEntityItem::setLineWidth(float lineWidth) {
+ withWriteLock([&] {
+ _lineWidth = lineWidth;
+ });
+}
+
+float LineEntityItem::getLineWidth() const {
+ float result;
+ withReadLock([&] {
+ result = _lineWidth;
+ });
+ return result;
+}
+
+QVector LineEntityItem::getLinePoints() const {
+ QVector result;
+ withReadLock([&] {
+ result = _points;
+ });
+ return result;
+}
diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h
index 8629c94eb4..bb8ae8a21a 100644
--- a/libraries/entities/src/LineEntityItem.h
+++ b/libraries/entities/src/LineEntityItem.h
@@ -42,23 +42,19 @@ class LineEntityItem : public EntityItem {
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
- const rgbColor& getColor() const { return _color; }
- xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
+ const rgbColor& getColor() const;
+ xColor getXColor() const;
- void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
- void setColor(const xColor& value) {
- _color[RED_INDEX] = value.red;
- _color[GREEN_INDEX] = value.green;
- _color[BLUE_INDEX] = value.blue;
- }
+ void setColor(const rgbColor& value);
+ void setColor(const xColor& value);
- void setLineWidth(float lineWidth){ _lineWidth = lineWidth; }
- float getLineWidth() const{ return _lineWidth; }
+ void setLineWidth(float lineWidth);
+ float getLineWidth() const;
bool setLinePoints(const QVector& points);
bool appendPoint(const glm::vec3& point);
- const QVector& getLinePoints() const{ return _points; }
+ QVector getLinePoints() const;
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; }
@@ -74,11 +70,12 @@ class LineEntityItem : public EntityItem {
static const float DEFAULT_LINE_WIDTH;
static const int MAX_POINTS_PER_LINE;
- protected:
+ private:
rgbColor _color;
float _lineWidth;
- bool _pointsChanged;
QVector _points;
+protected:
+ bool _pointsChanged;
};
#endif // hifi_LineEntityItem_h
diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp
index 140522b00e..80f7f3b6b8 100644
--- a/libraries/entities/src/ParticleEffectEntityItem.cpp
+++ b/libraries/entities/src/ParticleEffectEntityItem.cpp
@@ -733,3 +733,20 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
_timeUntilNextEmit = 0.0f;
}
}
+
+QString ParticleEffectEntityItem::getTextures() const {
+ QString result;
+ withReadLock([&] {
+ result = _textures;
+ });
+ return result;
+}
+
+void ParticleEffectEntityItem::setTextures(const QString& textures) {
+ withWriteLock([&] {
+ if (_textures != textures) {
+ _textures = textures;
+ _texturesChangedFlag = true;
+ }
+ });
+}
diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h
index 6c6596e7a2..4d053e5a45 100644
--- a/libraries/entities/src/ParticleEffectEntityItem.h
+++ b/libraries/entities/src/ParticleEffectEntityItem.h
@@ -205,13 +205,8 @@ public:
void computeAndUpdateDimensions();
static const QString DEFAULT_TEXTURES;
- const QString& getTextures() const { return _textures; }
- void setTextures(const QString& textures) {
- if (_textures != textures) {
- _textures = textures;
- _texturesChangedFlag = true;
- }
- }
+ QString getTextures() const;
+ void setTextures(const QString& textures);
static const bool DEFAULT_EMITTER_SHOULD_TRAIL;
bool getEmitterShouldTrail() const { return _emitterShouldTrail; }
diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp
index 7abafad627..9fe8ac0c8f 100644
--- a/libraries/entities/src/PolyLineEntityItem.cpp
+++ b/libraries/entities/src/PolyLineEntityItem.cpp
@@ -104,14 +104,18 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
bool PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) {
- _strokeWidths = strokeWidths;
- _strokeWidthsChanged = true;
+ withWriteLock([&] {
+ _strokeWidths = strokeWidths;
+ _strokeWidthsChanged = true;
+ });
return true;
}
bool PolyLineEntityItem::setNormals(const QVector& normals) {
- _normals = normals;
- _normalsChanged = true;
+ withWriteLock([&] {
+ _normals = normals;
+ _normalsChanged = true;
+ });
return true;
}
@@ -119,35 +123,39 @@ bool PolyLineEntityItem::setLinePoints(const QVector& points) {
if (points.size() > MAX_POINTS_PER_LINE) {
return false;
}
- if (points.size() != _points.size()) {
- _pointsChanged = true;
- }
- //Check to see if points actually changed. If they haven't, return before doing anything else
- else if (points.size() == _points.size()) {
- //same number of points, so now compare every point
- for (int i = 0; i < points.size(); i++) {
- if (points.at(i) != _points.at(i)){
- _pointsChanged = true;
- break;
+ bool result = false;
+ withWriteLock([&] {
+ //Check to see if points actually changed. If they haven't, return before doing anything else
+ if (points.size() != _points.size()) {
+ _pointsChanged = true;
+ } else if (points.size() == _points.size()) {
+ //same number of points, so now compare every point
+ for (int i = 0; i < points.size(); i++) {
+ if (points.at(i) != _points.at(i)) {
+ _pointsChanged = true;
+ break;
+ }
}
}
- }
- if (!_pointsChanged) {
- return false;
- }
-
- for (int i = 0; i < points.size(); i++) {
- glm::vec3 point = points.at(i);
- glm::vec3 halfBox = getDimensions() * 0.5f;
- if ((point.x < -halfBox.x || point.x > halfBox.x) ||
- (point.y < -halfBox.y || point.y > halfBox.y) ||
- (point.z < -halfBox.z || point.z > halfBox.z)) {
- qCDebug(entities) << "Point is outside entity's bounding box";
- return false;
+ if (!_pointsChanged) {
+ return;
}
- }
- _points = points;
- return true;
+
+ for (int i = 0; i < points.size(); i++) {
+ glm::vec3 point = points.at(i);
+ glm::vec3 halfBox = getDimensions() * 0.5f;
+ if ((point.x < -halfBox.x || point.x > halfBox.x) ||
+ (point.y < -halfBox.y || point.y > halfBox.y) ||
+ (point.z < -halfBox.z || point.z > halfBox.z)) {
+ qCDebug(entities) << "Point is outside entity's bounding box";
+ return;
+ }
+ }
+ _points = points;
+ result = true;
+ });
+
+ return result;
}
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
@@ -210,3 +218,45 @@ void PolyLineEntityItem::debugDump() const {
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}
+
+
+QVector PolyLineEntityItem::getLinePoints() const {
+ QVector result;
+ withReadLock([&] {
+ result = _points;
+ });
+ return result;
+}
+
+QVector PolyLineEntityItem::getNormals() const {
+ QVector result;
+ withReadLock([&] {
+ result = _normals;
+ });
+ return result;
+}
+
+QVector PolyLineEntityItem::getStrokeWidths() const {
+ QVector result;
+ withReadLock([&] {
+ result = _strokeWidths;
+ });
+ return result;
+}
+
+QString PolyLineEntityItem::getTextures() const {
+ QString result;
+ withReadLock([&] {
+ result = _textures;
+ });
+ return result;
+}
+
+void PolyLineEntityItem::setTextures(const QString& textures) {
+ withWriteLock([&] {
+ if (_textures != textures) {
+ _textures = textures;
+ _texturesChangedFlag = true;
+ }
+ });
+}
diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h
index 5f9f9124cf..0ee9a638de 100644
--- a/libraries/entities/src/PolyLineEntityItem.h
+++ b/libraries/entities/src/PolyLineEntityItem.h
@@ -59,21 +59,16 @@ class PolyLineEntityItem : public EntityItem {
bool setLinePoints(const QVector& points);
bool appendPoint(const glm::vec3& point);
- const QVector& getLinePoints() const{ return _points; }
+ QVector getLinePoints() const;
bool setNormals(const QVector& normals);
- const QVector& getNormals() const{ return _normals; }
+ QVector getNormals() const;
bool setStrokeWidths(const QVector& strokeWidths);
- const QVector& getStrokeWidths() const{ return _strokeWidths; }
+ QVector getStrokeWidths() const;
- const QString& getTextures() const { return _textures; }
- void setTextures(const QString& textures) {
- if (_textures != textures) {
- _textures = textures;
- _texturesChangedFlag = true;
- }
- }
+ QString getTextures() const;
+ void setTextures(const QString& textures);
virtual bool needsToCallUpdate() const override { return true; }
diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp
index 2a374c1d17..711c3b5625 100644
--- a/libraries/entities/src/PolyVoxEntityItem.cpp
+++ b/libraries/entities/src/PolyVoxEntityItem.cpp
@@ -242,3 +242,129 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
});
return voxelDataCopy;
}
+
+
+void PolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) {
+ withWriteLock([&] {
+ _xTextureURL = xTextureURL;
+ });
+}
+
+QString PolyVoxEntityItem::getXTextureURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _xTextureURL;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) {
+ withWriteLock([&] {
+ _yTextureURL = yTextureURL;
+ });
+}
+
+QString PolyVoxEntityItem::getYTextureURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _yTextureURL;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) {
+ withWriteLock([&] {
+ _zTextureURL = zTextureURL;
+ });
+}
+QString PolyVoxEntityItem::getZTextureURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _zTextureURL;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) {
+ withWriteLock([&] {
+ _xNNeighborID = xNNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getXNNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _xNNeighborID;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) {
+ withWriteLock([&] {
+ _yNNeighborID = yNNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getYNNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _yNNeighborID;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) {
+ withWriteLock([&] {
+ _zNNeighborID = zNNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getZNNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _zNNeighborID;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) {
+ withWriteLock([&] {
+ _xPNeighborID = xPNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getXPNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _xPNeighborID;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) {
+ withWriteLock([&] {
+ _yPNeighborID = yPNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getYPNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _yPNeighborID;
+ });
+ return result;
+}
+
+void PolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) {
+ withWriteLock([&] {
+ _zPNeighborID = zPNeighborID;
+ });
+}
+
+EntityItemID PolyVoxEntityItem::getZPNeighborID() const {
+ EntityItemID result;
+ withReadLock([&] {
+ result = _zPNeighborID;
+ });
+ return result;
+}
diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h
index cf7531fc9e..05b5cb33a6 100644
--- a/libraries/entities/src/PolyVoxEntityItem.h
+++ b/libraries/entities/src/PolyVoxEntityItem.h
@@ -99,36 +99,36 @@ class PolyVoxEntityItem : public EntityItem {
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
static const QString DEFAULT_X_TEXTURE_URL;
- virtual void setXTextureURL(QString xTextureURL) { _xTextureURL = xTextureURL; }
- virtual const QString& getXTextureURL() const { return _xTextureURL; }
+ virtual void setXTextureURL(const QString& xTextureURL);
+ QString getXTextureURL() const;
static const QString DEFAULT_Y_TEXTURE_URL;
- virtual void setYTextureURL(QString yTextureURL) { _yTextureURL = yTextureURL; }
- virtual const QString& getYTextureURL() const { return _yTextureURL; }
+ virtual void setYTextureURL(const QString& yTextureURL);
+ QString getYTextureURL() const;
static const QString DEFAULT_Z_TEXTURE_URL;
- virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; }
- virtual const QString& getZTextureURL() const { return _zTextureURL; }
+ virtual void setZTextureURL(const QString& zTextureURL);
+ QString getZTextureURL() const;
- virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; }
- void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); }
- virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; }
- virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; }
- void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); }
- virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; }
- virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; }
- void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); }
- virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; }
+ virtual void setXNNeighborID(const EntityItemID& xNNeighborID);
+ void setXNNeighborID(const QString& xNNeighborID);
+ virtual EntityItemID getXNNeighborID() const;
+ virtual void setYNNeighborID(const EntityItemID& yNNeighborID);
+ void setYNNeighborID(const QString& yNNeighborID);
+ virtual EntityItemID getYNNeighborID() const;
+ virtual void setZNNeighborID(const EntityItemID& zNNeighborID);
+ void setZNNeighborID(const QString& zNNeighborID);
+ virtual EntityItemID getZNNeighborID() const;
- virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; }
- void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); }
- virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; }
- virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; }
- void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); }
- virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; }
- virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; }
- void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); }
- virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; }
+ virtual void setXPNeighborID(const EntityItemID& xPNeighborID);
+ void setXPNeighborID(const QString& xPNeighborID);
+ virtual EntityItemID getXPNeighborID() const;
+ virtual void setYPNeighborID(const EntityItemID& yPNeighborID);
+ void setYPNeighborID(const QString& yPNeighborID);
+ virtual EntityItemID getYPNeighborID() const;
+ virtual void setZPNeighborID(const EntityItemID& zPNeighborID);
+ void setZPNeighborID(const QString& zPNeighborID);
+ virtual EntityItemID getZPNeighborID() const;
virtual void rebakeMesh() {};
diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp
index fbb0bdc9cf..c6b857f6e7 100644
--- a/libraries/entities/src/TextEntityItem.cpp
+++ b/libraries/entities/src/TextEntityItem.cpp
@@ -141,3 +141,98 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
// FIXME - should set face and surfaceNormal
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
}
+
+void TextEntityItem::setText(const QString& value) {
+ withWriteLock([&] {
+ _text = value;
+ });
+}
+
+QString TextEntityItem::getText() const {
+ QString result;
+ withReadLock([&] {
+ result = _text;
+ });
+ return result;
+}
+
+void TextEntityItem::setLineHeight(float value) {
+ withWriteLock([&] {
+ _lineHeight = value;
+ });
+}
+
+float TextEntityItem::getLineHeight() const {
+ float result;
+ withReadLock([&] {
+ result = _lineHeight;
+ });
+ return result;
+}
+
+const rgbColor& TextEntityItem::getTextColor() const {
+ return _textColor;
+}
+
+const rgbColor& TextEntityItem::getBackgroundColor() const {
+ return _backgroundColor;
+}
+
+xColor TextEntityItem::getTextColorX() const {
+ xColor result;
+ withReadLock([&] {
+ result = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] };
+ });
+ return result;
+}
+
+void TextEntityItem::setTextColor(const rgbColor& value) {
+ withWriteLock([&] {
+ memcpy(_textColor, value, sizeof(_textColor));
+ });
+}
+
+void TextEntityItem::setTextColor(const xColor& value) {
+ withWriteLock([&] {
+ _textColor[RED_INDEX] = value.red;
+ _textColor[GREEN_INDEX] = value.green;
+ _textColor[BLUE_INDEX] = value.blue;
+ });
+}
+
+xColor TextEntityItem::getBackgroundColorX() const {
+ xColor result;
+ withReadLock([&] {
+ result = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] };
+ });
+ return result;
+}
+
+void TextEntityItem::setBackgroundColor(const rgbColor& value) {
+ withWriteLock([&] {
+ memcpy(_backgroundColor, value, sizeof(_backgroundColor));
+ });
+}
+
+void TextEntityItem::setBackgroundColor(const xColor& value) {
+ withWriteLock([&] {
+ _backgroundColor[RED_INDEX] = value.red;
+ _backgroundColor[GREEN_INDEX] = value.green;
+ _backgroundColor[BLUE_INDEX] = value.blue;
+ });
+}
+
+bool TextEntityItem::getFaceCamera() const {
+ bool result;
+ withReadLock([&] {
+ result = _faceCamera;
+ });
+ return result;
+}
+
+void TextEntityItem::setFaceCamera(bool value) {
+ withWriteLock([&] {
+ _faceCamera = value;
+ });
+}
+
diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h
index 633aa96bfa..ee421d567a 100644
--- a/libraries/entities/src/TextEntityItem.h
+++ b/libraries/entities/src/TextEntityItem.h
@@ -53,40 +53,34 @@ public:
void** intersectedObject, bool precisionPicking) const override;
static const QString DEFAULT_TEXT;
- void setText(const QString& value) { _text = value; }
- const QString& getText() const { return _text; }
+ void setText(const QString& value);
+ QString getText() const;
static const float DEFAULT_LINE_HEIGHT;
- void setLineHeight(float value) { _lineHeight = value; }
- float getLineHeight() const { return _lineHeight; }
+ void setLineHeight(float value);
+ float getLineHeight() const;
static const xColor DEFAULT_TEXT_COLOR;
- const rgbColor& getTextColor() const { return _textColor; }
- xColor getTextColorX() const { xColor color = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; return color; }
+ // FIXME should not return a reference because of thread safety, but can't return an array
+ const rgbColor& getTextColor() const;
+ xColor getTextColorX() const;
- void setTextColor(const rgbColor& value) { memcpy(_textColor, value, sizeof(_textColor)); }
- void setTextColor(const xColor& value) {
- _textColor[RED_INDEX] = value.red;
- _textColor[GREEN_INDEX] = value.green;
- _textColor[BLUE_INDEX] = value.blue;
- }
+ void setTextColor(const rgbColor& value);
+ void setTextColor(const xColor& value);
static const xColor DEFAULT_BACKGROUND_COLOR;
- const rgbColor& getBackgroundColor() const { return _backgroundColor; }
- xColor getBackgroundColorX() const { xColor color = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; return color; }
+ // FIXME should not return a reference because of thread safety, but can't return an array
+ const rgbColor& getBackgroundColor() const;
+ xColor getBackgroundColorX() const;
- void setBackgroundColor(const rgbColor& value) { memcpy(_backgroundColor, value, sizeof(_backgroundColor)); }
- void setBackgroundColor(const xColor& value) {
- _backgroundColor[RED_INDEX] = value.red;
- _backgroundColor[GREEN_INDEX] = value.green;
- _backgroundColor[BLUE_INDEX] = value.blue;
- }
+ void setBackgroundColor(const rgbColor& value);
+ void setBackgroundColor(const xColor& value);
static const bool DEFAULT_FACE_CAMERA;
- bool getFaceCamera() const { return _faceCamera; }
- void setFaceCamera(bool value) { _faceCamera = value; }
+ bool getFaceCamera() const;
+ void setFaceCamera(bool value);
-protected:
+private:
QString _text;
float _lineHeight;
rgbColor _textColor;
diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp
index 182d58ba36..5b060cc702 100644
--- a/libraries/entities/src/WebEntityItem.cpp
+++ b/libraries/entities/src/WebEntityItem.cpp
@@ -124,18 +124,26 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g
}
void WebEntityItem::setSourceUrl(const QString& value) {
- if (_sourceUrl != value) {
- auto newURL = QUrl::fromUserInput(value);
+ withWriteLock([&] {
+ if (_sourceUrl != value) {
+ auto newURL = QUrl::fromUserInput(value);
- if (newURL.isValid()) {
- _sourceUrl = newURL.toDisplayString();
- } else {
- qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL.";
+ if (newURL.isValid()) {
+ _sourceUrl = newURL.toDisplayString();
+ } else {
+ qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL.";
+ }
}
- }
+ });
}
-const QString& WebEntityItem::getSourceUrl() const { return _sourceUrl; }
+QString WebEntityItem::getSourceUrl() const {
+ QString result;
+ withReadLock([&] {
+ result = _sourceUrl;
+ });
+ return result;
+}
void WebEntityItem::setDPI(uint16_t value) {
_dpi = value;
diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h
index 19a7b577fe..5cd081687f 100644
--- a/libraries/entities/src/WebEntityItem.h
+++ b/libraries/entities/src/WebEntityItem.h
@@ -52,7 +52,7 @@ public:
void** intersectedObject, bool precisionPicking) const override;
virtual void setSourceUrl(const QString& value);
- const QString& getSourceUrl() const;
+ QString getSourceUrl() const;
virtual bool wantsHandControllerPointerEvents() const override { return true; }
diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp
index 37b3be99a3..26d566a795 100644
--- a/libraries/entities/src/ZoneEntityItem.cpp
+++ b/libraries/entities/src/ZoneEntityItem.cpp
@@ -208,10 +208,12 @@ ShapeType ZoneEntityItem::getShapeType() const {
}
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
- _compoundShapeURL = url;
- if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
- _shapeType = DEFAULT_SHAPE_TYPE;
- }
+ withWriteLock([&] {
+ _compoundShapeURL = url;
+ if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
+ _shapeType = DEFAULT_SHAPE_TYPE;
+ }
+ });
}
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
@@ -223,7 +225,9 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
}
void ZoneEntityItem::setFilterURL(QString url) {
- _filterURL = url;
+ withWriteLock([&] {
+ _filterURL = url;
+ });
if (DependencyManager::isSet()) {
auto entityEditFilters = DependencyManager::get();
qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID();
@@ -231,3 +235,22 @@ void ZoneEntityItem::setFilterURL(QString url) {
}
}
+QString ZoneEntityItem::getFilterURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _filterURL;
+ });
+ return result;
+}
+
+bool ZoneEntityItem::hasCompoundShapeURL() const {
+ return !getCompoundShapeURL().isEmpty();
+}
+
+QString ZoneEntityItem::getCompoundShapeURL() const {
+ QString result;
+ withReadLock([&] {
+ result = _compoundShapeURL;
+ });
+ return result;
+}
diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h
index 2bef95e452..dfc18aff80 100644
--- a/libraries/entities/src/ZoneEntityItem.h
+++ b/libraries/entities/src/ZoneEntityItem.h
@@ -58,8 +58,8 @@ public:
void setShapeType(ShapeType type) override { _shapeType = type; }
virtual ShapeType getShapeType() const override;
- virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); }
- const QString getCompoundShapeURL() const { return _compoundShapeURL; }
+ virtual bool hasCompoundShapeURL() const;
+ QString getCompoundShapeURL() const;
virtual void setCompoundShapeURL(const QString& url);
const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; }
@@ -74,7 +74,7 @@ public:
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
bool getGhostingAllowed() const { return _ghostingAllowed; }
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
- QString getFilterURL() const { return _filterURL; }
+ QString getFilterURL() const;
void setFilterURL(const QString url);
virtual bool supportsDetailedRayIntersection() const override { return true; }
diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
index e5c630d97e..3f1d629638 100644
--- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp
+++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
@@ -59,8 +59,6 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
bool OffscreenGLCanvas::makeCurrent() {
bool result = _context->makeCurrent(_offscreenSurface);
- Q_ASSERT(result);
-
std::call_once(_reportOnce, [this]{
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
index 16e32ab42e..3bbd26e010 100644
--- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp
+++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
@@ -612,11 +612,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionmetaObject()->indexOfSignal("sendToScript");
- if (sendToScriptIndex != -1) {
- connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
- }
+ connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
// The root item is ready. Associate it with the window.
_rootItem = newItem;
diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp
index b4d8977b6d..7747e1b6dc 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.cpp
+++ b/libraries/script-engine/src/TabletScriptingInterface.cpp
@@ -275,6 +275,9 @@ void TabletProxy::emitWebEvent(QVariant msg) {
emit webEventReceived(msg);
}
+bool TabletProxy::isPathLoaded(QVariant path) {
+ return path.toString() == _currentPathLoaded.toString();
+}
void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
std::lock_guard guard(_mutex);
_qmlOffscreenSurface = qmlOffscreenSurface;
@@ -322,6 +325,7 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
removeButtonsFromHomeScreen();
_state = State::Uninitialized;
emit screenChanged(QVariant("Closed"), QVariant(""));
+ _currentPathLoaded = "";
}
}
@@ -345,6 +349,7 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) {
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
_state = State::Menu;
emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
+ _currentPathLoaded = VRMENU_SOURCE_URL;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
}
}
@@ -364,6 +369,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) {
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
_state = State::QML;
emit screenChanged(QVariant("QML"), path);
+ _currentPathLoaded = path;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
}
} else {
@@ -426,6 +432,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
}
_state = State::Home;
emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL));
+ _currentPathLoaded = TABLET_SOURCE_URL;
}
}
@@ -450,6 +457,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
}
_state = State::Web;
emit screenChanged(QVariant("Web"), QVariant(url));
+ _currentPathLoaded = QVariant(url);
}
QObject* TabletProxy::addButton(const QVariant& properties) {
diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h
index e9ae60fee1..195db02789 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.h
+++ b/libraries/script-engine/src/TabletScriptingInterface.h
@@ -183,6 +183,8 @@ public:
Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
Q_INVOKABLE bool getLandscape() { return _landscape; }
+ Q_INVOKABLE bool isPathLoaded(QVariant path);
+
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
QObject* getTabletSurface();
@@ -235,6 +237,7 @@ protected:
bool _initialScreen { false };
QVariant _initialPath { "" };
+ QVariant _currentPathLoaded { "" };
QString _name;
std::mutex _mutex;
std::vector> _tabletButtonProxies;
diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js
new file mode 100644
index 0000000000..fd3bb82145
--- /dev/null
+++ b/script-archive/selfieStick.js
@@ -0,0 +1,121 @@
+// selfieStick.js
+//
+// Created by Faye Li on March 23, 2016
+//
+// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick
+// and control your camera.
+// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions)
+//
+
+// selfieStick.js
+//
+// Created by Faye Li on March 23, 2016
+//
+// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick
+// and control your camera.
+//
+
+(function() { // BEGIN LOCAL_SCOPE
+ var MODEL_URL = "https://hifi-content.s3.amazonaws.com/faye/twitch-stream/selfie_stick.json";
+ var AVATAR_URL = "https://hifi-content.s3.amazonaws.com/jimi/avatar/camera/fst/camera.fst";
+ var originalAvatar = null;
+ var importedEntityIDs = [];
+ var selfieStickEntityID = null;
+ var lensEntityID = null;
+ var freeMovementMode = true;
+
+ turnOffAvatarCollisions();
+ changeAvatar();
+ importModel();
+ processImportedEntities();
+ setupSpaceBarControl();
+ Script.update.connect(update);
+
+ function turnOffAvatarCollisions() {
+ Menu.setIsOptionChecked("Enable avatar collisions", 0);
+ }
+
+ function turnOnAvatarCollisions() {
+ Menu.setIsOptionChecked("Enable avatar collisions", 1);
+ }
+
+ function changeAvatar() {
+ originalAvatar = MyAvatar.skeletonModelURL;
+ MyAvatar.skeletonModelURL = AVATAR_URL;
+ }
+
+ function importModel() {
+ var success = Clipboard.importEntities(MODEL_URL);
+ var spawnLocation = MyAvatar.position;
+ if (success) {
+ importedEntityIDs = Clipboard.pasteEntities(spawnLocation);
+ }
+ }
+
+ function processImportedEntities() {
+ importedEntityIDs.forEach(function(id){
+ var props = Entities.getEntityProperties(id);
+ if (props.name === "Selfie Stick") {
+ selfieStickEntityID = id;
+ } else if (props.name === "Lens") {
+ lensEntityID = id;
+ }
+ });
+ }
+
+ function setupSpaceBarControl() {
+ var mappingName = "Handheld-Cam-Space-Bar";
+ var myMapping = Controller.newMapping(mappingName);
+ myMapping.from(Controller.Hardware.Keyboard.Space).to(function(value){
+ if ( value === 0 ) {
+ return;
+ }
+ if (freeMovementMode) {
+ freeMovementMode = false;
+ Camera.mode = "entity";
+ Camera.cameraEntity = lensEntityID;
+ } else {
+ freeMovementMode = true;
+ Camera.mode = "first person";
+ }
+ });
+ Controller.enableMapping(mappingName);
+ }
+
+ function update(deltaTime) {
+ if (freeMovementMode) {
+ var upFactor = 0.1;
+ var upUnitVec = Vec3.normalize(Quat.getUp(MyAvatar.orientation));
+ var upOffset = Vec3.multiply(upUnitVec, upFactor);
+ var forwardFactor = -0.1;
+ var forwardUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation));
+ var forwardOffset = Vec3.multiply(forwardUnitVec, forwardFactor);
+ var newPos = Vec3.sum(Vec3.sum(MyAvatar.position, upOffset), forwardOffset);
+ var newRot = MyAvatar.orientation;
+ Entities.editEntity(selfieStickEntityID, {position: newPos, rotation: newRot});
+ } else {
+ var props = Entities.getEntityProperties(selfieStickEntityID);
+ var upFactor = 0.1;
+ var upUnitVec = Vec3.normalize(Quat.getUp(props.rotation));
+ var upOffset = Vec3.multiply(upUnitVec, -upFactor);
+ var forwardFactor = -0.1;
+ var forwardUnitVec = Vec3.normalize(Quat.getFront(props.rotation));
+ var forwardOffset = Vec3.multiply(forwardUnitVec, -forwardFactor);
+ var newPos = Vec3.sum(Vec3.sum(props.position, upOffset), forwardOffset);
+ MyAvatar.position = newPos;
+ MyAvatar.orientation = props.rotation;
+ }
+ }
+
+ // Removes all entities we imported and reset settings we've changed
+ function cleanup() {
+ importedEntityIDs.forEach(function(id) {
+ Entities.deleteEntity(id);
+ });
+ Camera.mode = "first person";
+ Controller.disableMapping("Handheld-Cam-Space-Bar");
+ MyAvatar.skeletonModelURL = originalAvatar;
+ turnOnAvatarCollisions();
+ }
+ Script.scriptEnding.connect(cleanup);
+}()); // END LOCAL_SCOPE
\ No newline at end of file
diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index e1b432d09f..d1c00a9d81 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -1094,7 +1094,6 @@ function MyController(hand) {
this.grabbedOverlay = null;
this.state = STATE_OFF;
this.pointer = null; // entity-id of line object
- this.entityActivated = false;
this.triggerValue = 0; // rolling average of trigger value
this.triggerClicked = false;
@@ -2826,12 +2825,6 @@ function MyController(hand) {
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
- if (this.entityActivated) {
- var saveGrabbedID = this.grabbedThingID;
- this.release();
- this.grabbedThingID = saveGrabbedID;
- }
-
var grabbedProperties;
if (this.grabbedIsOverlay) {
grabbedProperties = {
@@ -3007,22 +3000,25 @@ function MyController(hand) {
* is called correctly, as these just freshly created entity may not have completely initialized.
*/
var grabEquipCheck = function () {
- if (_this.state == STATE_NEAR_GRABBING) {
- _this.callEntityMethodOnGrabbed("startNearGrab");
+ if (_this.state == STATE_NEAR_GRABBING) {
+ _this.callEntityMethodOnGrabbed("startNearGrab");
} else { // this.state == STATE_HOLD
- _this.callEntityMethodOnGrabbed("startEquip");
+ _this.callEntityMethodOnGrabbed("startEquip");
}
- _this.currentHandControllerTipPosition =
- (_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
- _this.currentObjectTime = Date.now();
+ // don't block teleport raypick with equipped entity
+ Messages.sendMessage('Hifi-Teleport-Ignore-Add', _this.grabbedThingID);
- _this.currentObjectPosition = grabbedProperties.position;
- _this.currentObjectRotation = grabbedProperties.rotation;
- _this.currentVelocity = ZERO_VEC;
- _this.currentAngularVelocity = ZERO_VEC;
+ _this.currentHandControllerTipPosition =
+ (_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
+ _this.currentObjectTime = Date.now();
- _this.prevDropDetected = false;
+ _this.currentObjectPosition = grabbedProperties.position;
+ _this.currentObjectRotation = grabbedProperties.rotation;
+ _this.currentVelocity = ZERO_VEC;
+ _this.currentAngularVelocity = ZERO_VEC;
+
+ _this.prevDropDetected = false;
}
if (isClone) {
@@ -3654,6 +3650,9 @@ function MyController(hand) {
this.turnOffVisualizations();
if (this.grabbedThingID !== null) {
+
+ Messages.sendMessage('Hifi-Teleport-Ignore-Remove', this.grabbedThingID);
+
if (this.state === STATE_HOLD) {
this.callEntityMethodOnGrabbed("releaseEquip");
}
diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js
index eb95d9d8a3..84f7357b1a 100644
--- a/scripts/system/tablet-goto.js
+++ b/scripts/system/tablet-goto.js
@@ -29,10 +29,15 @@
}
function onScreenChanged(type, url) {
- // for toolbar mode: change button to active when window is first openend, false otherwise.
- button.editProperties({isActive: shouldActivateButton});
- shouldActivateButton = false;
- onGotoScreen = false;
+ if (url === gotoQmlSource) {
+ onGotoScreen = true;
+ shouldActivateButton = true;
+ button.editProperties({isActive: shouldActivateButton});
+ } else {
+ shouldActivateButton = false;
+ onGotoScreen = false;
+ button.editProperties({isActive: shouldActivateButton});
+ }
}
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");