mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 15:44:13 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into ambient-bis
This commit is contained in:
commit
16e6f0900d
55 changed files with 1802 additions and 435 deletions
|
@ -200,7 +200,7 @@ void AvatarMixer::manageDisplayName(const SharedNodePointer& node) {
|
||||||
QString baseName = avatar.getDisplayName().trimmed();
|
QString baseName = avatar.getDisplayName().trimmed();
|
||||||
const QRegularExpression curses { "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
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.
|
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);
|
baseName = baseName.remove(trailingDigits);
|
||||||
if (baseName.isEmpty()) {
|
if (baseName.isEmpty()) {
|
||||||
baseName = "anonymous";
|
baseName = "anonymous";
|
||||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.2
|
import QtQuick.Controls 1.2
|
||||||
import QtWebChannel 1.0
|
import QtWebChannel 1.0
|
||||||
import QtWebEngine 1.2
|
import QtWebEngine 1.2
|
||||||
|
import FileTypeProfile 1.0
|
||||||
|
|
||||||
import "controls-uit"
|
import "controls-uit"
|
||||||
import "styles" as HifiStyles
|
import "styles" as HifiStyles
|
||||||
|
@ -216,6 +217,11 @@ ScrollingWindow {
|
||||||
WebChannel.id: "eventBridgeWrapper"
|
WebChannel.id: "eventBridgeWrapper"
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile: FileTypeProfile {
|
||||||
|
id: webviewProfile
|
||||||
|
storageName: "qmlWebEngine"
|
||||||
|
}
|
||||||
|
|
||||||
webChannel.registeredObjects: [eventBridgeWrapper]
|
webChannel.registeredObjects: [eventBridgeWrapper]
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ Item {
|
||||||
id: pingCol
|
id: pingCol
|
||||||
spacing: 4; x: 4; y: 4;
|
spacing: 4; x: 4; y: 4;
|
||||||
StatText {
|
StatText {
|
||||||
text: "Audio ping: " + root.audioPing
|
text: "Audio ping/loss: " + root.audioPing + "/" + root.audioPacketLoss + "%"
|
||||||
}
|
}
|
||||||
StatText {
|
StatText {
|
||||||
text: "Avatar ping: " + root.avatarPing
|
text: "Avatar ping: " + root.avatarPing
|
||||||
|
|
|
@ -104,6 +104,7 @@ Item {
|
||||||
|
|
||||||
// Required to support clicking on "hifi://" links
|
// Required to support clicking on "hifi://" links
|
||||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||||
|
urlAppend(loadRequest.url.toString())
|
||||||
var url = loadRequest.url.toString();
|
var url = loadRequest.url.toString();
|
||||||
if (urlHandler.canHandleUrl(url)) {
|
if (urlHandler.canHandleUrl(url)) {
|
||||||
if (urlHandler.handleUrl(url)) {
|
if (urlHandler.handleUrl(url)) {
|
||||||
|
@ -113,12 +114,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onNavigationRequested: {
|
|
||||||
if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) {
|
|
||||||
pagesModel.append({webUrl: request.url.toString()})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onNewViewRequested: {
|
onNewViewRequested: {
|
||||||
request.openIn(webView);
|
request.openIn(webView);
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gotoPage(url) {
|
function gotoPage(url) {
|
||||||
pagesModel.append({webUrl: url})
|
urlAppend(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadPage() {
|
function reloadPage() {
|
||||||
|
@ -126,9 +126,20 @@ Item {
|
||||||
view.setEnabled(true);
|
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: {
|
onCurrentPageChanged: {
|
||||||
if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
|
if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
|
||||||
loader.item.url = pagesModel.get(currentPage).webUrl
|
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) {
|
if (currentPage >= 0) {
|
||||||
//we got something to load already
|
//we got something to load already
|
||||||
item.url = pagesModel.get(currentPage).webUrl
|
item.url = pagesModel.get(currentPage).webUrl
|
||||||
|
web.address = loader.item.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
interface/resources/qml/controls/WebEntityView.qml
Normal file
22
interface/resources/qml/controls/WebEntityView.qml
Normal file
|
@ -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";
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ Item {
|
||||||
property alias eventBridge: eventBridgeWrapper.eventBridge
|
property alias eventBridge: eventBridgeWrapper.eventBridge
|
||||||
property alias canGoBack: root.canGoBack;
|
property alias canGoBack: root.canGoBack;
|
||||||
property var goBack: root.goBack;
|
property var goBack: root.goBack;
|
||||||
|
property alias urlTag: root.urlTag
|
||||||
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
||||||
property bool keyboardRaised: false
|
property bool keyboardRaised: false
|
||||||
property bool punctuationMode: false
|
property bool punctuationMode: false
|
||||||
|
@ -27,6 +28,8 @@ Item {
|
||||||
WebChannel.id: "eventBridgeWrapper"
|
WebChannel.id: "eventBridgeWrapper"
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property alias viewProfile: root.profile
|
||||||
|
|
||||||
WebEngineView {
|
WebEngineView {
|
||||||
id: root
|
id: root
|
||||||
|
@ -66,6 +69,8 @@ Item {
|
||||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||||
worldId: WebEngineScript.MainWorld
|
worldId: WebEngineScript.MainWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property string urlTag: "noDownload=false";
|
||||||
|
|
||||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||||
|
|
||||||
|
@ -94,6 +99,7 @@ Item {
|
||||||
// Required to support clicking on "hifi://" links
|
// Required to support clicking on "hifi://" links
|
||||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||||
var url = loadRequest.url.toString();
|
var url = loadRequest.url.toString();
|
||||||
|
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
|
||||||
if (urlHandler.canHandleUrl(url)) {
|
if (urlHandler.canHandleUrl(url)) {
|
||||||
if (urlHandler.handleUrl(url)) {
|
if (urlHandler.handleUrl(url)) {
|
||||||
root.stop();
|
root.stop();
|
||||||
|
|
|
@ -243,12 +243,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DropShadow {
|
|
||||||
anchors.fill: actionIcon
|
|
||||||
radius: 8.0
|
|
||||||
color: "#80000000"
|
|
||||||
source: actionIcon
|
|
||||||
}
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: messageArea;
|
id: messageArea;
|
||||||
width: rectIcon.width;
|
width: rectIcon.width;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
import "../controls-uit"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property var dialogTitleText : "";
|
property var dialogTitleText : "";
|
||||||
|
@ -67,6 +68,29 @@ Item {
|
||||||
verticalAlignment: Text.AlignTop;
|
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 {
|
ListModel {
|
||||||
id: comboListViewModel;
|
id: comboListViewModel;
|
||||||
}
|
}
|
||||||
|
@ -92,8 +116,7 @@ Item {
|
||||||
color: selectedOptionIndex === index ? '#cee6ff' : 'white';
|
color: selectedOptionIndex === index ? '#cee6ff' : 'white';
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: comboOptionSelected;
|
id: comboOptionSelected;
|
||||||
visible: selectedOptionIndex === index ? true : false;
|
color: selectedOptionIndex == index ? hifi.colors.blueAccent : 'white';
|
||||||
color: hifi.colors.blueAccent;
|
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
@ -102,7 +125,7 @@ Item {
|
||||||
height: width;
|
height: width;
|
||||||
radius: width;
|
radius: width;
|
||||||
border.width: 3;
|
border.width: 3;
|
||||||
border.color: hifi.colors.blueHighlight;
|
border.color: selectedOptionIndex === index ? hifi.colors.blueHighlight: hifi.colors.lightGrayText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,28 @@ Item {
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
textFormat: Text.StyledText
|
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
|
// Popup Text
|
||||||
Text {
|
Text {
|
||||||
|
|
|
@ -310,9 +310,9 @@ Rectangle {
|
||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
onClicked: letterbox(hifi.glyphs.question,
|
onClicked: letterbox(hifi.glyphs.question,
|
||||||
"Connections and Friends",
|
"Connections and Friends",
|
||||||
"<font color='purple'>Purple borders around profile pictures are <b>Connections</b>.</font><br>" +
|
"<font color='purple'>Purple borders around profile pictures represent <b>Connections</b>.</font><br>" +
|
||||||
"When your availability is set to Everyone, Connections can see your username and location.<br><br>" +
|
"When your availability is set to Everyone, Connections can see your username and location.<br><br>" +
|
||||||
"<font color='green'>Green borders around profile pictures are <b>Friends</b>.</font><br>" +
|
"<font color='green'>Green borders around profile pictures represent <b>Friends</b>.</font><br>" +
|
||||||
"When your availability is set to Friends, only Friends can see your username and location.");
|
"When your availability is set to Friends, only Friends can see your username and location.");
|
||||||
onEntered: connectionsHelpText.color = hifi.colors.blueHighlight;
|
onEntered: connectionsHelpText.color = hifi.colors.blueHighlight;
|
||||||
onExited: connectionsHelpText.color = hifi.colors.blueAccent;
|
onExited: connectionsHelpText.color = hifi.colors.blueAccent;
|
||||||
|
|
|
@ -33,14 +33,25 @@ StackView {
|
||||||
property int cardHeight: 320;
|
property int cardHeight: 320;
|
||||||
property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/";
|
property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/";
|
||||||
|
|
||||||
|
property var tablet: null;
|
||||||
|
property bool isDesktop: false;
|
||||||
|
|
||||||
Component { id: tabletStoryCard; TabletStoryCard {} }
|
Component { id: tabletStoryCard; TabletStoryCard {} }
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
root.currentItem.focus = true;
|
root.currentItem.focus = true;
|
||||||
root.currentItem.forceActiveFocus();
|
root.currentItem.forceActiveFocus();
|
||||||
|
addressLine.focus = true;
|
||||||
|
addressLine.forceActiveFocus();
|
||||||
fillDestinations();
|
fillDestinations();
|
||||||
updateLocationText(false);
|
updateLocationText(false);
|
||||||
root.parentChanged.connect(center);
|
root.parentChanged.connect(center);
|
||||||
center();
|
center();
|
||||||
|
isDesktop = (typeof desktop !== "undefined");
|
||||||
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
||||||
|
if (desktop) {
|
||||||
|
root.title = "GOTO";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
root.parentChanged.disconnect(center);
|
root.parentChanged.disconnect(center);
|
||||||
|
@ -108,6 +119,8 @@ StackView {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
addressBarDialog.loadHome();
|
addressBarDialog.loadHome();
|
||||||
tabletRoot.shown = false;
|
tabletRoot.shown = false;
|
||||||
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
}
|
}
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
@ -294,6 +307,7 @@ StackView {
|
||||||
right: parent.right
|
right: parent.right
|
||||||
leftMargin: 10
|
leftMargin: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
model: suggestions
|
model: suggestions
|
||||||
orientation: ListView.Vertical
|
orientation: ListView.Vertical
|
||||||
|
|
||||||
|
@ -547,6 +561,13 @@ StackView {
|
||||||
if (addressLine.text !== "") {
|
if (addressLine.text !== "") {
|
||||||
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
|
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDesktop) {
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
} else {
|
||||||
|
HMD.closeTablet();
|
||||||
|
}
|
||||||
|
|
||||||
tabletRoot.shown = false;
|
tabletRoot.shown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,10 @@ Item {
|
||||||
property bool pinned: false
|
property bool pinned: false
|
||||||
clip: true
|
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();
|
onButtonStateChanged: updateYOffset();
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|
|
@ -142,6 +142,7 @@
|
||||||
#include "ModelPackager.h"
|
#include "ModelPackager.h"
|
||||||
#include "networking/HFWebEngineProfile.h"
|
#include "networking/HFWebEngineProfile.h"
|
||||||
#include "networking/HFTabletWebEngineProfile.h"
|
#include "networking/HFTabletWebEngineProfile.h"
|
||||||
|
#include "networking/FileTypeProfile.h"
|
||||||
#include "scripting/TestScriptingInterface.h"
|
#include "scripting/TestScriptingInterface.h"
|
||||||
#include "scripting/AccountScriptingInterface.h"
|
#include "scripting/AccountScriptingInterface.h"
|
||||||
#include "scripting/AssetMappingsScriptingInterface.h"
|
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||||
|
@ -218,6 +219,7 @@ static const QString FST_EXTENSION = ".fst";
|
||||||
static const QString FBX_EXTENSION = ".fbx";
|
static const QString FBX_EXTENSION = ".fbx";
|
||||||
static const QString OBJ_EXTENSION = ".obj";
|
static const QString OBJ_EXTENSION = ".obj";
|
||||||
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
||||||
|
static const QString WEB_VIEW_TAG = "noDownload=true";
|
||||||
|
|
||||||
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
|
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
|
||||||
|
|
||||||
|
@ -1934,6 +1936,7 @@ void Application::initializeUi() {
|
||||||
|
|
||||||
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
|
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
|
||||||
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
|
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
|
||||||
|
qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
offscreenUi->create(_glWidget->qglContext());
|
offscreenUi->create(_glWidget->qglContext());
|
||||||
|
@ -2010,6 +2013,7 @@ void Application::initializeUi() {
|
||||||
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||||
|
|
||||||
rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||||
|
rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||||
rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||||
rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||||
|
@ -5545,7 +5549,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
|
|
||||||
bool Application::canAcceptURL(const QString& urlString) const {
|
bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
QUrl url(urlString);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
||||||
|
@ -5653,7 +5659,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
QUrl scriptURL { scriptFilenameOrURL };
|
QUrl scriptURL { scriptFilenameOrURL };
|
||||||
|
|
||||||
if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
|
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;
|
QString message = "Would you like to run this script:\n" + shortName;
|
||||||
|
|
26
interface/src/networking/FileTypeProfile.cpp
Normal file
26
interface/src/networking/FileTypeProfile.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
25
interface/src/networking/FileTypeProfile.h
Normal file
25
interface/src/networking/FileTypeProfile.h
Normal file
|
@ -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 <QtWebEngine/QQuickWebEngineProfile>
|
||||||
|
|
||||||
|
class FileTypeProfile : public QQuickWebEngineProfile {
|
||||||
|
public:
|
||||||
|
FileTypeProfile(QObject* parent = Q_NULLPTR);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // hifi_FileTypeProfile_h
|
21
interface/src/networking/FileTypeRequestInterceptor.cpp
Normal file
21
interface/src/networking/FileTypeRequestInterceptor.cpp
Normal file
|
@ -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 <QtCore/QDebug>
|
||||||
|
|
||||||
|
#include "RequestFilters.h"
|
||||||
|
|
||||||
|
void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
|
||||||
|
RequestFilters::interceptHFWebEngineRequest(info);
|
||||||
|
RequestFilters::interceptFileType(info);
|
||||||
|
}
|
26
interface/src/networking/FileTypeRequestInterceptor.h
Normal file
26
interface/src/networking/FileTypeRequestInterceptor.h
Normal file
|
@ -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 <QWebEngineUrlRequestInterceptor>
|
||||||
|
|
||||||
|
class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor {
|
||||||
|
public:
|
||||||
|
FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {};
|
||||||
|
|
||||||
|
virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_FileTypeRequestInterceptor_h
|
|
@ -10,35 +10,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "HFWebEngineRequestInterceptor.h"
|
#include "HFWebEngineRequestInterceptor.h"
|
||||||
#include "NetworkingConstants.h"
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include "RequestFilters.h"
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
|
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
|
||||||
// check if this is a request to a highfidelity URL
|
RequestFilters::interceptHFWebEngineRequest(info);
|
||||||
if (isAuthableHighFidelityURL(info.requestUrl())) {
|
|
||||||
// if we have an access token, add it to the right HTTP header for authorization
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
65
interface/src/networking/RequestFilters.cpp
Normal file
65
interface/src/networking/RequestFilters.cpp
Normal file
|
@ -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 <QtCore/QDebug>
|
||||||
|
|
||||||
|
#include <AccountManager.h>
|
||||||
|
|
||||||
|
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<AccountManager>();
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
28
interface/src/networking/RequestFilters.h
Normal file
28
interface/src/networking/RequestFilters.h
Normal file
|
@ -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 <QObject>
|
||||||
|
#include <QWebEngineUrlRequestInfo>
|
||||||
|
|
||||||
|
class RequestFilters : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info);
|
||||||
|
static void interceptFileType(QWebEngineUrlRequestInfo& info);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_RequestFilters_h
|
|
@ -31,6 +31,7 @@
|
||||||
#include "TabletScriptingInterface.h"
|
#include "TabletScriptingInterface.h"
|
||||||
#include "scripting/HMDScriptingInterface.h"
|
#include "scripting/HMDScriptingInterface.h"
|
||||||
|
|
||||||
|
static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml";
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
||||||
if (!member) {
|
if (!member) {
|
||||||
|
@ -46,12 +47,48 @@ void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsManager::toggleAddressBar() {
|
void DialogsManager::toggleAddressBar() {
|
||||||
AddressBarDialog::toggle();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
emit addressBarToggled();
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
auto tablet = dynamic_cast<TabletProxy*>(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() {
|
void DialogsManager::showAddressBar() {
|
||||||
AddressBarDialog::show();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||||
|
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
|
||||||
|
|
||||||
|
if (!hmd->getShouldShowTablet()) {
|
||||||
|
hmd->openTablet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsManager::showFeed() {
|
void DialogsManager::showFeed() {
|
||||||
|
|
|
@ -79,6 +79,7 @@ private:
|
||||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||||
QPointer<TestingDialog> _testingDialog;
|
QPointer<TestingDialog> _testingDialog;
|
||||||
QPointer<DomainConnectionDialog> _domainConnectionDialog;
|
QPointer<DomainConnectionDialog> _domainConnectionDialog;
|
||||||
|
bool _closeAddressBar { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DialogsManager_h
|
#endif // hifi_DialogsManager_h
|
||||||
|
|
|
@ -126,7 +126,7 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(updatedAvatarCount, avatarManager->getNumAvatarsUpdated());
|
STAT_UPDATE(updatedAvatarCount, avatarManager->getNumAvatarsUpdated());
|
||||||
STAT_UPDATE(notUpdatedAvatarCount, avatarManager->getNumAvatarsNotUpdated());
|
STAT_UPDATE(notUpdatedAvatarCount, avatarManager->getNumAvatarsNotUpdated());
|
||||||
STAT_UPDATE(serverCount, (int)nodeList->size());
|
STAT_UPDATE(serverCount, (int)nodeList->size());
|
||||||
STAT_UPDATE(framerate, qApp->getFps());
|
STAT_UPDATE_FLOAT(framerate, qApp->getFps(), 0.1f);
|
||||||
if (qApp->getActiveDisplayPlugin()) {
|
if (qApp->getActiveDisplayPlugin()) {
|
||||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||||
auto stats = displayPlugin->getHardwareStats();
|
auto stats = displayPlugin->getHardwareStats();
|
||||||
|
@ -134,11 +134,11 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(longrenders, stats["long_render_count"].toInt());
|
STAT_UPDATE(longrenders, stats["long_render_count"].toInt());
|
||||||
STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt());
|
STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt());
|
||||||
STAT_UPDATE(longframes, stats["long_frame_count"].toInt());
|
STAT_UPDATE(longframes, stats["long_frame_count"].toInt());
|
||||||
STAT_UPDATE(renderrate, displayPlugin->renderRate());
|
STAT_UPDATE_FLOAT(renderrate, displayPlugin->renderRate(), 0.1f);
|
||||||
STAT_UPDATE(presentrate, displayPlugin->presentRate());
|
STAT_UPDATE_FLOAT(presentrate, displayPlugin->presentRate(), 0.1f);
|
||||||
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
|
STAT_UPDATE_FLOAT(presentnewrate, displayPlugin->newFramePresentRate(), 0.1f);
|
||||||
STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate());
|
STAT_UPDATE_FLOAT(presentdroprate, displayPlugin->droppedFrameRate(), 0.1f);
|
||||||
STAT_UPDATE(stutterrate, displayPlugin->stutterRate());
|
STAT_UPDATE_FLOAT(stutterrate, displayPlugin->stutterRate(), 0.1f);
|
||||||
} else {
|
} else {
|
||||||
STAT_UPDATE(appdropped, -1);
|
STAT_UPDATE(appdropped, -1);
|
||||||
STAT_UPDATE(longrenders, -1);
|
STAT_UPDATE(longrenders, -1);
|
||||||
|
@ -151,8 +151,8 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(avatarSimrate, (int)qApp->getAvatarSimrate());
|
STAT_UPDATE(avatarSimrate, (int)qApp->getAvatarSimrate());
|
||||||
|
|
||||||
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||||
STAT_UPDATE(packetInCount, bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond());
|
STAT_UPDATE(packetInCount, (int)bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond());
|
||||||
STAT_UPDATE(packetOutCount, bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond());
|
STAT_UPDATE(packetOutCount, (int)bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond());
|
||||||
STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f);
|
STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f);
|
||||||
STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 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 avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer);
|
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(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1);
|
||||||
STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1);
|
STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1);
|
||||||
STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1);
|
STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1);
|
||||||
|
@ -196,36 +200,36 @@ void Stats::updateStats(bool force) {
|
||||||
if (_expanded || force) {
|
if (_expanded || force) {
|
||||||
SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
if (avatarMixer) {
|
if (avatarMixer) {
|
||||||
STAT_UPDATE(avatarMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
|
STAT_UPDATE(avatarMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
|
||||||
STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
|
STAT_UPDATE(avatarMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||||
STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
|
STAT_UPDATE(avatarMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
|
||||||
STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
|
STAT_UPDATE(avatarMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||||
} else {
|
} else {
|
||||||
STAT_UPDATE(avatarMixerInKbps, -1);
|
STAT_UPDATE(avatarMixerInKbps, -1);
|
||||||
STAT_UPDATE(avatarMixerInPps, -1);
|
STAT_UPDATE(avatarMixerInPps, -1);
|
||||||
STAT_UPDATE(avatarMixerOutKbps, -1);
|
STAT_UPDATE(avatarMixerOutKbps, -1);
|
||||||
STAT_UPDATE(avatarMixerOutPps, -1);
|
STAT_UPDATE(avatarMixerOutPps, -1);
|
||||||
}
|
}
|
||||||
STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate());
|
STAT_UPDATE_FLOAT(myAvatarSendRate, avatarManager->getMyAvatarSendRate(), 0.1f);
|
||||||
|
|
||||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||||
auto audioClient = DependencyManager::get<AudioClient>();
|
auto audioClient = DependencyManager::get<AudioClient>();
|
||||||
if (audioMixerNode || force) {
|
if (audioMixerNode || force) {
|
||||||
STAT_UPDATE(audioMixerKbps, roundf(
|
STAT_UPDATE(audioMixerKbps, (int)roundf(
|
||||||
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +
|
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +
|
||||||
bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||||
STAT_UPDATE(audioMixerPps, roundf(
|
STAT_UPDATE(audioMixerPps, (int)roundf(
|
||||||
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) +
|
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) +
|
||||||
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||||
|
|
||||||
STAT_UPDATE(audioMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
|
STAT_UPDATE(audioMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||||
STAT_UPDATE(audioMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
|
STAT_UPDATE(audioMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
|
||||||
STAT_UPDATE(audioMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
STAT_UPDATE(audioMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||||
STAT_UPDATE(audioMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
STAT_UPDATE(audioMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||||
STAT_UPDATE(audioAudioInboundPPS, audioClient->getAudioInboundPPS());
|
STAT_UPDATE(audioAudioInboundPPS, (int)audioClient->getAudioInboundPPS());
|
||||||
STAT_UPDATE(audioSilentInboundPPS, audioClient->getSilentInboundPPS());
|
STAT_UPDATE(audioSilentInboundPPS, (int)audioClient->getSilentInboundPPS());
|
||||||
STAT_UPDATE(audioOutboundPPS, audioClient->getAudioOutboundPPS());
|
STAT_UPDATE(audioOutboundPPS, (int)audioClient->getAudioOutboundPPS());
|
||||||
STAT_UPDATE(audioSilentOutboundPPS, audioClient->getSilentOutboundPPS());
|
STAT_UPDATE(audioSilentOutboundPPS, (int)audioClient->getSilentOutboundPPS());
|
||||||
} else {
|
} else {
|
||||||
STAT_UPDATE(audioMixerKbps, -1);
|
STAT_UPDATE(audioMixerKbps, -1);
|
||||||
STAT_UPDATE(audioMixerPps, -1);
|
STAT_UPDATE(audioMixerPps, -1);
|
||||||
|
|
|
@ -81,6 +81,7 @@ class Stats : public QQuickItem {
|
||||||
STATS_PROPERTY(int, audioSilentOutboundPPS, 0)
|
STATS_PROPERTY(int, audioSilentOutboundPPS, 0)
|
||||||
STATS_PROPERTY(int, audioAudioInboundPPS, 0)
|
STATS_PROPERTY(int, audioAudioInboundPPS, 0)
|
||||||
STATS_PROPERTY(int, audioSilentInboundPPS, 0)
|
STATS_PROPERTY(int, audioSilentInboundPPS, 0)
|
||||||
|
STATS_PROPERTY(int, audioPacketLoss, 0)
|
||||||
STATS_PROPERTY(QString, audioCodec, QString())
|
STATS_PROPERTY(QString, audioCodec, QString())
|
||||||
STATS_PROPERTY(QString, audioNoiseGate, QString())
|
STATS_PROPERTY(QString, audioNoiseGate, QString())
|
||||||
|
|
||||||
|
@ -204,6 +205,7 @@ signals:
|
||||||
void audioSilentOutboundPPSChanged();
|
void audioSilentOutboundPPSChanged();
|
||||||
void audioAudioInboundPPSChanged();
|
void audioAudioInboundPPSChanged();
|
||||||
void audioSilentInboundPPSChanged();
|
void audioSilentInboundPPSChanged();
|
||||||
|
void audioPacketLossChanged();
|
||||||
void audioCodecChanged();
|
void audioCodecChanged();
|
||||||
void audioNoiseGateChanged();
|
void audioNoiseGateChanged();
|
||||||
|
|
||||||
|
@ -263,4 +265,3 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Stats_h
|
#endif // hifi_Stats_h
|
||||||
|
|
||||||
|
|
|
@ -277,10 +277,11 @@ bool RenderableModelEntityItem::getAnimationFrame() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_animation && _animation->isLoaded()) {
|
auto animation = getAnimation();
|
||||||
|
if (animation && animation->isLoaded()) {
|
||||||
|
|
||||||
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
const QVector<FBXAnimationFrame>& frames = animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||||
auto& fbxJoints = _animation->getGeometry().joints;
|
auto& fbxJoints = animation->getGeometry().joints;
|
||||||
|
|
||||||
int frameCount = frames.size();
|
int frameCount = frames.size();
|
||||||
if (frameCount > 0) {
|
if (frameCount > 0) {
|
||||||
|
@ -566,7 +567,7 @@ void RenderableModelEntityItem::update(const quint64& now) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a copy of the animation properites
|
// make a copy of the animation properites
|
||||||
_renderAnimationProperties = _animationProperties;
|
_renderAnimationProperties = getAnimationProperties();
|
||||||
|
|
||||||
ModelEntityItem::update(now);
|
ModelEntityItem::update(now);
|
||||||
}
|
}
|
||||||
|
@ -608,11 +609,11 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
|
||||||
|
|
||||||
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
||||||
ModelEntityItem::setShapeType(type);
|
ModelEntityItem::setShapeType(type);
|
||||||
if (_shapeType == SHAPE_TYPE_COMPOUND) {
|
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||||
if (!_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
|
if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
|
||||||
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(getCompoundShapeURL());
|
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(getCompoundShapeURL());
|
||||||
}
|
}
|
||||||
} else if (_compoundShapeResource && !_compoundShapeURL.isEmpty()) {
|
} else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
|
||||||
// the compoundURL has been set but the shapeType does not agree
|
// the compoundURL has been set but the shapeType does not agree
|
||||||
_compoundShapeResource.reset();
|
_compoundShapeResource.reset();
|
||||||
}
|
}
|
||||||
|
@ -627,7 +628,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
if (tree) {
|
if (tree) {
|
||||||
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
||||||
}
|
}
|
||||||
if (_shapeType == SHAPE_TYPE_COMPOUND) {
|
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||||
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(url);
|
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +638,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
|
||||||
ShapeType type = getShapeType();
|
ShapeType type = getShapeType();
|
||||||
|
|
||||||
if (type == SHAPE_TYPE_COMPOUND) {
|
if (type == SHAPE_TYPE_COMPOUND) {
|
||||||
if (!_model || _compoundShapeURL.isEmpty()) {
|
if (!_model || getCompoundShapeURL().isEmpty()) {
|
||||||
EntityTreePointer tree = getTree();
|
EntityTreePointer tree = getTree();
|
||||||
if (tree) {
|
if (tree) {
|
||||||
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
||||||
|
@ -659,8 +660,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
|
||||||
doInitialModelSimulation();
|
doInitialModelSimulation();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (!_compoundShapeURL.isEmpty()) {
|
} else if (!getCompoundShapeURL().isEmpty()) {
|
||||||
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(_compoundShapeURL);
|
_compoundShapeResource = DependencyManager::get<ModelCache>()->getGeometryResource(getCompoundShapeURL());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,7 +776,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
||||||
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset;
|
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) {
|
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||||
// should never fall in here when model not fully loaded
|
// should never fall in here when model not fully loaded
|
||||||
assert(_model && _model->isLoaded());
|
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 {
|
} else {
|
||||||
ModelEntityItem::computeShapeInfo(shapeInfo);
|
ModelEntityItem::computeShapeInfo(shapeInfo);
|
||||||
shapeInfo.setParams(type, 0.5f * dimensions);
|
shapeInfo.setParams(type, 0.5f * dimensions);
|
||||||
|
|
|
@ -660,22 +660,22 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) {
|
void RenderablePolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) {
|
||||||
if (xTextureURL != _xTextureURL) {
|
if (xTextureURL != getXTextureURL()) {
|
||||||
_xTexture.clear();
|
_xTexture.clear();
|
||||||
PolyVoxEntityItem::setXTextureURL(xTextureURL);
|
PolyVoxEntityItem::setXTextureURL(xTextureURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) {
|
void RenderablePolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) {
|
||||||
if (yTextureURL != _yTextureURL) {
|
if (yTextureURL != getYTextureURL()) {
|
||||||
_yTexture.clear();
|
_yTexture.clear();
|
||||||
PolyVoxEntityItem::setYTextureURL(yTextureURL);
|
PolyVoxEntityItem::setYTextureURL(yTextureURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) {
|
void RenderablePolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) {
|
||||||
if (zTextureURL != _zTextureURL) {
|
if (zTextureURL != getZTextureURL()) {
|
||||||
_zTexture.clear();
|
_zTexture.clear();
|
||||||
PolyVoxEntityItem::setZTextureURL(zTextureURL);
|
PolyVoxEntityItem::setZTextureURL(zTextureURL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,9 +101,9 @@ public:
|
||||||
virtual bool setAll(uint8_t toValue) override;
|
virtual bool setAll(uint8_t toValue) override;
|
||||||
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
|
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
|
||||||
|
|
||||||
virtual void setXTextureURL(QString xTextureURL) override;
|
virtual void setXTextureURL(const QString& xTextureURL) override;
|
||||||
virtual void setYTextureURL(QString yTextureURL) override;
|
virtual void setYTextureURL(const QString& yTextureURL) override;
|
||||||
virtual void setZTextureURL(QString zTextureURL) override;
|
virtual void setZTextureURL(const QString& zTextureURL) override;
|
||||||
|
|
||||||
virtual bool addToScene(EntityItemPointer self,
|
virtual bool addToScene(EntityItemPointer self,
|
||||||
std::shared_ptr<render::Scene> scene,
|
std::shared_ptr<render::Scene> scene,
|
||||||
|
|
|
@ -77,14 +77,16 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
||||||
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true);
|
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true);
|
||||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
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
|
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
||||||
batch.setModelTransform(transformToTopLeft);
|
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,
|
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
||||||
dimensions.y - 2.0f * topMargin);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() {
|
||||||
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
|
_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));
|
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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.
|
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
|
||||||
if (overwriteLocalData) weOwnSimulation = false;
|
if (overwriteLocalData) weOwnSimulation = false;
|
||||||
} else if (_simulationOwner.set(newSimOwner)) {
|
} else if (_simulationOwner.set(newSimOwner)) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||||
somethingChanged = true;
|
somethingChanged = true;
|
||||||
// recompute weOwnSimulation for later
|
// recompute weOwnSimulation for later
|
||||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||||
|
@ -695,19 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
weOwnSimulation = true;
|
weOwnSimulation = true;
|
||||||
if (!_simulationOwner.isNull()) {
|
if (!_simulationOwner.isNull()) {
|
||||||
// someone else really did own it
|
// someone else really did own it
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||||
somethingChanged = true;
|
somethingChanged = true;
|
||||||
_simulationOwner.clearCurrentOwner();
|
_simulationOwner.clearCurrentOwner();
|
||||||
}
|
}
|
||||||
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
|
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
|
||||||
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
|
// 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.
|
// this could happen when the user reloads the cache and entity tree.
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||||
somethingChanged = true;
|
somethingChanged = true;
|
||||||
_simulationOwner.clearCurrentOwner();
|
_simulationOwner.clearCurrentOwner();
|
||||||
weOwnSimulation = false;
|
weOwnSimulation = false;
|
||||||
} else if (_simulationOwner.set(newSimOwner)) {
|
} else if (_simulationOwner.set(newSimOwner)) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||||
somethingChanged = true;
|
somethingChanged = true;
|
||||||
// recompute weOwnSimulation for later
|
// recompute weOwnSimulation for later
|
||||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||||
|
@ -909,19 +909,23 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk
|
||||||
|
|
||||||
float EntityItem::computeMass() const {
|
float EntityItem::computeMass() const {
|
||||||
glm::vec3 dimensions = getDimensions();
|
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) {
|
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) {
|
void EntityItem::updateDensity(float density) {
|
||||||
float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||||
if (_density != clampedDensity) {
|
withWriteLock([&] {
|
||||||
_density = clampedDensity;
|
if (_density != clampedDensity) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
_density = clampedDensity;
|
||||||
}
|
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setMass(float mass) {
|
void EntityItem::setMass(float mass) {
|
||||||
|
@ -941,10 +945,12 @@ void EntityItem::setMass(float mass) {
|
||||||
} else {
|
} else {
|
||||||
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||||
}
|
}
|
||||||
if (_density != newDensity) {
|
withWriteLock([&] {
|
||||||
_density = newDensity;
|
if (_density != newDensity) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
_density = newDensity;
|
||||||
}
|
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setHref(QString value) {
|
void EntityItem::setHref(QString value) {
|
||||||
|
@ -952,32 +958,47 @@ void EntityItem::setHref(QString value) {
|
||||||
if (! (value.toLower().startsWith("hifi://")) ) {
|
if (! (value.toLower().startsWith("hifi://")) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_href = value;
|
withWriteLock([&] {
|
||||||
|
_href = value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setCollisionSoundURL(const QString& value) {
|
void EntityItem::setCollisionSoundURL(const QString& value) {
|
||||||
if (_collisionSoundURL != value) {
|
bool modified = false;
|
||||||
_collisionSoundURL = value;
|
withWriteLock([&] {
|
||||||
|
if (_collisionSoundURL != value) {
|
||||||
|
_collisionSoundURL = value;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (modified) {
|
||||||
if (auto myTree = getTree()) {
|
if (auto myTree = getTree()) {
|
||||||
myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID());
|
myTree->notifyNewCollisionSoundURL(value, getEntityItemID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedSoundPointer EntityItem::getCollisionSound() {
|
SharedSoundPointer EntityItem::getCollisionSound() {
|
||||||
if (!_collisionSound) {
|
SharedSoundPointer result;
|
||||||
_collisionSound = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
|
withReadLock([&] {
|
||||||
|
result = _collisionSound;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
result = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
|
||||||
|
withWriteLock([&] {
|
||||||
|
_collisionSound = result;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return _collisionSound;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::simulate(const quint64& now) {
|
void EntityItem::simulate(const quint64& now) {
|
||||||
if (_lastSimulated == 0) {
|
if (getLastSimulated() == 0) {
|
||||||
_lastSimulated = now;
|
setLastSimulated(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
float timeElapsed = (float)(now - getLastSimulated()) / (float)(USECS_PER_SECOND);
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entities) << "********** EntityItem::simulate()";
|
qCDebug(entities) << "********** EntityItem::simulate()";
|
||||||
|
@ -1021,10 +1042,10 @@ void EntityItem::simulate(const quint64& now) {
|
||||||
if (!stepKinematicMotion(timeElapsed)) {
|
if (!stepKinematicMotion(timeElapsed)) {
|
||||||
// this entity is no longer moving
|
// this entity is no longer moving
|
||||||
// flag it to transition from KINEMATIC to STATIC
|
// flag it to transition from KINEMATIC to STATIC
|
||||||
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;
|
markDirtyFlags(Simulation::DIRTY_MOTION_TYPE);
|
||||||
setAcceleration(Vectors::ZERO);
|
setAcceleration(Vectors::ZERO);
|
||||||
}
|
}
|
||||||
_lastSimulated = now;
|
setLastSimulated(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityItem::stepKinematicMotion(float timeElapsed) {
|
bool EntityItem::stepKinematicMotion(float timeElapsed) {
|
||||||
|
@ -1056,9 +1077,10 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
|
||||||
timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED);
|
timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED);
|
||||||
|
|
||||||
if (isSpinning) {
|
if (isSpinning) {
|
||||||
|
float angularDamping = getAngularDamping();
|
||||||
// angular damping
|
// angular damping
|
||||||
if (_angularDamping > 0.0f) {
|
if (angularDamping > 0.0f) {
|
||||||
angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
|
angularVelocity *= powf(1.0f - angularDamping, timeElapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED =
|
const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED =
|
||||||
|
@ -1086,15 +1108,17 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) {
|
||||||
glm::vec3 deltaVelocity = Vectors::ZERO;
|
glm::vec3 deltaVelocity = Vectors::ZERO;
|
||||||
|
|
||||||
// linear damping
|
// linear damping
|
||||||
if (_damping > 0.0f) {
|
float damping = getDamping();
|
||||||
deltaVelocity = (powf(1.0f - _damping, timeElapsed) - 1.0f) * linearVelocity;
|
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
|
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
|
// yes acceleration
|
||||||
// acceleration is in world-frame but we need it in local-frame
|
// acceleration is in world-frame but we need it in local-frame
|
||||||
glm::vec3 linearAcceleration = _acceleration;
|
glm::vec3 linearAcceleration = acceleration;
|
||||||
bool success;
|
bool success;
|
||||||
Transform parentTransform = getParentTransform(success);
|
Transform parentTransform = getParentTransform(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -1180,7 +1204,7 @@ bool EntityItem::lifetimeHasExpired() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 EntityItem::getExpiry() 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 {
|
EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||||
|
@ -1189,10 +1213,10 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
||||||
EntityItemProperties properties(propertyFlags);
|
EntityItemProperties properties(propertyFlags);
|
||||||
properties._id = getID();
|
properties._id = getID();
|
||||||
properties._idSet = true;
|
properties._idSet = true;
|
||||||
properties._created = _created;
|
properties._created = getCreated();
|
||||||
properties._lastEdited = _lastEdited;
|
properties._lastEdited = getLastEdited();
|
||||||
properties.setClientOnly(_clientOnly);
|
properties.setClientOnly(getClientOnly());
|
||||||
properties.setOwningAvatarID(_owningAvatarID);
|
properties.setOwningAvatarID(getOwningAvatarID());
|
||||||
|
|
||||||
properties._type = getType();
|
properties._type = getType();
|
||||||
|
|
||||||
|
@ -1259,7 +1283,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
|
||||||
properties._angularVelocity = getLocalAngularVelocity();
|
properties._angularVelocity = getLocalAngularVelocity();
|
||||||
}
|
}
|
||||||
if (!properties._accelerationChanged) {
|
if (!properties._accelerationChanged) {
|
||||||
properties._acceleration = _acceleration;
|
properties._acceleration = getAcceleration();
|
||||||
}
|
}
|
||||||
|
|
||||||
properties._positionChanged = true;
|
properties._positionChanged = true;
|
||||||
|
@ -1270,7 +1294,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::pokeSimulationOwnership() {
|
void EntityItem::pokeSimulationOwnership() {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE;
|
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE);
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
|
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
|
||||||
// we already own it
|
// we already own it
|
||||||
|
@ -1282,7 +1306,7 @@ void EntityItem::pokeSimulationOwnership() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::grabSimulationOwnership() {
|
void EntityItem::grabSimulationOwnership() {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB;
|
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
|
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
|
||||||
// we already own it
|
// we already own it
|
||||||
|
@ -1575,18 +1599,18 @@ float EntityItem::getVolumeEstimate() const {
|
||||||
void EntityItem::updateRegistrationPoint(const glm::vec3& value) {
|
void EntityItem::updateRegistrationPoint(const glm::vec3& value) {
|
||||||
if (value != _registrationPoint) {
|
if (value != _registrationPoint) {
|
||||||
setRegistrationPoint(value);
|
setRegistrationPoint(value);
|
||||||
_dirtyFlags |= Simulation::DIRTY_SHAPE;
|
markDirtyFlags(Simulation::DIRTY_SHAPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updatePosition(const glm::vec3& value) {
|
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||||
if (getLocalPosition() != value) {
|
if (getLocalPosition() != value) {
|
||||||
setLocalPosition(value);
|
setLocalPosition(value);
|
||||||
_dirtyFlags |= Simulation::DIRTY_POSITION;
|
markDirtyFlags(Simulation::DIRTY_POSITION);
|
||||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||||
if (object->getNestableType() == NestableType::Entity) {
|
if (object->getNestableType() == NestableType::Entity) {
|
||||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(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) {
|
void EntityItem::updateParentID(const QUuid& value) {
|
||||||
if (getParentID() != value) {
|
if (getParentID() != value) {
|
||||||
setParentID(value);
|
setParentID(value);
|
||||||
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; // children are forced to be kinematic
|
// children are forced to be kinematic
|
||||||
_dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
// 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) {
|
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||||
if (getDimensions() != value) {
|
if (getDimensions() != value) {
|
||||||
setDimensions(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) {
|
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||||
if (object->getNestableType() == NestableType::Entity) {
|
if (object->getNestableType() == NestableType::Entity) {
|
||||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||||
entity->_dirtyFlags |= Simulation::DIRTY_ROTATION;
|
entity->markDirtyFlags(Simulation::DIRTY_ROTATION | Simulation::DIRTY_POSITION);
|
||||||
entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1777,20 +1801,26 @@ void EntityItem::updateRestitution(float value) {
|
||||||
|
|
||||||
void EntityItem::updateFriction(float value) {
|
void EntityItem::updateFriction(float value) {
|
||||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
|
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
|
||||||
if (_friction != clampedValue) {
|
withWriteLock([&] {
|
||||||
_friction = clampedValue;
|
if (_friction != clampedValue) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
|
_friction = clampedValue;
|
||||||
}
|
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setRestitution(float value) {
|
void EntityItem::setRestitution(float value) {
|
||||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION);
|
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) {
|
void EntityItem::setFriction(float value) {
|
||||||
float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION);
|
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) {
|
void EntityItem::updateLifetime(float value) {
|
||||||
|
@ -1883,7 +1913,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_simulationOwner.set(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:
|
// 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)
|
// (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
|
// (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 =
|
static QString repeatedMessage =
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*");
|
LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*");
|
||||||
qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for"
|
qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for"
|
||||||
<< getID() << getName();
|
<< getID() << _name; // getName();
|
||||||
removeActionInternal(actionID, nullptr);
|
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
|
// the json filter syntax did not match what we expected, return a match
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,22 +110,21 @@ public:
|
||||||
virtual void somethingChangedNotification() { }
|
virtual void somethingChangedNotification() { }
|
||||||
|
|
||||||
void recordCreationTime(); // set _created to 'now'
|
void recordCreationTime(); // set _created to 'now'
|
||||||
quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs
|
quint64 getLastSimulated() const; /// Last simulated time of this entity universal usecs
|
||||||
void setLastSimulated(quint64 now) { _lastSimulated = now; }
|
void setLastSimulated(quint64 now);
|
||||||
|
|
||||||
/// Last edited time of this entity universal usecs
|
/// Last edited time of this entity universal usecs
|
||||||
quint64 getLastEdited() const { return _lastEdited; }
|
quint64 getLastEdited() const;
|
||||||
void setLastEdited(quint64 lastEdited)
|
void setLastEdited(quint64 lastEdited);
|
||||||
{ _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
|
|
||||||
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
||||||
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
||||||
|
|
||||||
/// Last time we sent out an edit packet for this entity
|
/// Last time we sent out an edit packet for this entity
|
||||||
quint64 getLastBroadcast() const { return _lastBroadcast; }
|
quint64 getLastBroadcast() const;
|
||||||
void setLastBroadcast(quint64 lastBroadcast) { _lastBroadcast = lastBroadcast; }
|
void setLastBroadcast(quint64 lastBroadcast);
|
||||||
|
|
||||||
void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); }
|
void markAsChangedOnServer();
|
||||||
quint64 getLastChangedOnServer() const { return _changedOnServer; }
|
quint64 getLastChangedOnServer() const;
|
||||||
|
|
||||||
// TODO: eventually only include properties changed since the params.lastQuerySent time
|
// TODO: eventually only include properties changed since the params.lastQuerySent time
|
||||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||||
|
@ -163,8 +162,8 @@ public:
|
||||||
static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew);
|
static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew);
|
||||||
|
|
||||||
// perform update
|
// perform update
|
||||||
virtual void update(const quint64& now) { _lastUpdated = now; }
|
virtual void update(const quint64& now);
|
||||||
quint64 getLastUpdated() const { return _lastUpdated; }
|
quint64 getLastUpdated() const;
|
||||||
|
|
||||||
// perform linear extrapolation for SimpleEntitySimulation
|
// perform linear extrapolation for SimpleEntitySimulation
|
||||||
void simulate(const quint64& now);
|
void simulate(const quint64& now);
|
||||||
|
@ -188,63 +187,63 @@ public:
|
||||||
|
|
||||||
const Transform getTransformToCenter(bool& success) const;
|
const Transform getTransformToCenter(bool& success) const;
|
||||||
|
|
||||||
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
|
inline void requiresRecalcBoxes();
|
||||||
|
|
||||||
// Hyperlink related getters and setters
|
// Hyperlink related getters and setters
|
||||||
QString getHref() const { return _href; }
|
QString getHref() const;
|
||||||
void setHref(QString value);
|
void setHref(QString value);
|
||||||
|
|
||||||
QString getDescription() const { return _description; }
|
QString getDescription() const;
|
||||||
void setDescription(QString value) { _description = value; }
|
void setDescription(const QString& value);
|
||||||
|
|
||||||
/// Dimensions in meters (0.0 - TREE_SCALE)
|
/// Dimensions in meters (0.0 - TREE_SCALE)
|
||||||
inline const glm::vec3 getDimensions() const { return getScale(); }
|
inline const glm::vec3 getDimensions() const { return getScale(); }
|
||||||
virtual void setDimensions(const glm::vec3& value);
|
virtual void setDimensions(const glm::vec3& value);
|
||||||
|
|
||||||
float getLocalRenderAlpha() const { return _localRenderAlpha; }
|
float getLocalRenderAlpha() const;
|
||||||
void setLocalRenderAlpha(float localRenderAlpha) { _localRenderAlpha = localRenderAlpha; }
|
void setLocalRenderAlpha(float localRenderAlpha);
|
||||||
|
|
||||||
void setDensity(float density);
|
void setDensity(float density);
|
||||||
float computeMass() const;
|
float computeMass() const;
|
||||||
void setMass(float mass);
|
void setMass(float mass);
|
||||||
|
|
||||||
float getDensity() const { return _density; }
|
float getDensity() const;
|
||||||
|
|
||||||
bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
|
|
||||||
const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters
|
glm::vec3 getGravity() const; /// get gravity in meters
|
||||||
void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters
|
void setGravity(const glm::vec3& value); /// gravity in meters
|
||||||
bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasGravity() const { return getGravity() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
|
|
||||||
const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second
|
glm::vec3 getAcceleration() const; /// get acceleration in meters/second/second
|
||||||
void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second
|
void setAcceleration(const glm::vec3& value); /// acceleration in meters/second/second
|
||||||
bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasAcceleration() const { return getAcceleration() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
|
|
||||||
float getDamping() const { return _damping; }
|
float getDamping() const;
|
||||||
void setDamping(float value) { _damping = value; }
|
void setDamping(float value);
|
||||||
|
|
||||||
float getRestitution() const { return _restitution; }
|
float getRestitution() const;
|
||||||
void setRestitution(float value);
|
void setRestitution(float value);
|
||||||
|
|
||||||
float getFriction() const { return _friction; }
|
float getFriction() const;
|
||||||
void setFriction(float value);
|
void setFriction(float value);
|
||||||
|
|
||||||
// lifetime related properties.
|
// lifetime related properties.
|
||||||
float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
|
float getLifetime() const; /// get the lifetime in seconds for the entity
|
||||||
void setLifetime(float value) { _lifetime = value; } /// set 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
|
quint64 getCreated() const; /// get the created-time in useconds for the entity
|
||||||
void setCreated(quint64 value) { _created = value; } /// set 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
|
/// 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
|
/// 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
|
/// 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;
|
bool lifetimeHasExpired() const;
|
||||||
quint64 getExpiry() const;
|
quint64 getExpiry() const;
|
||||||
|
|
||||||
|
@ -256,63 +255,61 @@ public:
|
||||||
using SpatiallyNestable::getQueryAACube;
|
using SpatiallyNestable::getQueryAACube;
|
||||||
virtual AACube getQueryAACube(bool& success) const override;
|
virtual AACube getQueryAACube(bool& success) const override;
|
||||||
|
|
||||||
QString getScript() const { return _script; }
|
QString getScript() const;
|
||||||
void setScript(const QString& value) { _script = value; }
|
void setScript(const QString& value);
|
||||||
|
|
||||||
quint64 getScriptTimestamp() const { return _scriptTimestamp; }
|
quint64 getScriptTimestamp() const;
|
||||||
void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
|
void setScriptTimestamp(const quint64 value);
|
||||||
|
|
||||||
QString getServerScripts() const { return _serverScripts; }
|
QString getServerScripts() const;
|
||||||
void setServerScripts(const QString& serverScripts)
|
void setServerScripts(const QString& serverScripts);
|
||||||
{ _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); }
|
|
||||||
|
|
||||||
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
|
QString getCollisionSoundURL() const;
|
||||||
void setCollisionSoundURL(const QString& value);
|
void setCollisionSoundURL(const QString& value);
|
||||||
|
|
||||||
SharedSoundPointer getCollisionSound();
|
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
|
/// registration point as ratio of entity
|
||||||
void setRegistrationPoint(const glm::vec3& value) {
|
void setRegistrationPoint(const glm::vec3& value);
|
||||||
_registrationPoint = glm::clamp(value, 0.0f, 1.0f); dimensionsChanged(); // Registration Point affects the bounding box
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; }
|
||||||
|
|
||||||
float getAngularDamping() const { return _angularDamping; }
|
float getAngularDamping() const;
|
||||||
void setAngularDamping(float value) { _angularDamping = value; }
|
void setAngularDamping(float value);
|
||||||
|
|
||||||
QString getName() const { return _name; }
|
QString getName() const;
|
||||||
void setName(const QString& value) { _name = value; }
|
void setName(const QString& value);
|
||||||
QString getDebugName() { return _name != "" ? _name : getID().toString(); }
|
QString getDebugName();
|
||||||
|
|
||||||
bool getVisible() const { return _visible; }
|
bool getVisible() const;
|
||||||
void setVisible(bool value) { _visible = value; }
|
void setVisible(bool value);
|
||||||
bool isVisible() const { return _visible; }
|
inline bool isVisible() const { return getVisible(); }
|
||||||
bool isInvisible() const { return !_visible; }
|
inline bool isInvisible() const { return !getVisible(); }
|
||||||
|
|
||||||
bool getCollisionless() const { return _collisionless; }
|
bool getCollisionless() const;
|
||||||
void setCollisionless(bool value) { _collisionless = value; }
|
void setCollisionless(bool value);
|
||||||
|
|
||||||
uint8_t getCollisionMask() const { return _collisionMask; }
|
uint8_t getCollisionMask() const;
|
||||||
void setCollisionMask(uint8_t value) { _collisionMask = value; }
|
void setCollisionMask(uint8_t value);
|
||||||
|
|
||||||
void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const;
|
void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const;
|
||||||
|
|
||||||
bool getDynamic() const { return SHAPE_TYPE_STATIC_MESH == getShapeType() ? false : _dynamic; }
|
bool getDynamic() const;
|
||||||
void setDynamic(bool value) { _dynamic = value; }
|
void setDynamic(bool value);
|
||||||
|
|
||||||
virtual bool shouldBePhysical() const { return false; }
|
virtual bool shouldBePhysical() const { return false; }
|
||||||
|
|
||||||
bool getLocked() const { return _locked; }
|
bool getLocked() const;
|
||||||
void setLocked(bool value) { _locked = value; }
|
void setLocked(bool value);
|
||||||
|
|
||||||
const QString& getUserData() const { return _userData; }
|
QString getUserData() const;
|
||||||
virtual void setUserData(const QString& value) { _userData = value; }
|
virtual void setUserData(const QString& value);
|
||||||
|
|
||||||
|
// FIXME not thread safe?
|
||||||
const SimulationOwner& getSimulationOwner() const { return _simulationOwner; }
|
const SimulationOwner& getSimulationOwner() const { return _simulationOwner; }
|
||||||
void setSimulationOwner(const QUuid& id, quint8 priority);
|
void setSimulationOwner(const QUuid& id, quint8 priority);
|
||||||
void setSimulationOwner(const SimulationOwner& owner);
|
void setSimulationOwner(const SimulationOwner& owner);
|
||||||
|
@ -325,8 +322,8 @@ public:
|
||||||
void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
|
void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
|
||||||
void rememberHasSimulationOwnershipBid() const;
|
void rememberHasSimulationOwnershipBid() const;
|
||||||
|
|
||||||
const QString& getMarketplaceID() const { return _marketplaceID; }
|
QString getMarketplaceID() const;
|
||||||
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
|
void setMarketplaceID(const QString& value);
|
||||||
|
|
||||||
// TODO: get rid of users of getRadius()...
|
// TODO: get rid of users of getRadius()...
|
||||||
float getRadius() const;
|
float getRadius() const;
|
||||||
|
@ -369,8 +366,9 @@ public:
|
||||||
void updateCreated(uint64_t value);
|
void updateCreated(uint64_t value);
|
||||||
virtual void setShapeType(ShapeType type) { /* do nothing */ }
|
virtual void setShapeType(ShapeType type) { /* do nothing */ }
|
||||||
|
|
||||||
uint32_t getDirtyFlags() const { return _dirtyFlags; }
|
uint32_t getDirtyFlags() const;
|
||||||
void clearDirtyFlags(uint32_t mask = 0xffffffff) { _dirtyFlags &= ~mask; }
|
void markDirtyFlags(uint32_t mask);
|
||||||
|
void clearDirtyFlags(uint32_t mask = 0xffffffff);
|
||||||
|
|
||||||
bool isMoving() const;
|
bool isMoving() const;
|
||||||
bool isMovingRelativeToParent() const;
|
bool isMovingRelativeToParent() const;
|
||||||
|
|
|
@ -69,38 +69,59 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEntityItem::setFalloffRadius(float value) {
|
void LightEntityItem::setFalloffRadius(float value) {
|
||||||
_falloffRadius = glm::max(value, 0.0f);
|
value = glm::max(value, 0.0f);
|
||||||
_lightPropertiesChanged = true;
|
if (value == getFalloffRadius()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
withWriteLock([&] {
|
||||||
|
_falloffRadius = value;
|
||||||
|
_lightPropertiesChanged = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEntityItem::setIsSpotlight(bool value) {
|
void LightEntityItem::setIsSpotlight(bool value) {
|
||||||
if (value != _isSpotlight) {
|
if (value == getIsSpotlight()) {
|
||||||
_isSpotlight = value;
|
return;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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,
|
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
|
||||||
// so update the dimensions to reflect this.
|
// so update the dimensions to reflect this.
|
||||||
const float length = getDimensions().z;
|
const float length = getDimensions().z;
|
||||||
const float width = length * glm::sin(glm::radians(_cutoff));
|
const float width = length * glm::sin(glm::radians(_cutoff));
|
||||||
setDimensions(glm::vec3(width, width, length));
|
setDimensions(glm::vec3(width, width, length));
|
||||||
}
|
}
|
||||||
_lightPropertiesChanged = true;
|
|
||||||
|
withWriteLock([&] {
|
||||||
|
_lightPropertiesChanged = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
|
bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
|
@ -205,5 +226,86 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
||||||
|
|
||||||
void LightEntityItem::somethingChangedNotification() {
|
void LightEntityItem::somethingChangedNotification() {
|
||||||
EntityItem::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,47 +57,33 @@ public:
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||||
bool& somethingChanged) override;
|
bool& somethingChanged) override;
|
||||||
|
|
||||||
const rgbColor& getColor() const { return _color; }
|
const rgbColor& getColor() const;
|
||||||
xColor getXColor() const {
|
xColor getXColor() const;
|
||||||
xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
void setColor(const rgbColor& value);
|
||||||
void setColor(const xColor& value) {
|
void setColor(const xColor& value);
|
||||||
_color[RED_INDEX] = value.red;
|
|
||||||
_color[GREEN_INDEX] = value.green;
|
|
||||||
_color[BLUE_INDEX] = value.blue;
|
|
||||||
_lightPropertiesChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getIsSpotlight() const { return _isSpotlight; }
|
bool getIsSpotlight() const;
|
||||||
void setIsSpotlight(bool value);
|
void setIsSpotlight(bool value);
|
||||||
|
|
||||||
void setIgnoredColor(const rgbColor& value) { }
|
void setIgnoredColor(const rgbColor& value) { }
|
||||||
void setIgnoredAttenuation(float value) { }
|
void setIgnoredAttenuation(float value) { }
|
||||||
|
|
||||||
float getIntensity() const { return _intensity; }
|
float getIntensity() const;
|
||||||
void setIntensity(float value) {
|
void setIntensity(float value);
|
||||||
_intensity = value;
|
float getFalloffRadius() const;
|
||||||
_lightPropertiesChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getFalloffRadius() const { return _falloffRadius; }
|
|
||||||
void setFalloffRadius(float value);
|
void setFalloffRadius(float value);
|
||||||
|
|
||||||
float getExponent() const { return _exponent; }
|
float getExponent() const;
|
||||||
void setExponent(float value) {
|
void setExponent(float value);
|
||||||
_exponent = value;
|
|
||||||
_lightPropertiesChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getCutoff() const { return _cutoff; }
|
float getCutoff() const;
|
||||||
void setCutoff(float value);
|
void setCutoff(float value);
|
||||||
|
|
||||||
static bool getLightsArePickable() { return _lightsArePickable; }
|
static bool getLightsArePickable() { return _lightsArePickable; }
|
||||||
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
|
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
|
||||||
|
|
||||||
// properties of a light
|
// properties of a light
|
||||||
|
@ -108,6 +94,7 @@ protected:
|
||||||
float _exponent { DEFAULT_EXPONENT };
|
float _exponent { DEFAULT_EXPONENT };
|
||||||
float _cutoff { DEFAULT_CUTOFF };
|
float _cutoff { DEFAULT_CUTOFF };
|
||||||
|
|
||||||
|
protected:
|
||||||
// Dirty flag turn true when either light properties is changing values.
|
// Dirty flag turn true when either light properties is changing values.
|
||||||
// This gets back to false in the somethingChangedNotification() call
|
// This gets back to false in the somethingChangedNotification() call
|
||||||
// Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity.
|
// Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity.
|
||||||
|
|
|
@ -34,8 +34,8 @@ EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const En
|
||||||
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
|
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
|
||||||
EntityItem(entityItemID),
|
EntityItem(entityItemID),
|
||||||
_lineWidth(DEFAULT_LINE_WIDTH),
|
_lineWidth(DEFAULT_LINE_WIDTH),
|
||||||
_pointsChanged(true),
|
_points(QVector<glm::vec3>(0)),
|
||||||
_points(QVector<glm::vec3>(0))
|
_pointsChanged(true)
|
||||||
{
|
{
|
||||||
_type = EntityTypes::Line;
|
_type = EntityTypes::Line;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,10 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) {
|
||||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_points << point;
|
withWriteLock([&] {
|
||||||
_pointsChanged = true;
|
_points << point;
|
||||||
|
_pointsChanged = true;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +107,11 @@ bool LineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_points = points;
|
|
||||||
_pointsChanged = true;
|
withWriteLock([&] {
|
||||||
|
_points = points;
|
||||||
|
_pointsChanged = true;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,3 +164,51 @@ void LineEntityItem::debugDump() const {
|
||||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
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<glm::vec3> LineEntityItem::getLinePoints() const {
|
||||||
|
QVector<glm::vec3> result;
|
||||||
|
withReadLock([&] {
|
||||||
|
result = _points;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -42,23 +42,19 @@ class LineEntityItem : public EntityItem {
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||||
bool& somethingChanged) override;
|
bool& somethingChanged) override;
|
||||||
|
|
||||||
const rgbColor& getColor() const { return _color; }
|
const rgbColor& getColor() const;
|
||||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
xColor getXColor() const;
|
||||||
|
|
||||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
void setColor(const rgbColor& value);
|
||||||
void setColor(const xColor& value) {
|
void setColor(const xColor& value);
|
||||||
_color[RED_INDEX] = value.red;
|
|
||||||
_color[GREEN_INDEX] = value.green;
|
|
||||||
_color[BLUE_INDEX] = value.blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLineWidth(float lineWidth){ _lineWidth = lineWidth; }
|
void setLineWidth(float lineWidth);
|
||||||
float getLineWidth() const{ return _lineWidth; }
|
float getLineWidth() const;
|
||||||
|
|
||||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||||
bool appendPoint(const glm::vec3& point);
|
bool appendPoint(const glm::vec3& point);
|
||||||
|
|
||||||
const QVector<glm::vec3>& getLinePoints() const{ return _points; }
|
QVector<glm::vec3> getLinePoints() const;
|
||||||
|
|
||||||
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; }
|
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 float DEFAULT_LINE_WIDTH;
|
||||||
static const int MAX_POINTS_PER_LINE;
|
static const int MAX_POINTS_PER_LINE;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
rgbColor _color;
|
rgbColor _color;
|
||||||
float _lineWidth;
|
float _lineWidth;
|
||||||
bool _pointsChanged;
|
|
||||||
QVector<glm::vec3> _points;
|
QVector<glm::vec3> _points;
|
||||||
|
protected:
|
||||||
|
bool _pointsChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_LineEntityItem_h
|
#endif // hifi_LineEntityItem_h
|
||||||
|
|
|
@ -733,3 +733,20 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
|
||||||
_timeUntilNextEmit = 0.0f;
|
_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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -205,13 +205,8 @@ public:
|
||||||
void computeAndUpdateDimensions();
|
void computeAndUpdateDimensions();
|
||||||
|
|
||||||
static const QString DEFAULT_TEXTURES;
|
static const QString DEFAULT_TEXTURES;
|
||||||
const QString& getTextures() const { return _textures; }
|
QString getTextures() const;
|
||||||
void setTextures(const QString& textures) {
|
void setTextures(const QString& textures);
|
||||||
if (_textures != textures) {
|
|
||||||
_textures = textures;
|
|
||||||
_texturesChangedFlag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const bool DEFAULT_EMITTER_SHOULD_TRAIL;
|
static const bool DEFAULT_EMITTER_SHOULD_TRAIL;
|
||||||
bool getEmitterShouldTrail() const { return _emitterShouldTrail; }
|
bool getEmitterShouldTrail() const { return _emitterShouldTrail; }
|
||||||
|
|
|
@ -104,14 +104,18 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
|
||||||
|
|
||||||
|
|
||||||
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
||||||
_strokeWidths = strokeWidths;
|
withWriteLock([&] {
|
||||||
_strokeWidthsChanged = true;
|
_strokeWidths = strokeWidths;
|
||||||
|
_strokeWidthsChanged = true;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
||||||
_normals = normals;
|
withWriteLock([&] {
|
||||||
_normalsChanged = true;
|
_normals = normals;
|
||||||
|
_normalsChanged = true;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,35 +123,39 @@ bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||||
if (points.size() > MAX_POINTS_PER_LINE) {
|
if (points.size() > MAX_POINTS_PER_LINE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (points.size() != _points.size()) {
|
bool result = false;
|
||||||
_pointsChanged = true;
|
withWriteLock([&] {
|
||||||
}
|
//Check to see if points actually changed. If they haven't, return before doing anything else
|
||||||
//Check to see if points actually changed. If they haven't, return before doing anything else
|
if (points.size() != _points.size()) {
|
||||||
else if (points.size() == _points.size()) {
|
_pointsChanged = true;
|
||||||
//same number of points, so now compare every point
|
} else if (points.size() == _points.size()) {
|
||||||
for (int i = 0; i < points.size(); i++) {
|
//same number of points, so now compare every point
|
||||||
if (points.at(i) != _points.at(i)){
|
for (int i = 0; i < points.size(); i++) {
|
||||||
_pointsChanged = true;
|
if (points.at(i) != _points.at(i)) {
|
||||||
break;
|
_pointsChanged = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!_pointsChanged) {
|
||||||
if (!_pointsChanged) {
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_points = points;
|
for (int i = 0; i < points.size(); i++) {
|
||||||
return true;
|
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,
|
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
|
@ -210,3 +218,45 @@ void PolyLineEntityItem::debugDump() const {
|
||||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QVector<glm::vec3> PolyLineEntityItem::getLinePoints() const {
|
||||||
|
QVector<glm::vec3> result;
|
||||||
|
withReadLock([&] {
|
||||||
|
result = _points;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::vec3> PolyLineEntityItem::getNormals() const {
|
||||||
|
QVector<glm::vec3> result;
|
||||||
|
withReadLock([&] {
|
||||||
|
result = _normals;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<float> PolyLineEntityItem::getStrokeWidths() const {
|
||||||
|
QVector<float> 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -59,21 +59,16 @@ class PolyLineEntityItem : public EntityItem {
|
||||||
|
|
||||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||||
bool appendPoint(const glm::vec3& point);
|
bool appendPoint(const glm::vec3& point);
|
||||||
const QVector<glm::vec3>& getLinePoints() const{ return _points; }
|
QVector<glm::vec3> getLinePoints() const;
|
||||||
|
|
||||||
bool setNormals(const QVector<glm::vec3>& normals);
|
bool setNormals(const QVector<glm::vec3>& normals);
|
||||||
const QVector<glm::vec3>& getNormals() const{ return _normals; }
|
QVector<glm::vec3> getNormals() const;
|
||||||
|
|
||||||
bool setStrokeWidths(const QVector<float>& strokeWidths);
|
bool setStrokeWidths(const QVector<float>& strokeWidths);
|
||||||
const QVector<float>& getStrokeWidths() const{ return _strokeWidths; }
|
QVector<float> getStrokeWidths() const;
|
||||||
|
|
||||||
const QString& getTextures() const { return _textures; }
|
QString getTextures() const;
|
||||||
void setTextures(const QString& textures) {
|
void setTextures(const QString& textures);
|
||||||
if (_textures != textures) {
|
|
||||||
_textures = textures;
|
|
||||||
_texturesChangedFlag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool needsToCallUpdate() const override { return true; }
|
virtual bool needsToCallUpdate() const override { return true; }
|
||||||
|
|
||||||
|
|
|
@ -242,3 +242,129 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
|
||||||
});
|
});
|
||||||
return voxelDataCopy;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -99,36 +99,36 @@ class PolyVoxEntityItem : public EntityItem {
|
||||||
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
|
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
|
||||||
|
|
||||||
static const QString DEFAULT_X_TEXTURE_URL;
|
static const QString DEFAULT_X_TEXTURE_URL;
|
||||||
virtual void setXTextureURL(QString xTextureURL) { _xTextureURL = xTextureURL; }
|
virtual void setXTextureURL(const QString& xTextureURL);
|
||||||
virtual const QString& getXTextureURL() const { return _xTextureURL; }
|
QString getXTextureURL() const;
|
||||||
|
|
||||||
static const QString DEFAULT_Y_TEXTURE_URL;
|
static const QString DEFAULT_Y_TEXTURE_URL;
|
||||||
virtual void setYTextureURL(QString yTextureURL) { _yTextureURL = yTextureURL; }
|
virtual void setYTextureURL(const QString& yTextureURL);
|
||||||
virtual const QString& getYTextureURL() const { return _yTextureURL; }
|
QString getYTextureURL() const;
|
||||||
|
|
||||||
static const QString DEFAULT_Z_TEXTURE_URL;
|
static const QString DEFAULT_Z_TEXTURE_URL;
|
||||||
virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; }
|
virtual void setZTextureURL(const QString& zTextureURL);
|
||||||
virtual const QString& getZTextureURL() const { return _zTextureURL; }
|
QString getZTextureURL() const;
|
||||||
|
|
||||||
virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; }
|
virtual void setXNNeighborID(const EntityItemID& xNNeighborID);
|
||||||
void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); }
|
void setXNNeighborID(const QString& xNNeighborID);
|
||||||
virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; }
|
virtual EntityItemID getXNNeighborID() const;
|
||||||
virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; }
|
virtual void setYNNeighborID(const EntityItemID& yNNeighborID);
|
||||||
void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); }
|
void setYNNeighborID(const QString& yNNeighborID);
|
||||||
virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; }
|
virtual EntityItemID getYNNeighborID() const;
|
||||||
virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; }
|
virtual void setZNNeighborID(const EntityItemID& zNNeighborID);
|
||||||
void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); }
|
void setZNNeighborID(const QString& zNNeighborID);
|
||||||
virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; }
|
virtual EntityItemID getZNNeighborID() const;
|
||||||
|
|
||||||
virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; }
|
virtual void setXPNeighborID(const EntityItemID& xPNeighborID);
|
||||||
void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); }
|
void setXPNeighborID(const QString& xPNeighborID);
|
||||||
virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; }
|
virtual EntityItemID getXPNeighborID() const;
|
||||||
virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; }
|
virtual void setYPNeighborID(const EntityItemID& yPNeighborID);
|
||||||
void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); }
|
void setYPNeighborID(const QString& yPNeighborID);
|
||||||
virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; }
|
virtual EntityItemID getYPNeighborID() const;
|
||||||
virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; }
|
virtual void setZPNeighborID(const EntityItemID& zPNeighborID);
|
||||||
void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); }
|
void setZPNeighborID(const QString& zPNeighborID);
|
||||||
virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; }
|
virtual EntityItemID getZPNeighborID() const;
|
||||||
|
|
||||||
virtual void rebakeMesh() {};
|
virtual void rebakeMesh() {};
|
||||||
|
|
||||||
|
|
|
@ -141,3 +141,98 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
|
||||||
// FIXME - should set face and surfaceNormal
|
// FIXME - should set face and surfaceNormal
|
||||||
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,40 +53,34 @@ public:
|
||||||
void** intersectedObject, bool precisionPicking) const override;
|
void** intersectedObject, bool precisionPicking) const override;
|
||||||
|
|
||||||
static const QString DEFAULT_TEXT;
|
static const QString DEFAULT_TEXT;
|
||||||
void setText(const QString& value) { _text = value; }
|
void setText(const QString& value);
|
||||||
const QString& getText() const { return _text; }
|
QString getText() const;
|
||||||
|
|
||||||
static const float DEFAULT_LINE_HEIGHT;
|
static const float DEFAULT_LINE_HEIGHT;
|
||||||
void setLineHeight(float value) { _lineHeight = value; }
|
void setLineHeight(float value);
|
||||||
float getLineHeight() const { return _lineHeight; }
|
float getLineHeight() const;
|
||||||
|
|
||||||
static const xColor DEFAULT_TEXT_COLOR;
|
static const xColor DEFAULT_TEXT_COLOR;
|
||||||
const rgbColor& getTextColor() const { return _textColor; }
|
// FIXME should not return a reference because of thread safety, but can't return an array
|
||||||
xColor getTextColorX() const { xColor color = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; return color; }
|
const rgbColor& getTextColor() const;
|
||||||
|
xColor getTextColorX() const;
|
||||||
|
|
||||||
void setTextColor(const rgbColor& value) { memcpy(_textColor, value, sizeof(_textColor)); }
|
void setTextColor(const rgbColor& value);
|
||||||
void setTextColor(const xColor& value) {
|
void setTextColor(const xColor& value);
|
||||||
_textColor[RED_INDEX] = value.red;
|
|
||||||
_textColor[GREEN_INDEX] = value.green;
|
|
||||||
_textColor[BLUE_INDEX] = value.blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const xColor DEFAULT_BACKGROUND_COLOR;
|
static const xColor DEFAULT_BACKGROUND_COLOR;
|
||||||
const rgbColor& getBackgroundColor() const { return _backgroundColor; }
|
// FIXME should not return a reference because of thread safety, but can't return an array
|
||||||
xColor getBackgroundColorX() const { xColor color = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; return color; }
|
const rgbColor& getBackgroundColor() const;
|
||||||
|
xColor getBackgroundColorX() const;
|
||||||
|
|
||||||
void setBackgroundColor(const rgbColor& value) { memcpy(_backgroundColor, value, sizeof(_backgroundColor)); }
|
void setBackgroundColor(const rgbColor& value);
|
||||||
void setBackgroundColor(const xColor& value) {
|
void setBackgroundColor(const xColor& value);
|
||||||
_backgroundColor[RED_INDEX] = value.red;
|
|
||||||
_backgroundColor[GREEN_INDEX] = value.green;
|
|
||||||
_backgroundColor[BLUE_INDEX] = value.blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const bool DEFAULT_FACE_CAMERA;
|
static const bool DEFAULT_FACE_CAMERA;
|
||||||
bool getFaceCamera() const { return _faceCamera; }
|
bool getFaceCamera() const;
|
||||||
void setFaceCamera(bool value) { _faceCamera = value; }
|
void setFaceCamera(bool value);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
QString _text;
|
QString _text;
|
||||||
float _lineHeight;
|
float _lineHeight;
|
||||||
rgbColor _textColor;
|
rgbColor _textColor;
|
||||||
|
|
|
@ -124,18 +124,26 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityItem::setSourceUrl(const QString& value) {
|
void WebEntityItem::setSourceUrl(const QString& value) {
|
||||||
if (_sourceUrl != value) {
|
withWriteLock([&] {
|
||||||
auto newURL = QUrl::fromUserInput(value);
|
if (_sourceUrl != value) {
|
||||||
|
auto newURL = QUrl::fromUserInput(value);
|
||||||
|
|
||||||
if (newURL.isValid()) {
|
if (newURL.isValid()) {
|
||||||
_sourceUrl = newURL.toDisplayString();
|
_sourceUrl = newURL.toDisplayString();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL.";
|
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) {
|
void WebEntityItem::setDPI(uint16_t value) {
|
||||||
_dpi = value;
|
_dpi = value;
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
void** intersectedObject, bool precisionPicking) const override;
|
void** intersectedObject, bool precisionPicking) const override;
|
||||||
|
|
||||||
virtual void setSourceUrl(const QString& value);
|
virtual void setSourceUrl(const QString& value);
|
||||||
const QString& getSourceUrl() const;
|
QString getSourceUrl() const;
|
||||||
|
|
||||||
virtual bool wantsHandControllerPointerEvents() const override { return true; }
|
virtual bool wantsHandControllerPointerEvents() const override { return true; }
|
||||||
|
|
||||||
|
|
|
@ -208,10 +208,12 @@ ShapeType ZoneEntityItem::getShapeType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
|
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
_compoundShapeURL = url;
|
withWriteLock([&] {
|
||||||
if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
|
_compoundShapeURL = url;
|
||||||
_shapeType = DEFAULT_SHAPE_TYPE;
|
if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
|
||||||
}
|
_shapeType = DEFAULT_SHAPE_TYPE;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
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) {
|
void ZoneEntityItem::setFilterURL(QString url) {
|
||||||
_filterURL = url;
|
withWriteLock([&] {
|
||||||
|
_filterURL = url;
|
||||||
|
});
|
||||||
if (DependencyManager::isSet<EntityEditFilters>()) {
|
if (DependencyManager::isSet<EntityEditFilters>()) {
|
||||||
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();
|
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();
|
||||||
qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID();
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ public:
|
||||||
void setShapeType(ShapeType type) override { _shapeType = type; }
|
void setShapeType(ShapeType type) override { _shapeType = type; }
|
||||||
virtual ShapeType getShapeType() const override;
|
virtual ShapeType getShapeType() const override;
|
||||||
|
|
||||||
virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); }
|
virtual bool hasCompoundShapeURL() const;
|
||||||
const QString getCompoundShapeURL() const { return _compoundShapeURL; }
|
QString getCompoundShapeURL() const;
|
||||||
virtual void setCompoundShapeURL(const QString& url);
|
virtual void setCompoundShapeURL(const QString& url);
|
||||||
|
|
||||||
const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; }
|
const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; }
|
||||||
|
@ -74,7 +74,7 @@ public:
|
||||||
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
|
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
|
||||||
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
||||||
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
||||||
QString getFilterURL() const { return _filterURL; }
|
QString getFilterURL() const;
|
||||||
void setFilterURL(const QString url);
|
void setFilterURL(const QString url);
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||||
|
|
|
@ -59,8 +59,6 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
||||||
|
|
||||||
bool OffscreenGLCanvas::makeCurrent() {
|
bool OffscreenGLCanvas::makeCurrent() {
|
||||||
bool result = _context->makeCurrent(_offscreenSurface);
|
bool result = _context->makeCurrent(_offscreenSurface);
|
||||||
Q_ASSERT(result);
|
|
||||||
|
|
||||||
std::call_once(_reportOnce, [this]{
|
std::call_once(_reportOnce, [this]{
|
||||||
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||||
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
|
|
@ -612,11 +612,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if the item contains sendToScript signal
|
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
||||||
int sendToScriptIndex = newItem->metaObject()->indexOfSignal("sendToScript");
|
|
||||||
if (sendToScriptIndex != -1) {
|
|
||||||
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The root item is ready. Associate it with the window.
|
// The root item is ready. Associate it with the window.
|
||||||
_rootItem = newItem;
|
_rootItem = newItem;
|
||||||
|
|
|
@ -275,6 +275,9 @@ void TabletProxy::emitWebEvent(QVariant msg) {
|
||||||
emit webEventReceived(msg);
|
emit webEventReceived(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TabletProxy::isPathLoaded(QVariant path) {
|
||||||
|
return path.toString() == _currentPathLoaded.toString();
|
||||||
|
}
|
||||||
void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
|
void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
|
||||||
std::lock_guard<std::mutex> guard(_mutex);
|
std::lock_guard<std::mutex> guard(_mutex);
|
||||||
_qmlOffscreenSurface = qmlOffscreenSurface;
|
_qmlOffscreenSurface = qmlOffscreenSurface;
|
||||||
|
@ -322,6 +325,7 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
|
||||||
removeButtonsFromHomeScreen();
|
removeButtonsFromHomeScreen();
|
||||||
_state = State::Uninitialized;
|
_state = State::Uninitialized;
|
||||||
emit screenChanged(QVariant("Closed"), QVariant(""));
|
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)));
|
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
|
||||||
_state = State::Menu;
|
_state = State::Menu;
|
||||||
emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
|
emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
|
||||||
|
_currentPathLoaded = VRMENU_SOURCE_URL;
|
||||||
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
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));
|
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
|
||||||
_state = State::QML;
|
_state = State::QML;
|
||||||
emit screenChanged(QVariant("QML"), path);
|
emit screenChanged(QVariant("QML"), path);
|
||||||
|
_currentPathLoaded = path;
|
||||||
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -426,6 +432,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
|
||||||
}
|
}
|
||||||
_state = State::Home;
|
_state = State::Home;
|
||||||
emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL));
|
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;
|
_state = State::Web;
|
||||||
emit screenChanged(QVariant("Web"), QVariant(url));
|
emit screenChanged(QVariant("Web"), QVariant(url));
|
||||||
|
_currentPathLoaded = QVariant(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* TabletProxy::addButton(const QVariant& properties) {
|
QObject* TabletProxy::addButton(const QVariant& properties) {
|
||||||
|
|
|
@ -183,6 +183,8 @@ public:
|
||||||
Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
|
Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
|
||||||
Q_INVOKABLE bool getLandscape() { return _landscape; }
|
Q_INVOKABLE bool getLandscape() { return _landscape; }
|
||||||
|
|
||||||
|
Q_INVOKABLE bool isPathLoaded(QVariant path);
|
||||||
|
|
||||||
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
|
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
|
||||||
|
|
||||||
QObject* getTabletSurface();
|
QObject* getTabletSurface();
|
||||||
|
@ -235,6 +237,7 @@ protected:
|
||||||
|
|
||||||
bool _initialScreen { false };
|
bool _initialScreen { false };
|
||||||
QVariant _initialPath { "" };
|
QVariant _initialPath { "" };
|
||||||
|
QVariant _currentPathLoaded { "" };
|
||||||
QString _name;
|
QString _name;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
|
std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
|
||||||
|
|
121
script-archive/selfieStick.js
Normal file
121
script-archive/selfieStick.js
Normal file
|
@ -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
|
|
@ -1094,7 +1094,6 @@ function MyController(hand) {
|
||||||
this.grabbedOverlay = null;
|
this.grabbedOverlay = null;
|
||||||
this.state = STATE_OFF;
|
this.state = STATE_OFF;
|
||||||
this.pointer = null; // entity-id of line object
|
this.pointer = null; // entity-id of line object
|
||||||
this.entityActivated = false;
|
|
||||||
|
|
||||||
this.triggerValue = 0; // rolling average of trigger value
|
this.triggerValue = 0; // rolling average of trigger value
|
||||||
this.triggerClicked = false;
|
this.triggerClicked = false;
|
||||||
|
@ -2826,12 +2825,6 @@ function MyController(hand) {
|
||||||
|
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.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;
|
var grabbedProperties;
|
||||||
if (this.grabbedIsOverlay) {
|
if (this.grabbedIsOverlay) {
|
||||||
grabbedProperties = {
|
grabbedProperties = {
|
||||||
|
@ -3007,22 +3000,25 @@ function MyController(hand) {
|
||||||
* is called correctly, as these just freshly created entity may not have completely initialized.
|
* is called correctly, as these just freshly created entity may not have completely initialized.
|
||||||
*/
|
*/
|
||||||
var grabEquipCheck = function () {
|
var grabEquipCheck = function () {
|
||||||
if (_this.state == STATE_NEAR_GRABBING) {
|
if (_this.state == STATE_NEAR_GRABBING) {
|
||||||
_this.callEntityMethodOnGrabbed("startNearGrab");
|
_this.callEntityMethodOnGrabbed("startNearGrab");
|
||||||
} else { // this.state == STATE_HOLD
|
} else { // this.state == STATE_HOLD
|
||||||
_this.callEntityMethodOnGrabbed("startEquip");
|
_this.callEntityMethodOnGrabbed("startEquip");
|
||||||
}
|
}
|
||||||
|
|
||||||
_this.currentHandControllerTipPosition =
|
// don't block teleport raypick with equipped entity
|
||||||
(_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
Messages.sendMessage('Hifi-Teleport-Ignore-Add', _this.grabbedThingID);
|
||||||
_this.currentObjectTime = Date.now();
|
|
||||||
|
|
||||||
_this.currentObjectPosition = grabbedProperties.position;
|
_this.currentHandControllerTipPosition =
|
||||||
_this.currentObjectRotation = grabbedProperties.rotation;
|
(_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
||||||
_this.currentVelocity = ZERO_VEC;
|
_this.currentObjectTime = Date.now();
|
||||||
_this.currentAngularVelocity = ZERO_VEC;
|
|
||||||
|
|
||||||
_this.prevDropDetected = false;
|
_this.currentObjectPosition = grabbedProperties.position;
|
||||||
|
_this.currentObjectRotation = grabbedProperties.rotation;
|
||||||
|
_this.currentVelocity = ZERO_VEC;
|
||||||
|
_this.currentAngularVelocity = ZERO_VEC;
|
||||||
|
|
||||||
|
_this.prevDropDetected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClone) {
|
if (isClone) {
|
||||||
|
@ -3654,6 +3650,9 @@ function MyController(hand) {
|
||||||
this.turnOffVisualizations();
|
this.turnOffVisualizations();
|
||||||
|
|
||||||
if (this.grabbedThingID !== null) {
|
if (this.grabbedThingID !== null) {
|
||||||
|
|
||||||
|
Messages.sendMessage('Hifi-Teleport-Ignore-Remove', this.grabbedThingID);
|
||||||
|
|
||||||
if (this.state === STATE_HOLD) {
|
if (this.state === STATE_HOLD) {
|
||||||
this.callEntityMethodOnGrabbed("releaseEquip");
|
this.callEntityMethodOnGrabbed("releaseEquip");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function onScreenChanged(type, url) {
|
function onScreenChanged(type, url) {
|
||||||
// for toolbar mode: change button to active when window is first openend, false otherwise.
|
if (url === gotoQmlSource) {
|
||||||
button.editProperties({isActive: shouldActivateButton});
|
onGotoScreen = true;
|
||||||
shouldActivateButton = false;
|
shouldActivateButton = true;
|
||||||
onGotoScreen = false;
|
button.editProperties({isActive: shouldActivateButton});
|
||||||
|
} else {
|
||||||
|
shouldActivateButton = false;
|
||||||
|
onGotoScreen = false;
|
||||||
|
button.editProperties({isActive: shouldActivateButton});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
Loading…
Reference in a new issue