mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-09 05:08:19 +02:00
fixed merge conflicts
This commit is contained in:
commit
eb44e54d87
80 changed files with 1175 additions and 470 deletions
|
@ -11,9 +11,14 @@
|
||||||
|
|
||||||
#include "AssignmentParentFinder.h"
|
#include "AssignmentParentFinder.h"
|
||||||
|
|
||||||
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID) const {
|
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success) const {
|
||||||
SpatiallyNestableWeakPointer parent;
|
SpatiallyNestableWeakPointer parent;
|
||||||
// search entities
|
// search entities
|
||||||
parent = _tree->findEntityByEntityItemID(parentID);
|
parent = _tree->findEntityByEntityItemID(parentID);
|
||||||
|
if (parent.expired()) {
|
||||||
|
success = false;
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class AssignmentParentFinder : public SpatialParentFinder {
|
||||||
public:
|
public:
|
||||||
AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { }
|
AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { }
|
||||||
virtual ~AssignmentParentFinder() { }
|
virtual ~AssignmentParentFinder() { }
|
||||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const;
|
virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EntityTreePointer _tree;
|
EntityTreePointer _tree;
|
||||||
|
|
2
cmake/externals/zlib/CMakeLists.txt
vendored
2
cmake/externals/zlib/CMakeLists.txt
vendored
|
@ -5,7 +5,7 @@ include(ExternalProject)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL http://zlib.net/zlib128.zip
|
URL http://hifi-public.s3.amazonaws.com/dependencies/zlib128.zip
|
||||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||||
LOG_DOWNLOAD 1
|
LOG_DOWNLOAD 1
|
||||||
|
|
|
@ -1372,6 +1372,7 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!this.setupHoldAction()) {
|
if (!this.setupHoldAction()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
// actionInspector.js
|
// actionInspector.js
|
||||||
// examples
|
// examples/debugging/
|
||||||
//
|
//
|
||||||
// Created by Seth Alves on 2015-9-30.
|
// Created by Seth Alves on 2015-9-30.
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
Script.include("libraries/utils.js");
|
Script.include("../libraries/utils.js");
|
||||||
|
|
||||||
|
|
||||||
var INSPECT_RADIUS = 10;
|
var INSPECT_RADIUS = 10;
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
// grabInspector.js
|
// grabInspector.js
|
||||||
// examples
|
// examples/debugging/
|
||||||
//
|
//
|
||||||
// Created by Seth Alves on 2015-9-30.
|
// Created by Seth Alves on 2015-9-30.
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
Script.include("libraries/utils.js");
|
Script.include("../libraries/utils.js");
|
||||||
|
|
||||||
var INSPECT_RADIUS = 10;
|
var INSPECT_RADIUS = 10;
|
||||||
var overlays = {};
|
var overlays = {};
|
58
examples/debugging/queryAACubeInspector.js
Normal file
58
examples/debugging/queryAACubeInspector.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// grabInspector.js
|
||||||
|
// examples/debugging/
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2015-12-19.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// This script draws an overlay cube around nearby entities to show their queryAABoxes.
|
||||||
|
|
||||||
|
|
||||||
|
Script.include("../libraries/utils.js");
|
||||||
|
|
||||||
|
var INSPECT_RADIUS = 10;
|
||||||
|
var overlays = {};
|
||||||
|
|
||||||
|
function updateOverlay(entityID, queryAACube) {
|
||||||
|
var cubeCenter = {x: queryAACube.x + queryAACube.scale / 2.0,
|
||||||
|
y: queryAACube.y + queryAACube.scale / 2.0,
|
||||||
|
z: queryAACube.z + queryAACube.scale / 2.0};
|
||||||
|
|
||||||
|
if (entityID in overlays) {
|
||||||
|
var overlay = overlays[entityID];
|
||||||
|
Overlays.editOverlay(overlay, {
|
||||||
|
position: cubeCenter,
|
||||||
|
size: queryAACube.scale
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
overlays[entityID] = Overlays.addOverlay("cube", {
|
||||||
|
position: cubeCenter,
|
||||||
|
size: queryAACube.scale,
|
||||||
|
color: { red: 0, green: 0, blue: 255},
|
||||||
|
alpha: 1,
|
||||||
|
// borderSize: ...,
|
||||||
|
solid: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.setInterval(function() {
|
||||||
|
var nearbyEntities = Entities.findEntities(MyAvatar.position, INSPECT_RADIUS);
|
||||||
|
for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) {
|
||||||
|
var entityID = nearbyEntities[entityIndex];
|
||||||
|
var queryAACube = Entities.getEntityProperties(entityID, ["queryAACube"]).queryAACube;
|
||||||
|
updateOverlay(entityID, queryAACube);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
for (var entityID in overlays) {
|
||||||
|
Overlays.deleteOverlay(overlays[entityID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
|
@ -17,13 +17,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
Target.prototype = {
|
Target.prototype = {
|
||||||
hasPlayedSound: false,
|
hasBecomeActive: false,
|
||||||
preload: function(entityID) {
|
preload: function(entityID) {
|
||||||
this.entityID = entityID;
|
this.entityID = entityID;
|
||||||
var SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/Clay_Pigeon_02.L.wav";
|
var SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/Clay_Pigeon_02.L.wav";
|
||||||
this.hitSound = SoundCache.getSound(SOUND_URL);
|
this.hitSound = SoundCache.getSound(SOUND_URL);
|
||||||
},
|
},
|
||||||
collisionWithEntity: function(me, otherEntity) {
|
collisionWithEntity: function(me, otherEntity) {
|
||||||
|
if (this.hasBecomeActive === false) {
|
||||||
var position = Entities.getEntityProperties(me, "position").position;
|
var position = Entities.getEntityProperties(me, "position").position;
|
||||||
Entities.editEntity(me, {
|
Entities.editEntity(me, {
|
||||||
gravity: {
|
gravity: {
|
||||||
|
@ -38,13 +39,12 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.hasPlayedSound === false) {
|
|
||||||
this.audioInjector = Audio.playSound(this.hitSound, {
|
this.audioInjector = Audio.playSound(this.hitSound, {
|
||||||
position: position,
|
position: position,
|
||||||
volume: 0.5
|
volume: 0.5
|
||||||
});
|
});
|
||||||
|
|
||||||
this.hasPlayedSound = true;
|
this.hasBecomeActive = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
{ "from": "Standard.DR", "to": "Actions.UiNavLateral" },
|
{ "from": "Standard.DR", "to": "Actions.UiNavLateral" },
|
||||||
{ "from": "Standard.LB", "to": "Actions.UiNavGroup","filters": "invert" },
|
{ "from": "Standard.LB", "to": "Actions.UiNavGroup","filters": "invert" },
|
||||||
{ "from": "Standard.RB", "to": "Actions.UiNavGroup" },
|
{ "from": "Standard.RB", "to": "Actions.UiNavGroup" },
|
||||||
{ "from": [ "Standard.A", "Standard.X", "Standard.RT", "Standard.LT" ], "to": "Actions.UiNavSelect" },
|
{ "from": [ "Standard.A", "Standard.X" ], "to": "Actions.UiNavSelect" },
|
||||||
{ "from": [ "Standard.B", "Standard.Y", "Standard.RightPrimaryThumb", "Standard.LeftPrimaryThumb" ], "to": "Actions.UiNavBack" },
|
{ "from": [ "Standard.B", "Standard.Y", "Standard.RightPrimaryThumb", "Standard.LeftPrimaryThumb" ], "to": "Actions.UiNavBack" },
|
||||||
{
|
{
|
||||||
"from": [ "Standard.RT", "Standard.LT" ],
|
"from": [ "Standard.RT", "Standard.LT" ],
|
||||||
|
|
|
@ -169,8 +169,10 @@ DialogContainer {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_Escape:
|
case Qt.Key_Escape:
|
||||||
case Qt.Key_Back:
|
case Qt.Key_Back:
|
||||||
|
if (enabled) {
|
||||||
enabled = false
|
enabled = false
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case Qt.Key_Enter:
|
case Qt.Key_Enter:
|
||||||
case Qt.Key_Return:
|
case Qt.Key_Return:
|
||||||
|
|
|
@ -96,6 +96,9 @@ DialogContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
|
if (!enabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_Escape:
|
case Qt.Key_Escape:
|
||||||
case Qt.Key_Back:
|
case Qt.Key_Back:
|
||||||
|
|
|
@ -343,8 +343,10 @@ DialogContainer {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_Escape:
|
case Qt.Key_Escape:
|
||||||
case Qt.Key_Back:
|
case Qt.Key_Back:
|
||||||
|
if (enabled) {
|
||||||
enabled = false
|
enabled = false
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case Qt.Key_Enter:
|
case Qt.Key_Enter:
|
||||||
case Qt.Key_Return:
|
case Qt.Key_Return:
|
||||||
|
|
|
@ -300,6 +300,10 @@ VrDialog {
|
||||||
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
|
if (!enabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (event.modifiers === Qt.ControlModifier)
|
if (event.modifiers === Qt.ControlModifier)
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_A:
|
case Qt.Key_A:
|
||||||
|
|
|
@ -10,7 +10,6 @@ import "styles"
|
||||||
|
|
||||||
VrDialog {
|
VrDialog {
|
||||||
id: root
|
id: root
|
||||||
objectName: "topLevelWindow"
|
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
title: "QmlWindow"
|
title: "QmlWindow"
|
||||||
resizable: true
|
resizable: true
|
||||||
|
@ -43,10 +42,6 @@ VrDialog {
|
||||||
focus: true
|
focus: true
|
||||||
property var dialog: root
|
property var dialog: root
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
forceActiveFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
console.log("QmlWindow pageLoader keypress")
|
console.log("QmlWindow pageLoader keypress")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
import Hifi 1.0
|
import Hifi 1.0
|
||||||
import QtQuick 2.3
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
// This is our primary 'window' object to which all dialogs and controls will
|
// This is our primary 'window' object to which all dialogs and controls will
|
||||||
// be childed.
|
// be childed.
|
||||||
Root {
|
Root {
|
||||||
id: root
|
id: root
|
||||||
|
objectName: "desktopRoot"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
property var rootMenu: Menu {
|
||||||
|
objectName: "rootMenu"
|
||||||
|
}
|
||||||
|
|
||||||
onParentChanged: {
|
onParentChanged: {
|
||||||
forceActiveFocus();
|
forceActiveFocus();
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import QtQuick 2.4
|
|
||||||
import QtQuick.Controls 1.3
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Menu {
|
|
||||||
id: root
|
|
||||||
objectName: "rootMenu"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@ import "../styles"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
objectName: "topLevelWindow"
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
implicitHeight: contentImplicitHeight + titleBorder.height + hifi.styles.borderWidth
|
implicitHeight: contentImplicitHeight + titleBorder.height + hifi.styles.borderWidth
|
||||||
implicitWidth: contentImplicitWidth + hifi.styles.borderWidth * 2
|
implicitWidth: contentImplicitWidth + hifi.styles.borderWidth * 2
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
#include <ObjectMotionState.h>
|
#include <ObjectMotionState.h>
|
||||||
#include <OctalCode.h>
|
#include <OctalCode.h>
|
||||||
#include <OctreeSceneStats.h>
|
#include <OctreeSceneStats.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
#include <gl/OffscreenGLCanvas.h>
|
#include <gl/OffscreenGLCanvas.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
@ -1177,7 +1178,6 @@ void Application::initializeUi() {
|
||||||
offscreenUi->setProxyWindow(_window->windowHandle());
|
offscreenUi->setProxyWindow(_window->windowHandle());
|
||||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||||
offscreenUi->load("Root.qml");
|
offscreenUi->load("Root.qml");
|
||||||
offscreenUi->load("RootMenu.qml");
|
|
||||||
// FIXME either expose so that dialogs can set this themselves or
|
// FIXME either expose so that dialogs can set this themselves or
|
||||||
// do better detection in the offscreen UI of what has focus
|
// do better detection in the offscreen UI of what has focus
|
||||||
offscreenUi->setNavigationFocused(false);
|
offscreenUi->setNavigationFocused(false);
|
||||||
|
@ -4381,7 +4381,7 @@ bool Application::askToSetAvatarUrl(const QString& url) {
|
||||||
bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
QMessageBox::StandardButton reply;
|
QMessageBox::StandardButton reply;
|
||||||
QString message = "Would you like to run this script:\n" + scriptFilenameOrURL;
|
QString message = "Would you like to run this script:\n" + scriptFilenameOrURL;
|
||||||
reply = QMessageBox::question(getWindow(), "Run Script", message, QMessageBox::Yes|QMessageBox::No);
|
reply = OffscreenUi::question(getWindow(), "Run Script", message, QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes) {
|
if (reply == QMessageBox::Yes) {
|
||||||
qCDebug(interfaceapp) << "Chose to run the script: " << scriptFilenameOrURL;
|
qCDebug(interfaceapp) << "Chose to run the script: " << scriptFilenameOrURL;
|
||||||
|
@ -4394,7 +4394,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
|
|
||||||
bool Application::askToUploadAsset(const QString& filename) {
|
bool Application::askToUploadAsset(const QString& filename) {
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRez()) {
|
if (!DependencyManager::get<NodeList>()->getThisNodeCanRez()) {
|
||||||
QMessageBox::warning(_window, "Failed Upload",
|
OffscreenUi::warning(_window, "Failed Upload",
|
||||||
QString("You don't have upload rights on that domain.\n\n"));
|
QString("You don't have upload rights on that domain.\n\n"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4438,7 +4438,7 @@ bool Application::askToUploadAsset(const QString& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// display a message box with the error
|
// display a message box with the error
|
||||||
QMessageBox::warning(_window, "Failed Upload", QString("Failed to upload %1.\n\n").arg(filename));
|
OffscreenUi::warning(_window, "Failed Upload", QString("Failed to upload %1.\n\n").arg(filename));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4629,7 +4629,7 @@ void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
|
||||||
// FIXME - change to new version of ScriptCache loading notification
|
// FIXME - change to new version of ScriptCache loading notification
|
||||||
void Application::handleScriptLoadError(const QString& scriptFilename) {
|
void Application::handleScriptLoadError(const QString& scriptFilename) {
|
||||||
qCDebug(interfaceapp) << "Application::loadScript(), script failed to load...";
|
qCDebug(interfaceapp) << "Application::loadScript(), script failed to load...";
|
||||||
QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");
|
OffscreenUi::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Application::getRunningScripts() {
|
QStringList Application::getRunningScripts() {
|
||||||
|
|
|
@ -16,22 +16,31 @@
|
||||||
|
|
||||||
#include "InterfaceParentFinder.h"
|
#include "InterfaceParentFinder.h"
|
||||||
|
|
||||||
SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID) const {
|
SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& success) const {
|
||||||
SpatiallyNestableWeakPointer parent;
|
SpatiallyNestableWeakPointer parent;
|
||||||
|
|
||||||
if (parentID.isNull()) {
|
if (parentID.isNull()) {
|
||||||
|
success = true;
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// search entities
|
// search entities
|
||||||
EntityTreeRenderer* treeRenderer = qApp->getEntities();
|
EntityTreeRenderer* treeRenderer = qApp->getEntities();
|
||||||
EntityTreePointer tree = treeRenderer->getTree();
|
EntityTreePointer tree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||||
parent = tree->findEntityByEntityItemID(parentID);
|
parent = tree ? tree->findEntityByEntityItemID(parentID) : nullptr;
|
||||||
if (!parent.expired()) {
|
if (!parent.expired()) {
|
||||||
|
success = true;
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// search avatars
|
// search avatars
|
||||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||||
return avatarManager->getAvatarBySessionID(parentID);
|
parent = avatarManager->getAvatarBySessionID(parentID);
|
||||||
|
if (!parent.expired()) {
|
||||||
|
success = true;
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = false;
|
||||||
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class InterfaceParentFinder : public SpatialParentFinder {
|
||||||
public:
|
public:
|
||||||
InterfaceParentFinder() { }
|
InterfaceParentFinder() { }
|
||||||
virtual ~InterfaceParentFinder() { }
|
virtual ~InterfaceParentFinder() { }
|
||||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const;
|
virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_InterfaceParentFinder_h
|
#endif // hifi_InterfaceParentFinder_h
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
#include <FSTReader.h>
|
#include <FSTReader.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
#include "ModelSelector.h"
|
#include "ModelSelector.h"
|
||||||
#include "ModelPropertiesDialog.h"
|
#include "ModelPropertiesDialog.h"
|
||||||
|
@ -78,7 +79,7 @@ bool ModelPackager::loadModel() {
|
||||||
if (_modelFile.completeSuffix().contains("fst")) {
|
if (_modelFile.completeSuffix().contains("fst")) {
|
||||||
QFile fst(_modelFile.filePath());
|
QFile fst(_modelFile.filePath());
|
||||||
if (!fst.open(QFile::ReadOnly | QFile::Text)) {
|
if (!fst.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
QMessageBox::warning(NULL,
|
OffscreenUi::warning(NULL,
|
||||||
QString("ModelPackager::loadModel()"),
|
QString("ModelPackager::loadModel()"),
|
||||||
QString("Could not open FST file %1").arg(_modelFile.filePath()),
|
QString("Could not open FST file %1").arg(_modelFile.filePath()),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
|
@ -97,7 +98,7 @@ bool ModelPackager::loadModel() {
|
||||||
// open the fbx file
|
// open the fbx file
|
||||||
QFile fbx(_fbxInfo.filePath());
|
QFile fbx(_fbxInfo.filePath());
|
||||||
if (!_fbxInfo.exists() || !_fbxInfo.isFile() || !fbx.open(QIODevice::ReadOnly)) {
|
if (!_fbxInfo.exists() || !_fbxInfo.isFile() || !fbx.open(QIODevice::ReadOnly)) {
|
||||||
QMessageBox::warning(NULL,
|
OffscreenUi::warning(NULL,
|
||||||
QString("ModelPackager::loadModel()"),
|
QString("ModelPackager::loadModel()"),
|
||||||
QString("Could not open FBX file %1").arg(_fbxInfo.filePath()),
|
QString("Could not open FBX file %1").arg(_fbxInfo.filePath()),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
|
@ -402,7 +403,7 @@ bool ModelPackager::copyTextures(const QString& oldDir, const QDir& newDir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
QMessageBox::warning(nullptr, "ModelPackager::copyTextures()",
|
OffscreenUi::warning(nullptr, "ModelPackager::copyTextures()",
|
||||||
"Missing textures:" + errors);
|
"Missing textures:" + errors);
|
||||||
qCDebug(interfaceapp) << "ModelPackager::copyTextures():" << errors;
|
qCDebug(interfaceapp) << "ModelPackager::copyTextures():" << errors;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <FSTReader.h>
|
#include <FSTReader.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
#include "ModelPropertiesDialog.h"
|
#include "ModelPropertiesDialog.h"
|
||||||
|
|
||||||
|
@ -200,7 +201,7 @@ void ModelPropertiesDialog::chooseTextureDirectory() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!directory.startsWith(_basePath)) {
|
if (!directory.startsWith(_basePath)) {
|
||||||
QMessageBox::warning(NULL, "Invalid texture directory", "Texture directory must be child of base path.");
|
OffscreenUi::warning(NULL, "Invalid texture directory", "Texture directory must be child of base path.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1));
|
_textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1));
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <AssetUpload.h>
|
#include <AssetUpload.h>
|
||||||
#include <ResourceManager.h>
|
#include <ResourceManager.h>
|
||||||
|
|
||||||
|
#include "OffscreenUi.h"
|
||||||
#include "../ui/AssetUploadDialogFactory.h"
|
#include "../ui/AssetUploadDialogFactory.h"
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(asset_migrator);
|
Q_DECLARE_LOGGING_CATEGORY(asset_migrator);
|
||||||
|
@ -52,7 +53,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
" continue?\n\nMake sure you are connected to the right domain."
|
" continue?\n\nMake sure you are connected to the right domain."
|
||||||
};
|
};
|
||||||
|
|
||||||
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE, MIGRATION_CONFIRMATION_TEXT,
|
auto button = OffscreenUi::question(_dialogParent, MESSAGE_BOX_TITLE, MIGRATION_CONFIRMATION_TEXT,
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
|
|
||||||
if (button == QMessageBox::No) {
|
if (button == QMessageBox::No) {
|
||||||
|
@ -67,7 +68,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
QByteArray jsonData;
|
QByteArray jsonData;
|
||||||
|
|
||||||
if (!gunzip(compressedJsonData, jsonData)) {
|
if (!gunzip(compressedJsonData, jsonData)) {
|
||||||
QMessageBox::warning(_dialogParent, "Error", "The file at" + filename + "was not in gzip format.");
|
OffscreenUi::warning(_dialogParent, "Error", "The file at" + filename + "was not in gzip format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument modelsJSON = QJsonDocument::fromJson(jsonData);
|
QJsonDocument modelsJSON = QJsonDocument::fromJson(jsonData);
|
||||||
|
@ -107,7 +108,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
if (request->getResult() == ResourceRequest::Success) {
|
if (request->getResult() == ResourceRequest::Success) {
|
||||||
migrateResource(request);
|
migrateResource(request);
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(_dialogParent, "Error",
|
OffscreenUi::warning(_dialogParent, "Error",
|
||||||
QString("Could not retrieve asset at %1").arg(modelURL.toString()));
|
QString("Could not retrieve asset at %1").arg(modelURL.toString()));
|
||||||
}
|
}
|
||||||
request->deleteLater();
|
request->deleteLater();
|
||||||
|
@ -115,7 +116,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
|
|
||||||
request->send();
|
request->send();
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(_dialogParent, "Error",
|
OffscreenUi::warning(_dialogParent, "Error",
|
||||||
QString("Could not create request for asset at %1").arg(modelURL.toString()));
|
QString("Could not create request for asset at %1").arg(modelURL.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
_doneReading = true;
|
_doneReading = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(_dialogParent, "Error",
|
OffscreenUi::warning(_dialogParent, "Error",
|
||||||
"There was a problem loading that entity-server file for ATP asset migration. Please try again");
|
"There was a problem loading that entity-server file for ATP asset migration. Please try again");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +213,7 @@ bool ATPAssetMigrator::wantsToMigrateResource(const QUrl& url) {
|
||||||
"Select \"No\" to be prompted for each discovered asset."
|
"Select \"No\" to be prompted for each discovered asset."
|
||||||
};
|
};
|
||||||
|
|
||||||
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE, COMPLETE_MIGRATION_TEXT,
|
auto button = OffscreenUi::question(_dialogParent, MESSAGE_BOX_TITLE, COMPLETE_MIGRATION_TEXT,
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
|
|
||||||
if (button == QMessageBox::Yes) {
|
if (button == QMessageBox::Yes) {
|
||||||
|
@ -226,7 +227,7 @@ bool ATPAssetMigrator::wantsToMigrateResource(const QUrl& url) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// present a dialog asking the user if they want to migrate this specific resource
|
// present a dialog asking the user if they want to migrate this specific resource
|
||||||
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE,
|
auto button = OffscreenUi::question(_dialogParent, MESSAGE_BOX_TITLE,
|
||||||
"Would you like to migrate the following resource?\n" + url.toString(),
|
"Would you like to migrate the following resource?\n" + url.toString(),
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
return button == QMessageBox::Yes;
|
return button == QMessageBox::Yes;
|
||||||
|
@ -254,11 +255,11 @@ void ATPAssetMigrator::saveEntityServerFile() {
|
||||||
QMessageBox::information(_dialogParent, "Success",
|
QMessageBox::information(_dialogParent, "Success",
|
||||||
QString("Your new entities file has been saved at %1").arg(saveName));
|
QString("Your new entities file has been saved at %1").arg(saveName));
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(_dialogParent, "Error", "Could not gzip JSON data for new entities file.");
|
OffscreenUi::warning(_dialogParent, "Error", "Could not gzip JSON data for new entities file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(_dialogParent, "Error",
|
OffscreenUi::warning(_dialogParent, "Error",
|
||||||
QString("Could not open file at %1 to write new entities file to.").arg(saveName));
|
QString("Could not open file at %1 to write new entities file to.").arg(saveName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,7 @@ void Avatar::simulate(float deltaTime) {
|
||||||
measureMotionDerivatives(deltaTime);
|
measureMotionDerivatives(deltaTime);
|
||||||
|
|
||||||
simulateAttachments(deltaTime);
|
simulateAttachments(deltaTime);
|
||||||
|
updatePalms();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
|
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
|
||||||
|
@ -1021,6 +1022,9 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
if (_moving && _motionState) {
|
if (_moving && _motionState) {
|
||||||
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
||||||
}
|
}
|
||||||
|
if (_moving || _hasNewJointRotations || _hasNewJointTranslations) {
|
||||||
|
locationChanged();
|
||||||
|
}
|
||||||
endUpdate();
|
endUpdate();
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
@ -1152,34 +1156,24 @@ void Avatar::rebuildCollisionShape() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread-safe
|
||||||
glm::vec3 Avatar::getLeftPalmPosition() {
|
glm::vec3 Avatar::getLeftPalmPosition() {
|
||||||
glm::vec3 leftHandPosition;
|
return _leftPalmPositionCache.get();
|
||||||
getSkeletonModel().getLeftHandPosition(leftHandPosition);
|
|
||||||
glm::quat leftRotation;
|
|
||||||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation);
|
|
||||||
leftHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftRotation);
|
|
||||||
return leftHandPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread-safe
|
||||||
glm::quat Avatar::getLeftPalmRotation() {
|
glm::quat Avatar::getLeftPalmRotation() {
|
||||||
glm::quat leftRotation;
|
return _leftPalmRotationCache.get();
|
||||||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation);
|
|
||||||
return leftRotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread-safe
|
||||||
glm::vec3 Avatar::getRightPalmPosition() {
|
glm::vec3 Avatar::getRightPalmPosition() {
|
||||||
glm::vec3 rightHandPosition;
|
return _rightPalmPositionCache.get();
|
||||||
getSkeletonModel().getRightHandPosition(rightHandPosition);
|
|
||||||
glm::quat rightRotation;
|
|
||||||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
|
|
||||||
rightHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightRotation);
|
|
||||||
return rightHandPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// thread-safe
|
||||||
glm::quat Avatar::getRightPalmRotation() {
|
glm::quat Avatar::getRightPalmRotation() {
|
||||||
glm::quat rightRotation;
|
return _rightPalmRotationCache.get();
|
||||||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
|
|
||||||
return rightRotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setPosition(const glm::vec3& position) {
|
void Avatar::setPosition(const glm::vec3& position) {
|
||||||
|
@ -1191,3 +1185,24 @@ void Avatar::setOrientation(const glm::quat& orientation) {
|
||||||
AvatarData::setOrientation(orientation);
|
AvatarData::setOrientation(orientation);
|
||||||
updateAttitude();
|
updateAttitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::updatePalms() {
|
||||||
|
|
||||||
|
// get palm rotations
|
||||||
|
glm::quat leftPalmRotation, rightPalmRotation;
|
||||||
|
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftPalmRotation);
|
||||||
|
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightPalmRotation);
|
||||||
|
|
||||||
|
// get palm positions
|
||||||
|
glm::vec3 leftPalmPosition, rightPalmPosition;
|
||||||
|
getSkeletonModel().getLeftHandPosition(leftPalmPosition);
|
||||||
|
getSkeletonModel().getRightHandPosition(rightPalmPosition);
|
||||||
|
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
|
||||||
|
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
|
||||||
|
|
||||||
|
// update thread-safe caches
|
||||||
|
_leftPalmRotationCache.set(leftPalmRotation);
|
||||||
|
_rightPalmRotationCache.set(rightPalmRotation);
|
||||||
|
_leftPalmPositionCache.set(leftPalmPosition);
|
||||||
|
_rightPalmPositionCache.set(rightPalmPosition);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "SkeletonModel.h"
|
#include "SkeletonModel.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "Rig.h"
|
#include "Rig.h"
|
||||||
|
#include <ThreadSafeValueCache.h>
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
|
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
|
||||||
|
@ -159,7 +160,9 @@ public:
|
||||||
|
|
||||||
AvatarMotionState* getMotionState() { return _motionState; }
|
AvatarMotionState* getMotionState() { return _motionState; }
|
||||||
|
|
||||||
|
using SpatiallyNestable::setPosition;
|
||||||
virtual void setPosition(const glm::vec3& position) override;
|
virtual void setPosition(const glm::vec3& position) override;
|
||||||
|
using SpatiallyNestable::setOrientation;
|
||||||
virtual void setOrientation(const glm::quat& orientation) override;
|
virtual void setOrientation(const glm::quat& orientation) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -225,8 +228,15 @@ protected:
|
||||||
|
|
||||||
virtual void updateJointMappings() override;
|
virtual void updateJointMappings() override;
|
||||||
|
|
||||||
|
virtual void updatePalms();
|
||||||
|
|
||||||
render::ItemID _renderItemID;
|
render::ItemID _renderItemID;
|
||||||
|
|
||||||
|
ThreadSafeValueCache<glm::vec3> _leftPalmPositionCache { glm::vec3() };
|
||||||
|
ThreadSafeValueCache<glm::quat> _leftPalmRotationCache { glm::quat() };
|
||||||
|
ThreadSafeValueCache<glm::vec3> _rightPalmPositionCache { glm::vec3() };
|
||||||
|
ThreadSafeValueCache<glm::quat> _rightPalmRotationCache { glm::quat() };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
NetworkTexturePointer _billboardTexture;
|
NetworkTexturePointer _billboardTexture;
|
||||||
|
|
|
@ -89,6 +89,8 @@ void AvatarActionHold::prepareForPhysicsSimulation() {
|
||||||
// code here for future reference.
|
// code here for future reference.
|
||||||
// _palmRotationFromRigidBody = avatarRotationInverse * palmRotation;
|
// _palmRotationFromRigidBody = avatarRotationInverse * palmRotation;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
activateBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) {
|
std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) {
|
||||||
|
@ -197,7 +199,6 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
||||||
if (_kinematic) {
|
if (_kinematic) {
|
||||||
doKinematicUpdate(deltaTimeStep);
|
doKinematicUpdate(deltaTimeStep);
|
||||||
} else {
|
} else {
|
||||||
activateBody();
|
|
||||||
forceBodyNonStatic();
|
forceBodyNonStatic();
|
||||||
ObjectActionSpring::updateActionWorker(deltaTimeStep);
|
ObjectActionSpring::updateActionWorker(deltaTimeStep);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +248,6 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
|
||||||
_previousSet = true;
|
_previousSet = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
activateBody();
|
|
||||||
forceBodyNonStatic();
|
forceBodyNonStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +344,6 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
||||||
ownerEntity->setActionDataNeedsTransmit(true);
|
ownerEntity->setActionDataNeedsTransmit(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
activateBody();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -431,6 +430,5 @@ void AvatarActionHold::deserialize(QByteArray serializedArguments) {
|
||||||
_active = true;
|
_active = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
activateBody();
|
|
||||||
forceBodyNonStatic();
|
forceBodyNonStatic();
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,6 +417,8 @@ void MyAvatar::updateSensorToWorldMatrix() {
|
||||||
// position when driven from the head.
|
// position when driven from the head.
|
||||||
glm::mat4 desiredMat = createMatFromQuatAndPos(getOrientation(), getPosition());
|
glm::mat4 desiredMat = createMatFromQuatAndPos(getOrientation(), getPosition());
|
||||||
_sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix);
|
_sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix);
|
||||||
|
|
||||||
|
lateUpdatePalms();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update avatar head rotation with sensor data
|
// Update avatar head rotation with sensor data
|
||||||
|
@ -1839,3 +1841,8 @@ QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioList
|
||||||
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) {
|
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) {
|
||||||
audioListenerMode = (AudioListenerMode)object.toUInt16();
|
audioListenerMode = (AudioListenerMode)object.toUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MyAvatar::lateUpdatePalms() {
|
||||||
|
Avatar::updatePalms();
|
||||||
|
}
|
||||||
|
|
|
@ -311,12 +311,14 @@ private:
|
||||||
|
|
||||||
void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity);
|
void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity);
|
||||||
|
|
||||||
PalmData getActivePalmData(int palmIndex) const;
|
|
||||||
|
|
||||||
// derive avatar body position and orientation from the current HMD Sensor location.
|
// derive avatar body position and orientation from the current HMD Sensor location.
|
||||||
// results are in HMD frame
|
// results are in HMD frame
|
||||||
glm::mat4 deriveBodyFromHMDSensor() const;
|
glm::mat4 deriveBodyFromHMDSensor() const;
|
||||||
|
|
||||||
|
virtual void updatePalms() override {}
|
||||||
|
void lateUpdatePalms();
|
||||||
|
|
||||||
|
|
||||||
float _driveKeys[MAX_DRIVE_KEYS];
|
float _driveKeys[MAX_DRIVE_KEYS];
|
||||||
bool _wasPushing;
|
bool _wasPushing;
|
||||||
bool _isPushing;
|
bool _isPushing;
|
||||||
|
|
|
@ -139,7 +139,7 @@ void EyeTracker::onStreamStarted() {
|
||||||
qCWarning(interfaceapp) << "Eye Tracker: Error starting streaming:" << smiReturnValueToString(result);
|
qCWarning(interfaceapp) << "Eye Tracker: Error starting streaming:" << smiReturnValueToString(result);
|
||||||
// Display error dialog unless SMI SDK has already displayed an error message.
|
// Display error dialog unless SMI SDK has already displayed an error message.
|
||||||
if (result != SMI_ERROR_HMD_NOT_SUPPORTED) {
|
if (result != SMI_ERROR_HMD_NOT_SUPPORTED) {
|
||||||
QMessageBox::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result));
|
OffscreenUi::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "Eye Tracker: Started streaming";
|
qCDebug(interfaceapp) << "Eye Tracker: Started streaming";
|
||||||
|
@ -152,7 +152,7 @@ void EyeTracker::onStreamStarted() {
|
||||||
result = smi_loadCalibration(HIGH_FIDELITY_EYE_TRACKER_CALIBRATION);
|
result = smi_loadCalibration(HIGH_FIDELITY_EYE_TRACKER_CALIBRATION);
|
||||||
if (result != SMI_RET_SUCCESS) {
|
if (result != SMI_RET_SUCCESS) {
|
||||||
qCWarning(interfaceapp) << "Eye Tracker: Error loading calibration:" << smiReturnValueToString(result);
|
qCWarning(interfaceapp) << "Eye Tracker: Error loading calibration:" << smiReturnValueToString(result);
|
||||||
QMessageBox::warning(nullptr, "Eye Tracker Error", "Error loading calibration"
|
OffscreenUi::warning(nullptr, "Eye Tracker Error", "Error loading calibration"
|
||||||
+ smiReturnValueToString(result));
|
+ smiReturnValueToString(result));
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "Eye Tracker: Loaded calibration";
|
qCDebug(interfaceapp) << "Eye Tracker: Loaded calibration";
|
||||||
|
@ -168,7 +168,7 @@ void EyeTracker::setEnabled(bool enabled, bool simulate) {
|
||||||
int result = smi_setCallback(eyeTrackerCallback);
|
int result = smi_setCallback(eyeTrackerCallback);
|
||||||
if (result != SMI_RET_SUCCESS) {
|
if (result != SMI_RET_SUCCESS) {
|
||||||
qCWarning(interfaceapp) << "Eye Tracker: Error setting callback:" << smiReturnValueToString(result);
|
qCWarning(interfaceapp) << "Eye Tracker: Error setting callback:" << smiReturnValueToString(result);
|
||||||
QMessageBox::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result));
|
OffscreenUi::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result));
|
||||||
} else {
|
} else {
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,7 @@ void EyeTracker::calibrate(int points) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != SMI_RET_SUCCESS) {
|
if (result != SMI_RET_SUCCESS) {
|
||||||
QMessageBox::warning(nullptr, "Eye Tracker Error", "Calibration error: " + smiReturnValueToString(result));
|
OffscreenUi::warning(nullptr, "Eye Tracker Error", "Calibration error: " + smiReturnValueToString(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "DomainHandler.h"
|
#include "DomainHandler.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
#include "OffscreenUi.h"
|
||||||
#include "ui/ModelsBrowser.h"
|
#include "ui/ModelsBrowser.h"
|
||||||
|
|
||||||
#include "WindowScriptingInterface.h"
|
#include "WindowScriptingInterface.h"
|
||||||
|
@ -153,12 +154,11 @@ QScriptValue WindowScriptingInterface::peekNonBlockingFormResult(QScriptValue fo
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Display an alert box
|
/// Display an alert box
|
||||||
/// \param const QString& message message to display
|
/// \param const QString& message message to display
|
||||||
/// \return QScriptValue::UndefinedValue
|
/// \return QScriptValue::UndefinedValue
|
||||||
QScriptValue WindowScriptingInterface::showAlert(const QString& message) {
|
QScriptValue WindowScriptingInterface::showAlert(const QString& message) {
|
||||||
QMessageBox::warning(qApp->getWindow(), "", message);
|
OffscreenUi::warning("", message);
|
||||||
return QScriptValue::UndefinedValue;
|
return QScriptValue::UndefinedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +166,11 @@ QScriptValue WindowScriptingInterface::showAlert(const QString& message) {
|
||||||
/// \param const QString& message message to display
|
/// \param const QString& message message to display
|
||||||
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
|
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
|
||||||
QScriptValue WindowScriptingInterface::showConfirm(const QString& message) {
|
QScriptValue WindowScriptingInterface::showConfirm(const QString& message) {
|
||||||
QMessageBox::StandardButton response = QMessageBox::question(qApp->getWindow(), "", message);
|
bool confirm = false;
|
||||||
return QScriptValue(response == QMessageBox::Yes);
|
OffscreenUi::question("", message, [&](QMessageBox::StandardButton response){
|
||||||
|
confirm = (response == QMessageBox::Yes);
|
||||||
|
});
|
||||||
|
return QScriptValue(confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowScriptingInterface::chooseDirectory() {
|
void WindowScriptingInterface::chooseDirectory() {
|
||||||
|
@ -185,7 +188,7 @@ void WindowScriptingInterface::chooseDirectory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validateAs.exactMatch(directory)) {
|
if (!validateAs.exactMatch(directory)) {
|
||||||
QMessageBox::warning(NULL, "Invalid Directory", errorMessage);
|
OffscreenUi::warning(NULL, "Invalid Directory", errorMessage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +600,6 @@ QScriptValue WindowScriptingInterface::showPrompt(const QString& message, const
|
||||||
if (promptDialog.exec() == QDialog::Accepted) {
|
if (promptDialog.exec() == QDialog::Accepted) {
|
||||||
return QScriptValue(promptDialog.textValue());
|
return QScriptValue(promptDialog.textValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
return QScriptValue::NullValue;
|
return QScriptValue::NullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <AssetUpload.h>
|
#include <AssetUpload.h>
|
||||||
#include <AssetUtils.h>
|
#include <AssetUtils.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
#include <ResourceManager.h>
|
#include <ResourceManager.h>
|
||||||
|
|
||||||
AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
||||||
|
@ -146,5 +147,5 @@ void AssetUploadDialogFactory::showErrorDialog(AssetUpload* upload, QWidget* dia
|
||||||
|
|
||||||
dialogMessage += errorMessage;
|
dialogMessage += errorMessage;
|
||||||
|
|
||||||
QMessageBox::warning(dialogParent, "Failed Upload", dialogMessage);
|
OffscreenUi::warning(dialogParent, "Failed Upload", dialogMessage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
|
|
||||||
#include "DiskCacheEditor.h"
|
#include "DiskCacheEditor.h"
|
||||||
|
#include "OffscreenUi.h"
|
||||||
|
|
||||||
DiskCacheEditor::DiskCacheEditor(QWidget* parent) : QObject(parent) {
|
DiskCacheEditor::DiskCacheEditor(QWidget* parent) : QObject(parent) {
|
||||||
|
|
||||||
|
@ -136,7 +137,7 @@ void DiskCacheEditor::refresh() {
|
||||||
|
|
||||||
void DiskCacheEditor::clear() {
|
void DiskCacheEditor::clear() {
|
||||||
QMessageBox::StandardButton buttonClicked =
|
QMessageBox::StandardButton buttonClicked =
|
||||||
QMessageBox::question(_dialog, "Clearing disk cache",
|
OffscreenUi::question(_dialog, "Clearing disk cache",
|
||||||
"You are about to erase all the content of the disk cache,"
|
"You are about to erase all the content of the disk cache,"
|
||||||
"are you sure you want to do that?");
|
"are you sure you want to do that?");
|
||||||
if (buttonClicked == QMessageBox::Yes) {
|
if (buttonClicked == QMessageBox::Yes) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "ScriptHighlighting.h"
|
#include "ScriptHighlighting.h"
|
||||||
|
@ -120,7 +121,7 @@ bool ScriptEditorWidget::setRunning(bool run) {
|
||||||
bool ScriptEditorWidget::saveFile(const QString &scriptPath) {
|
bool ScriptEditorWidget::saveFile(const QString &scriptPath) {
|
||||||
QFile file(scriptPath);
|
QFile file(scriptPath);
|
||||||
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
||||||
QMessageBox::warning(this, tr("Interface"), tr("Cannot write script %1:\n%2.").arg(scriptPath)
|
OffscreenUi::warning(this, tr("Interface"), tr("Cannot write script %1:\n%2.").arg(scriptPath)
|
||||||
.arg(file.errorString()));
|
.arg(file.errorString()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) {
|
||||||
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
||||||
QFile file(scriptPath);
|
QFile file(scriptPath);
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
QMessageBox::warning(this, tr("Interface"), tr("Cannot read script %1:\n%2.").arg(scriptPath)
|
OffscreenUi::warning(this, tr("Interface"), tr("Cannot read script %1:\n%2.").arg(scriptPath)
|
||||||
.arg(file.errorString()));
|
.arg(file.errorString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +209,7 @@ void ScriptEditorWidget::setScriptFile(const QString& scriptPath) {
|
||||||
|
|
||||||
bool ScriptEditorWidget::questionSave() {
|
bool ScriptEditorWidget::questionSave() {
|
||||||
if (_scriptEditorWidgetUI->scriptEdit->document()->isModified()) {
|
if (_scriptEditorWidgetUI->scriptEdit->document()->isModified()) {
|
||||||
QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Interface"),
|
QMessageBox::StandardButton button = OffscreenUi::warning(this, tr("Interface"),
|
||||||
tr("The script has been modified.\nDo you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard |
|
tr("The script has been modified.\nDo you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard |
|
||||||
QMessageBox::Cancel, QMessageBox::Save);
|
QMessageBox::Cancel, QMessageBox::Save);
|
||||||
return button == QMessageBox::Save ? save() : (button == QMessageBox::Discard);
|
return button == QMessageBox::Save ? save() : (button == QMessageBox::Discard);
|
||||||
|
@ -222,7 +223,7 @@ void ScriptEditorWidget::onWindowActivated() {
|
||||||
|
|
||||||
if (QFileInfo(_currentScript).lastModified() > _currentScriptModified) {
|
if (QFileInfo(_currentScript).lastModified() > _currentScriptModified) {
|
||||||
if (static_cast<ScriptEditorWindow*>(this->parent()->parent()->parent())->autoReloadScripts()
|
if (static_cast<ScriptEditorWindow*>(this->parent()->parent()->parent())->autoReloadScripts()
|
||||||
|| QMessageBox::warning(this, _currentScript,
|
|| OffscreenUi::warning(this, _currentScript,
|
||||||
tr("This file has been modified outside of the Interface editor.") + "\n\n"
|
tr("This file has been modified outside of the Interface editor.") + "\n\n"
|
||||||
+ (isModified()
|
+ (isModified()
|
||||||
? tr("Do you want to reload it and lose the changes you've made in the Interface editor?")
|
? tr("Do you want to reload it and lose the changes you've made in the Interface editor?")
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
const int NARROW_SNAPSHOT_DIALOG_SIZE = 500;
|
const int NARROW_SNAPSHOT_DIALOG_SIZE = 500;
|
||||||
const int WIDE_SNAPSHOT_DIALOG_WIDTH = 650;
|
const int WIDE_SNAPSHOT_DIALOG_WIDTH = 650;
|
||||||
|
@ -87,7 +88,7 @@ void SnapshotShareDialog::accept() {
|
||||||
void SnapshotShareDialog::uploadSnapshot() {
|
void SnapshotShareDialog::uploadSnapshot() {
|
||||||
|
|
||||||
if (AccountManager::getInstance().getAccountInfo().getDiscourseApiKey().isEmpty()) {
|
if (AccountManager::getInstance().getAccountInfo().getDiscourseApiKey().isEmpty()) {
|
||||||
QMessageBox::warning(this, "",
|
OffscreenUi::warning(this, "",
|
||||||
"Your Discourse API key is missing, you cannot share snapshots. Please try to relog.");
|
"Your Discourse API key is missing, you cannot share snapshots. Please try to relog.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +179,7 @@ void SnapshotShareDialog::postRequestFinished() {
|
||||||
errorMessage = errorArray.first().toString();
|
errorMessage = errorArray.first().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QMessageBox::warning(this, "", errorMessage);
|
OffscreenUi::warning(this, "", errorMessage);
|
||||||
_ui.shareButton->setEnabled(true);
|
_ui.shareButton->setEnabled(true);
|
||||||
_ui.shareButton->setStyleSheet(SHARE_BUTTON_STYLE + SHARE_BUTTON_ENABLED_STYLE);
|
_ui.shareButton->setStyleSheet(SHARE_BUTTON_STYLE + SHARE_BUTTON_ENABLED_STYLE);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +194,7 @@ void SnapshotShareDialog::uploadRequestFinished() {
|
||||||
if (responseObject.contains("url")) {
|
if (responseObject.contains("url")) {
|
||||||
sendForumPost(responseObject["url"].toString());
|
sendForumPost(responseObject["url"].toString());
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, "", SHARE_DEFAULT_ERROR);
|
OffscreenUi::warning(this, "", SHARE_DEFAULT_ERROR);
|
||||||
_ui.shareButton->setEnabled(true);
|
_ui.shareButton->setEnabled(true);
|
||||||
_ui.shareButton->setStyleSheet(SHARE_BUTTON_STYLE + SHARE_BUTTON_ENABLED_STYLE);
|
_ui.shareButton->setStyleSheet(SHARE_BUTTON_STYLE + SHARE_BUTTON_ENABLED_STYLE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,10 +90,18 @@ const QUrl& AvatarData::defaultFullAvatarModelUrl() {
|
||||||
// There are a number of possible strategies for this set of tools through endRender, below.
|
// There are a number of possible strategies for this set of tools through endRender, below.
|
||||||
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
||||||
avatarLock.lock();
|
avatarLock.lock();
|
||||||
Transform trans = getTransform();
|
bool success;
|
||||||
|
Transform trans = getTransform(success);
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- AvatarData::nextAttitude failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
trans.setTranslation(position);
|
trans.setTranslation(position);
|
||||||
trans.setRotation(orientation);
|
trans.setRotation(orientation);
|
||||||
SpatiallyNestable::setTransform(trans);
|
SpatiallyNestable::setTransform(trans, success);
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- AvatarData::nextAttitude failed";
|
||||||
|
}
|
||||||
avatarLock.unlock();
|
avatarLock.unlock();
|
||||||
updateAttitude();
|
updateAttitude();
|
||||||
}
|
}
|
||||||
|
@ -208,8 +216,9 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||||
setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
|
setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
|
||||||
}
|
}
|
||||||
// referential state
|
// referential state
|
||||||
SpatiallyNestablePointer parent = getParentPointer();
|
bool success;
|
||||||
if (parent) {
|
SpatiallyNestablePointer parent = getParentPointer(success);
|
||||||
|
if (parent && success) {
|
||||||
setAtBit(bitItems, HAS_REFERENTIAL);
|
setAtBit(bitItems, HAS_REFERENTIAL);
|
||||||
}
|
}
|
||||||
*destinationBuffer++ = bitItems;
|
*destinationBuffer++ = bitItems;
|
||||||
|
@ -1446,7 +1455,11 @@ QJsonObject AvatarData::toJson() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto recordingBasis = getRecordingBasis();
|
auto recordingBasis = getRecordingBasis();
|
||||||
Transform avatarTransform = getTransform();
|
bool success;
|
||||||
|
Transform avatarTransform = getTransform(success);
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform";
|
||||||
|
}
|
||||||
avatarTransform.setScale(getTargetScale());
|
avatarTransform.setScale(getTargetScale());
|
||||||
if (recordingBasis) {
|
if (recordingBasis) {
|
||||||
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);
|
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);
|
||||||
|
@ -1635,3 +1648,13 @@ void AvatarData::setPosition(const glm::vec3& position) {
|
||||||
void AvatarData::setOrientation(const glm::quat& orientation) {
|
void AvatarData::setOrientation(const glm::quat& orientation) {
|
||||||
SpatiallyNestable::setOrientation(orientation);
|
SpatiallyNestable::setOrientation(orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat AvatarData::getAbsoluteJointRotationInObjectFrame(int index) const {
|
||||||
|
assert(false);
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
||||||
|
assert(false);
|
||||||
|
return glm::vec3();
|
||||||
|
}
|
||||||
|
|
|
@ -201,7 +201,9 @@ public:
|
||||||
float getBodyRoll() const;
|
float getBodyRoll() const;
|
||||||
void setBodyRoll(float bodyRoll);
|
void setBodyRoll(float bodyRoll);
|
||||||
|
|
||||||
|
using SpatiallyNestable::setPosition;
|
||||||
virtual void setPosition(const glm::vec3& position) override;
|
virtual void setPosition(const glm::vec3& position) override;
|
||||||
|
using SpatiallyNestable::setOrientation;
|
||||||
virtual void setOrientation(const glm::quat& orientation) override;
|
virtual void setOrientation(const glm::quat& orientation) override;
|
||||||
|
|
||||||
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
||||||
|
@ -354,6 +356,9 @@ public slots:
|
||||||
void setJointMappingsFromNetworkReply();
|
void setJointMappingsFromNetworkReply();
|
||||||
void setSessionUUID(const QUuid& sessionUUID) { setID(sessionUUID); }
|
void setSessionUUID(const QUuid& sessionUUID) { setID(sessionUUID); }
|
||||||
|
|
||||||
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||||
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
glm::vec3 _handPosition;
|
glm::vec3 _handPosition;
|
||||||
|
|
||||||
|
|
|
@ -767,7 +767,12 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
||||||
|
|
||||||
// Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2)
|
// Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2)
|
||||||
const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f;
|
const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f;
|
||||||
const float stretchFactor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2);
|
bool success;
|
||||||
|
auto minAACube = entity->getMinimumAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const float stretchFactor = log(1.0f + (minAACube.getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2);
|
||||||
AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position);
|
AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,14 +56,20 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
|
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
auto transToCenter = getTransformToCenter(success);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_procedural->ready()) {
|
if (_procedural->ready()) {
|
||||||
batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well
|
batch.setModelTransform(transToCenter); // we want to include the scale as well
|
||||||
_procedural->prepare(batch, getPosition(), getDimensions());
|
_procedural->prepare(batch, getPosition(), getDimensions());
|
||||||
auto color = _procedural->getColor(cubeColor);
|
auto color = _procedural->getColor(cubeColor);
|
||||||
batch._glColor4f(color.r, color.g, color.b, color.a);
|
batch._glColor4f(color.r, color.g, color.b, color.a);
|
||||||
DependencyManager::get<GeometryCache>()->renderCube(batch);
|
DependencyManager::get<GeometryCache>()->renderCube(batch);
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, transToCenter, cubeColor);
|
||||||
}
|
}
|
||||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
|
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
|
||||||
args->_details._trianglesRendered += (int)triCount;
|
args->_details._trianglesRendered += (int)triCount;
|
||||||
|
|
|
@ -28,7 +28,12 @@ namespace render {
|
||||||
|
|
||||||
template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) {
|
template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) {
|
||||||
if (payload && payload->entity) {
|
if (payload && payload->entity) {
|
||||||
return payload->entity->getAABox();
|
bool success;
|
||||||
|
auto result = payload->entity->getAABox(success);
|
||||||
|
if (!success) {
|
||||||
|
return render::Item::Bound();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return render::Item::Bound();
|
return render::Item::Bound();
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,12 @@ namespace render {
|
||||||
|
|
||||||
template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) {
|
template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) {
|
||||||
if (payload && payload->entity) {
|
if (payload && payload->entity) {
|
||||||
return payload->entity->getAABox();
|
bool success;
|
||||||
|
auto result = payload->entity->getAABox(success);
|
||||||
|
if (!success) {
|
||||||
|
return render::Item::Bound();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return render::Item::Bound();
|
return render::Item::Bound();
|
||||||
}
|
}
|
||||||
|
@ -338,11 +343,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
} else {
|
} else {
|
||||||
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
auto shapeTransform = getTransformToCenter();
|
bool success;
|
||||||
|
auto shapeTransform = getTransformToCenter(success);
|
||||||
|
if (success) {
|
||||||
batch.setModelTransform(Transform()); // we want to include the scale as well
|
batch.setModelTransform(Transform()); // we want to include the scale as well
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
Model* result = NULL;
|
Model* result = NULL;
|
||||||
|
|
|
@ -236,9 +236,14 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
|
||||||
particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed));
|
particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bounds = getAABox();
|
bool successb, successp, successr;
|
||||||
auto position = getPosition();
|
auto bounds = getAABox(successb);
|
||||||
auto rotation = getRotation();
|
auto position = getPosition(successp);
|
||||||
|
auto rotation = getOrientation(successr);
|
||||||
|
bool success = successb && successp && successr;
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Transform transform;
|
Transform transform;
|
||||||
if (!getEmitterShouldTrail()) {
|
if (!getEmitterShouldTrail()) {
|
||||||
transform.setTranslation(position);
|
transform.setTranslation(position);
|
||||||
|
|
|
@ -142,9 +142,11 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
|
||||||
|
|
||||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
||||||
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
||||||
glm::vec3 center = getCenterPosition();
|
bool success; // TODO -- Does this actually have to happen in world space?
|
||||||
glm::vec3 position = getPosition();
|
glm::vec3 center = getCenterPosition(success);
|
||||||
|
glm::vec3 position = getPosition(success);
|
||||||
glm::vec3 positionToCenter = center - position;
|
glm::vec3 positionToCenter = center - position;
|
||||||
|
|
||||||
positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment();
|
positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment();
|
||||||
glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter);
|
glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter);
|
||||||
glm::mat4 scaled = glm::scale(centerToCorner, scale);
|
glm::mat4 scaled = glm::scale(centerToCorner, scale);
|
||||||
|
@ -581,7 +583,12 @@ namespace render {
|
||||||
template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload) {
|
template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload) {
|
||||||
if (payload && payload->_owner) {
|
if (payload && payload->_owner) {
|
||||||
auto polyVoxEntity = std::dynamic_pointer_cast<RenderablePolyVoxEntityItem>(payload->_owner);
|
auto polyVoxEntity = std::dynamic_pointer_cast<RenderablePolyVoxEntityItem>(payload->_owner);
|
||||||
return polyVoxEntity->getAABox();
|
bool success;
|
||||||
|
auto result = polyVoxEntity->getAABox(success);
|
||||||
|
if (!success) {
|
||||||
|
return render::Item::Bound();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return render::Item::Bound();
|
return render::Item::Bound();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,11 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
|
||||||
|
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha());
|
glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||||
Transform modelTransform = getTransformToCenter();
|
bool success;
|
||||||
|
Transform modelTransform = getTransformToCenter(success);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||||
if (_procedural->ready()) {
|
if (_procedural->ready()) {
|
||||||
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
|
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
|
||||||
|
|
|
@ -45,7 +45,11 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
|
||||||
Transform transformToTopLeft = getTransformToCenter();
|
bool success;
|
||||||
|
Transform transformToTopLeft = getTransformToCenter(success);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getFaceCamera()) {
|
if (getFaceCamera()) {
|
||||||
//rotate about vertical to face the camera
|
//rotate about vertical to face the camera
|
||||||
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
|
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
|
||||||
|
|
|
@ -185,7 +185,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
||||||
|
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
batch.setModelTransform(getTransformToCenter());
|
bool success;
|
||||||
|
batch.setModelTransform(getTransformToCenter(success));
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool textured = false, culled = false, emissive = false;
|
bool textured = false, culled = false, emissive = false;
|
||||||
if (_texture) {
|
if (_texture) {
|
||||||
batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);
|
batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);
|
||||||
|
|
|
@ -135,7 +135,11 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
|
|
||||||
auto shapeTransform = getTransformToCenter();
|
bool success;
|
||||||
|
auto shapeTransform = getTransformToCenter(success);
|
||||||
|
if (!success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||||
if (getShapeType() == SHAPE_TYPE_SPHERE) {
|
if (getShapeType() == SHAPE_TYPE_SPHERE) {
|
||||||
shapeTransform.postScale(SPHERE_ENTITY_SCALE);
|
shapeTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||||
|
@ -190,7 +194,12 @@ namespace render {
|
||||||
|
|
||||||
template <> const Item::Bound payloadGetBound(const RenderableZoneEntityItemMeta::Pointer& payload) {
|
template <> const Item::Bound payloadGetBound(const RenderableZoneEntityItemMeta::Pointer& payload) {
|
||||||
if (payload && payload->entity) {
|
if (payload && payload->entity) {
|
||||||
return payload->entity->getAABox();
|
bool success;
|
||||||
|
auto result = payload->entity->getAABox(success);
|
||||||
|
if (!success) {
|
||||||
|
return render::Item::Bound();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return render::Item::Bound();
|
return render::Item::Bound();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,13 @@ AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer n
|
||||||
// caller must have verified existence of newEntity
|
// caller must have verified existence of newEntity
|
||||||
assert(_newEntity);
|
assert(_newEntity);
|
||||||
|
|
||||||
_newEntityBox = _newEntity->getMaximumAACube().clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE);
|
bool success;
|
||||||
|
auto queryCube = _newEntity->getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
_newEntity->markAncestorMissing(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_newEntityBox = queryCube.clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddEntityOperator::preRecursion(OctreeElementPointer element) {
|
bool AddEntityOperator::preRecursion(OctreeElementPointer element) {
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
//
|
|
||||||
// BoundingBoxRelatedProperties.cpp
|
|
||||||
// libraries/entities/src
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2015-9-24
|
|
||||||
// Copyright 2013 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 "EntityItemProperties.h"
|
|
||||||
#include "BoundingBoxRelatedProperties.h"
|
|
||||||
#include "EntityTree.h"
|
|
||||||
|
|
||||||
BoundingBoxRelatedProperties::BoundingBoxRelatedProperties(EntityItemPointer entity) :
|
|
||||||
position(entity->getPosition()),
|
|
||||||
rotation(entity->getRotation()),
|
|
||||||
registrationPoint(entity->getRegistrationPoint()),
|
|
||||||
dimensions(entity->getDimensions()),
|
|
||||||
parentID(entity->getParentID()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundingBoxRelatedProperties::BoundingBoxRelatedProperties(EntityItemPointer entity,
|
|
||||||
const EntityItemProperties& propertiesWithUpdates) :
|
|
||||||
BoundingBoxRelatedProperties(entity) {
|
|
||||||
|
|
||||||
if (propertiesWithUpdates.parentIDChanged()) {
|
|
||||||
parentID = propertiesWithUpdates.getParentID();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parentFound = false;
|
|
||||||
if (parentID != UNKNOWN_ENTITY_ID) {
|
|
||||||
EntityTreePointer tree = entity->getTree();
|
|
||||||
EntityItemPointer parentZone = tree->findEntityByID(parentID);
|
|
||||||
if (parentZone) {
|
|
||||||
parentFound = true;
|
|
||||||
glm::vec3 localPosition = propertiesWithUpdates.containsPositionChange() ?
|
|
||||||
propertiesWithUpdates.getPosition() :
|
|
||||||
entity->getLocalPosition();
|
|
||||||
|
|
||||||
glm::quat localRotation = propertiesWithUpdates.rotationChanged() ?
|
|
||||||
propertiesWithUpdates.getRotation() :
|
|
||||||
entity->getLocalOrientation();
|
|
||||||
|
|
||||||
const Transform parentTransform = parentZone->getTransformToCenter();
|
|
||||||
Transform parentDescaled(parentTransform.getRotation(), glm::vec3(1.0f), parentTransform.getTranslation());
|
|
||||||
|
|
||||||
Transform localTransform(localRotation, glm::vec3(1.0f), localPosition);
|
|
||||||
Transform result;
|
|
||||||
Transform::mult(result, parentDescaled, localTransform);
|
|
||||||
position = result.getTranslation();
|
|
||||||
rotation = result.getRotation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parentFound) {
|
|
||||||
if (propertiesWithUpdates.containsPositionChange()) {
|
|
||||||
position = propertiesWithUpdates.getPosition();
|
|
||||||
}
|
|
||||||
if (propertiesWithUpdates.rotationChanged()) {
|
|
||||||
rotation = propertiesWithUpdates.getRotation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertiesWithUpdates.registrationPointChanged()) {
|
|
||||||
registrationPoint = propertiesWithUpdates.getRegistrationPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertiesWithUpdates.dimensionsChanged()) {
|
|
||||||
dimensions = propertiesWithUpdates.getDimensions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AACube BoundingBoxRelatedProperties::getMaximumAACube() const {
|
|
||||||
// see EntityItem::getMaximumAACube for comments which explain the following.
|
|
||||||
glm::vec3 scaledRegistrationPoint = (dimensions * registrationPoint);
|
|
||||||
glm::vec3 registrationRemainder = (dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - registrationPoint));
|
|
||||||
glm::vec3 furthestExtentFromRegistration = glm::max(scaledRegistrationPoint, registrationRemainder);
|
|
||||||
float radius = glm::length(furthestExtentFromRegistration);
|
|
||||||
glm::vec3 minimumCorner = position - glm::vec3(radius, radius, radius);
|
|
||||||
return AACube(minimumCorner, radius * 2.0f);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
//
|
|
||||||
// BoundingBoxRelatedProperties.h
|
|
||||||
// libraries/entities/src
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2015-9-24
|
|
||||||
// Copyright 2013 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 "EntityItem.h"
|
|
||||||
|
|
||||||
#ifndef hifi_BoundingBoxRelatedProperties_h
|
|
||||||
#define hifi_BoundingBoxRelatedProperties_h
|
|
||||||
|
|
||||||
class BoundingBoxRelatedProperties {
|
|
||||||
public:
|
|
||||||
BoundingBoxRelatedProperties(EntityItemPointer entity);
|
|
||||||
BoundingBoxRelatedProperties(EntityItemPointer entity, const EntityItemProperties& propertiesWithUpdates);
|
|
||||||
AACube getMaximumAACube() const;
|
|
||||||
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::quat rotation;
|
|
||||||
glm::vec3 registrationPoint;
|
|
||||||
glm::vec3 dimensions;
|
|
||||||
EntityItemID parentID;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_BoundingBoxRelatedProperties_h
|
|
|
@ -133,6 +133,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
||||||
requestedProperties += PROP_ACTION_DATA;
|
requestedProperties += PROP_ACTION_DATA;
|
||||||
requestedProperties += PROP_PARENT_ID;
|
requestedProperties += PROP_PARENT_ID;
|
||||||
requestedProperties += PROP_PARENT_JOINT_INDEX;
|
requestedProperties += PROP_PARENT_JOINT_INDEX;
|
||||||
|
requestedProperties += PROP_QUERY_AA_CUBE;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +270,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getActionData());
|
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getActionData());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, getParentID());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, getParentID());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
|
||||||
|
|
||||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||||
requestedProperties,
|
requestedProperties,
|
||||||
|
@ -693,6 +695,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||||
|
|
||||||
|
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
||||||
|
|
||||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||||
propertyFlags, overwriteLocalData, somethingChanged);
|
propertyFlags, overwriteLocalData, somethingChanged);
|
||||||
|
|
||||||
|
@ -1047,6 +1051,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
||||||
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube);
|
||||||
|
|
||||||
properties._defaultSettings = false;
|
properties._defaultSettings = false;
|
||||||
|
|
||||||
|
@ -1111,6 +1116,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setActionData);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setActionData);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||||
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
||||||
|
|
||||||
if (somethingChanged) {
|
if (somethingChanged) {
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
|
@ -1152,8 +1158,8 @@ void EntityItem::recordCreationTime() {
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Transform EntityItem::getTransformToCenter() const {
|
const Transform EntityItem::getTransformToCenter(bool& success) const {
|
||||||
Transform result = getTransform();
|
Transform result = getTransform(success);
|
||||||
if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center
|
if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center
|
||||||
result.postTranslate(ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()); // Position to center
|
result.postTranslate(ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()); // Position to center
|
||||||
}
|
}
|
||||||
|
@ -1171,11 +1177,11 @@ void EntityItem::setDimensions(const glm::vec3& value) {
|
||||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||||
/// This accounts for the registration point (upon which rotation occurs around).
|
/// This accounts for the registration point (upon which rotation occurs around).
|
||||||
///
|
///
|
||||||
const AACube& EntityItem::getMaximumAACube() const {
|
AACube EntityItem::getMaximumAACube(bool& success) const {
|
||||||
if (_recalcMaxAACube) {
|
if (_recalcMaxAACube) {
|
||||||
// * we know that the position is the center of rotation
|
// * we know that the position is the center of rotation
|
||||||
glm::vec3 centerOfRotation = getPosition(); // also where _registration point is
|
glm::vec3 centerOfRotation = getPosition(success); // also where _registration point is
|
||||||
|
if (success) {
|
||||||
// * we know that the registration point is the center of rotation
|
// * we know that the registration point is the center of rotation
|
||||||
// * we can calculate the length of the furthest extent from the registration point
|
// * we can calculate the length of the furthest extent from the registration point
|
||||||
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint)
|
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint)
|
||||||
|
@ -1194,13 +1200,16 @@ const AACube& EntityItem::getMaximumAACube() const {
|
||||||
_maxAACube = AACube(minimumCorner, radius * 2.0f);
|
_maxAACube = AACube(minimumCorner, radius * 2.0f);
|
||||||
_recalcMaxAACube = false;
|
_recalcMaxAACube = false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
return _maxAACube;
|
return _maxAACube;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The minimum bounding cube for the entity accounting for it's rotation.
|
/// The minimum bounding cube for the entity accounting for it's rotation.
|
||||||
/// This accounts for the registration point (upon which rotation occurs around).
|
/// This accounts for the registration point (upon which rotation occurs around).
|
||||||
///
|
///
|
||||||
const AACube& EntityItem::getMinimumAACube() const {
|
AACube EntityItem::getMinimumAACube(bool& success) const {
|
||||||
if (_recalcMinAACube) {
|
if (_recalcMinAACube) {
|
||||||
// _position represents the position of the registration point.
|
// _position represents the position of the registration point.
|
||||||
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
||||||
|
@ -1208,11 +1217,13 @@ const AACube& EntityItem::getMinimumAACube() const {
|
||||||
glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * getRegistrationPoint());
|
glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * getRegistrationPoint());
|
||||||
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
|
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
|
||||||
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
||||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
Extents rotatedExtentsRelativeToRegistrationPoint =
|
||||||
|
unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
||||||
|
|
||||||
// shift the extents to be relative to the position/registration point
|
// shift the extents to be relative to the position/registration point
|
||||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition());
|
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition(success));
|
||||||
|
|
||||||
|
if (success) {
|
||||||
// the cube that best encompasses extents is...
|
// the cube that best encompasses extents is...
|
||||||
AABox box(rotatedExtentsRelativeToRegistrationPoint);
|
AABox box(rotatedExtentsRelativeToRegistrationPoint);
|
||||||
glm::vec3 centerOfBox = box.calcCenter();
|
glm::vec3 centerOfBox = box.calcCenter();
|
||||||
|
@ -1223,10 +1234,13 @@ const AACube& EntityItem::getMinimumAACube() const {
|
||||||
_minAACube = AACube(cornerOfCube, longestSide);
|
_minAACube = AACube(cornerOfCube, longestSide);
|
||||||
_recalcMinAACube = false;
|
_recalcMinAACube = false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
return _minAACube;
|
return _minAACube;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AABox& EntityItem::getAABox() const {
|
AABox EntityItem::getAABox(bool& success) const {
|
||||||
if (_recalcAABox) {
|
if (_recalcAABox) {
|
||||||
// _position represents the position of the registration point.
|
// _position represents the position of the registration point.
|
||||||
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
||||||
|
@ -1234,17 +1248,37 @@ const AABox& EntityItem::getAABox() const {
|
||||||
glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * _registrationPoint);
|
glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * _registrationPoint);
|
||||||
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
|
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
|
||||||
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
||||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
Extents rotatedExtentsRelativeToRegistrationPoint =
|
||||||
|
unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
||||||
|
|
||||||
// shift the extents to be relative to the position/registration point
|
// shift the extents to be relative to the position/registration point
|
||||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition());
|
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition(success));
|
||||||
|
|
||||||
|
if (success) {
|
||||||
_cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint);
|
_cachedAABox = AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||||
_recalcAABox = false;
|
_recalcAABox = false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
return _cachedAABox;
|
return _cachedAABox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AACube EntityItem::getQueryAACube(bool& success) const {
|
||||||
|
AACube result = SpatiallyNestable::getQueryAACube(success);
|
||||||
|
if (success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// this is for when we've loaded an older json file that didn't have queryAACube properties.
|
||||||
|
result = getMaximumAACube(success);
|
||||||
|
if (success) {
|
||||||
|
_queryAACube = result;
|
||||||
|
_queryAACubeSet = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: This should only be used in cases of old bitstreams which only contain radius data
|
// NOTE: This should only be used in cases of old bitstreams which only contain radius data
|
||||||
// 0,0,0 --> maxDimension,maxDimension,maxDimension
|
// 0,0,0 --> maxDimension,maxDimension,maxDimension
|
||||||
// ... has a corner to corner distance of glm::length(maxDimension,maxDimension,maxDimension)
|
// ... has a corner to corner distance of glm::length(maxDimension,maxDimension,maxDimension)
|
||||||
|
@ -1274,7 +1308,9 @@ float EntityItem::getRadius() const {
|
||||||
|
|
||||||
bool EntityItem::contains(const glm::vec3& point) const {
|
bool EntityItem::contains(const glm::vec3& point) const {
|
||||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||||
return getAABox().contains(point);
|
bool success;
|
||||||
|
bool result = getAABox(success).contains(point);
|
||||||
|
return result && success;
|
||||||
} else {
|
} else {
|
||||||
ShapeInfo info;
|
ShapeInfo info;
|
||||||
info.setParams(getShapeType(), glm::vec3(0.5f));
|
info.setParams(getShapeType(), glm::vec3(0.5f));
|
||||||
|
@ -1817,6 +1853,14 @@ QList<EntityActionPointer> EntityItem::getActionsOfType(EntityActionType typeToG
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat EntityItem::getAbsoluteJointRotationInObjectFrame(int index) const {
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityItem::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
void EntityItem::locationChanged() {
|
void EntityItem::locationChanged() {
|
||||||
requiresRecalcBoxes();
|
requiresRecalcBoxes();
|
||||||
SpatiallyNestable::locationChanged(); // tell all the children, also
|
SpatiallyNestable::locationChanged(); // tell all the children, also
|
||||||
|
|
|
@ -161,11 +161,10 @@ public:
|
||||||
// attributes applicable to all entity types
|
// attributes applicable to all entity types
|
||||||
EntityTypes::EntityType getType() const { return _type; }
|
EntityTypes::EntityType getType() const { return _type; }
|
||||||
|
|
||||||
inline glm::vec3 getCenterPosition() const { return getTransformToCenter().getTranslation(); }
|
inline glm::vec3 getCenterPosition(bool& success) const { return getTransformToCenter(success).getTranslation(); }
|
||||||
void setCenterPosition(const glm::vec3& position);
|
void setCenterPosition(const glm::vec3& position);
|
||||||
|
|
||||||
const Transform getTransformToCenter() const;
|
const Transform getTransformToCenter(bool& success) const;
|
||||||
void setTranformToCenter(const Transform& transform);
|
|
||||||
|
|
||||||
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
|
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
|
||||||
|
|
||||||
|
@ -232,9 +231,12 @@ public:
|
||||||
quint64 getExpiry() const;
|
quint64 getExpiry() const;
|
||||||
|
|
||||||
// position, size, and bounds related helpers
|
// position, size, and bounds related helpers
|
||||||
const AACube& getMaximumAACube() const;
|
virtual AACube getMaximumAACube(bool& success) const override;
|
||||||
const AACube& getMinimumAACube() const;
|
AACube getMinimumAACube(bool& success) const;
|
||||||
const AABox& getAABox() const; /// axis aligned bounding box in world-frame (meters)
|
AABox getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters)
|
||||||
|
|
||||||
|
using SpatiallyNestable::getQueryAACube;
|
||||||
|
virtual AACube getQueryAACube(bool& success) const override;
|
||||||
|
|
||||||
const QString& getScript() const { return _script; }
|
const QString& getScript() const { return _script; }
|
||||||
void setScript(const QString& value) { _script = value; }
|
void setScript(const QString& value) { _script = value; }
|
||||||
|
@ -379,8 +381,8 @@ public:
|
||||||
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet);
|
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet);
|
||||||
|
|
||||||
// these are in the frame of this object
|
// these are in the frame of this object
|
||||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); }
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||||
|
|
||||||
virtual void loader() {} // called indirectly when urls for geometry are updated
|
virtual void loader() {} // called indirectly when urls for geometry are updated
|
||||||
|
|
||||||
|
|
|
@ -262,6 +262,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||||
CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
|
CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID);
|
CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
||||||
|
CHECK_PROPERTY_CHANGE(PROP_QUERY_AA_CUBE, queryAACube);
|
||||||
|
|
||||||
changedProperties += _animation.getChangedProperties();
|
changedProperties += _animation.getChangedProperties();
|
||||||
changedProperties += _keyLight.getChangedProperties();
|
changedProperties += _keyLight.getChangedProperties();
|
||||||
|
@ -473,10 +474,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
||||||
|
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_ID, parentID);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_ID, parentID);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
||||||
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_QUERY_AA_CUBE, queryAACube);
|
||||||
|
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation);
|
||||||
|
|
||||||
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_QUERY_AA_CUBE, queryAACube);
|
||||||
|
|
||||||
// FIXME - I don't think these properties are supported any more
|
// FIXME - I don't think these properties are supported any more
|
||||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
//COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
||||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
||||||
|
@ -601,6 +605,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
|
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
|
||||||
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(queryAACube, AACube, setQueryAACube);
|
||||||
|
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, glmVec3, setLocalPosition);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, glmVec3, setLocalPosition);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation);
|
||||||
|
@ -922,6 +927,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
||||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
|
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, properties.getQueryAACube());
|
||||||
|
|
||||||
if (properties.getType() == EntityTypes::Web) {
|
if (properties.getType() == EntityTypes::Web) {
|
||||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
||||||
|
@ -1208,6 +1214,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||||
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
||||||
|
|
||||||
if (properties.getType() == EntityTypes::Web) {
|
if (properties.getType() == EntityTypes::Web) {
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||||
|
@ -1460,32 +1467,8 @@ void EntityItemProperties::markAllChanged() {
|
||||||
|
|
||||||
_parentIDChanged = true;
|
_parentIDChanged = true;
|
||||||
_parentJointIndexChanged = true;
|
_parentJointIndexChanged = true;
|
||||||
}
|
|
||||||
|
|
||||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
_queryAACubeChanged = true;
|
||||||
/// This accounts for the registration point (upon which rotation occurs around).
|
|
||||||
///
|
|
||||||
AACube EntityItemProperties::getMaximumAACube() const {
|
|
||||||
// * we know that the position is the center of rotation
|
|
||||||
glm::vec3 centerOfRotation = _position; // also where _registration point is
|
|
||||||
|
|
||||||
// * we know that the registration point is the center of rotation
|
|
||||||
// * we can calculate the length of the furthest extent from the registration point
|
|
||||||
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint)
|
|
||||||
glm::vec3 registrationPoint = (_dimensions * _registrationPoint);
|
|
||||||
glm::vec3 registrationRemainder = (_dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint));
|
|
||||||
glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder);
|
|
||||||
|
|
||||||
// * we know that if you rotate in any direction you would create a sphere
|
|
||||||
// that has a radius of the length of furthest extent from registration point
|
|
||||||
float radius = glm::length(furthestExtentFromRegistration);
|
|
||||||
|
|
||||||
// * we know that the minimum bounding cube of this maximum possible sphere is
|
|
||||||
// (center - radius) to (center + radius)
|
|
||||||
glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius);
|
|
||||||
float diameter = radius * 2.0f;
|
|
||||||
|
|
||||||
return AACube(minimumCorner, diameter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The minimum bounding box for the entity.
|
// The minimum bounding box for the entity.
|
||||||
|
@ -1785,6 +1768,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
||||||
if (parentJointIndexChanged()) {
|
if (parentJointIndexChanged()) {
|
||||||
out += "parentJointIndex";
|
out += "parentJointIndex";
|
||||||
}
|
}
|
||||||
|
if (queryAACubeChanged()) {
|
||||||
|
out += "queryAACube";
|
||||||
|
}
|
||||||
|
|
||||||
getAnimation().listChangedProperties(out);
|
getAnimation().listChangedProperties(out);
|
||||||
getKeyLight().listChangedProperties(out);
|
getKeyLight().listChangedProperties(out);
|
||||||
|
@ -1798,3 +1784,7 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
||||||
bool EntityItemProperties::parentDependentPropertyChanged() const {
|
bool EntityItemProperties::parentDependentPropertyChanged() const {
|
||||||
return localPositionChanged() || positionChanged() || localRotationChanged() || rotationChanged();
|
return localPositionChanged() || positionChanged() || localRotationChanged() || rotationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityItemProperties::parentRelatedPropertyChanged() const {
|
||||||
|
return parentDependentPropertyChanged() || parentIDChanged() || parentJointIndexChanged();
|
||||||
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ public:
|
||||||
EntityPropertyFlags getChangedProperties() const;
|
EntityPropertyFlags getChangedProperties() const;
|
||||||
|
|
||||||
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret?
|
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret?
|
||||||
|
bool parentRelatedPropertyChanged() const; // parentDependentPropertyChanged or parentID or parentJointIndex
|
||||||
|
|
||||||
AACube getMaximumAACube() const;
|
|
||||||
AABox getAABox() const;
|
AABox getAABox() const;
|
||||||
|
|
||||||
void debugDump() const;
|
void debugDump() const;
|
||||||
|
@ -192,7 +192,8 @@ public:
|
||||||
DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||||
DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||||
DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
|
DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
|
||||||
DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, 0);
|
DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, -1);
|
||||||
|
DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube());
|
||||||
|
|
||||||
// these are used when bouncing location data into and out of scripts
|
// these are used when bouncing location data into and out of scripts
|
||||||
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||||
|
@ -397,6 +398,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||||
|
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentID, parentID, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentID, parentID, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentJointIndex, parentJointIndex, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentJointIndex, parentJointIndex, "");
|
||||||
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, QueryAACube, queryAACube, "");
|
||||||
|
|
||||||
properties.getAnimation().debugDump();
|
properties.getAnimation().debugDump();
|
||||||
properties.getAtmosphere().debugDump();
|
properties.getAtmosphere().debugDump();
|
||||||
|
|
|
@ -122,6 +122,9 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
|
||||||
|
|
||||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) { return QScriptValue(QUuid(v).toString()); }
|
inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) { return QScriptValue(QUuid(v).toString()); }
|
||||||
|
|
||||||
|
inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { return aaCubeToScriptValue(e, v); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(X,G,g,P,p) \
|
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(X,G,g,P,p) \
|
||||||
if ((desiredProperties.isEmpty() || desiredProperties.getHasProperty(X)) && \
|
if ((desiredProperties.isEmpty() || desiredProperties.getHasProperty(X)) && \
|
||||||
|
@ -225,6 +228,13 @@ inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isVal
|
||||||
return glm::vec3(0);
|
return glm::vec3(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline AACube AACube_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||||
|
isValid = true;
|
||||||
|
AACube result;
|
||||||
|
aaCubeFromScriptValue(v, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline qVectorFloat qVectorFloat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
inline qVectorFloat qVectorFloat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
return qVectorFloatFromScriptValue(v);
|
return qVectorFloatFromScriptValue(v);
|
||||||
|
|
|
@ -157,6 +157,8 @@ enum EntityPropertyList {
|
||||||
PROP_LOCAL_POSITION, // only used to convert values to and from scripts
|
PROP_LOCAL_POSITION, // only used to convert values to and from scripts
|
||||||
PROP_LOCAL_ROTATION, // only used to convert values to and from scripts
|
PROP_LOCAL_ROTATION, // only used to convert values to and from scripts
|
||||||
|
|
||||||
|
PROP_QUERY_AA_CUBE, // how the EntityTree considers the size and position on an entity
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||||
PROP_AFTER_LAST_ITEM,
|
PROP_AFTER_LAST_ITEM,
|
||||||
|
|
|
@ -72,12 +72,15 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties
|
||||||
scriptSideProperties.setLocalPosition(entitySideProperties.getPosition());
|
scriptSideProperties.setLocalPosition(entitySideProperties.getPosition());
|
||||||
scriptSideProperties.setLocalRotation(entitySideProperties.getRotation());
|
scriptSideProperties.setLocalRotation(entitySideProperties.getRotation());
|
||||||
|
|
||||||
|
bool success;
|
||||||
glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(),
|
glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(),
|
||||||
entitySideProperties.getParentID(),
|
entitySideProperties.getParentID(),
|
||||||
entitySideProperties.getParentJointIndex());
|
entitySideProperties.getParentJointIndex(),
|
||||||
|
success);
|
||||||
glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(),
|
glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(),
|
||||||
entitySideProperties.getParentID(),
|
entitySideProperties.getParentID(),
|
||||||
entitySideProperties.getParentJointIndex());
|
entitySideProperties.getParentJointIndex(),
|
||||||
|
success);
|
||||||
scriptSideProperties.setPosition(worldPosition);
|
scriptSideProperties.setPosition(worldPosition);
|
||||||
scriptSideProperties.setRotation(worldRotation);
|
scriptSideProperties.setRotation(worldRotation);
|
||||||
|
|
||||||
|
@ -89,13 +92,15 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti
|
||||||
// convert position and rotation properties from world-space to local, unless localPosition and localRotation
|
// convert position and rotation properties from world-space to local, unless localPosition and localRotation
|
||||||
// are set. If they are set, they overwrite position and rotation.
|
// are set. If they are set, they overwrite position and rotation.
|
||||||
EntityItemProperties entitySideProperties = scriptSideProperties;
|
EntityItemProperties entitySideProperties = scriptSideProperties;
|
||||||
|
bool success;
|
||||||
|
|
||||||
if (scriptSideProperties.localPositionChanged()) {
|
if (scriptSideProperties.localPositionChanged()) {
|
||||||
entitySideProperties.setPosition(scriptSideProperties.getLocalPosition());
|
entitySideProperties.setPosition(scriptSideProperties.getLocalPosition());
|
||||||
} else if (scriptSideProperties.positionChanged()) {
|
} else if (scriptSideProperties.positionChanged()) {
|
||||||
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(),
|
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(),
|
||||||
entitySideProperties.getParentID(),
|
entitySideProperties.getParentID(),
|
||||||
entitySideProperties.getParentJointIndex());
|
entitySideProperties.getParentJointIndex(),
|
||||||
|
success);
|
||||||
entitySideProperties.setPosition(localPosition);
|
entitySideProperties.setPosition(localPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +109,8 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti
|
||||||
} else if (scriptSideProperties.rotationChanged()) {
|
} else if (scriptSideProperties.rotationChanged()) {
|
||||||
glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(),
|
glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(),
|
||||||
entitySideProperties.getParentID(),
|
entitySideProperties.getParentID(),
|
||||||
entitySideProperties.getParentJointIndex());
|
entitySideProperties.getParentJointIndex(),
|
||||||
|
success);
|
||||||
entitySideProperties.setRotation(localRotation);
|
entitySideProperties.setRotation(localRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +134,10 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY);
|
propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY);
|
||||||
|
if (propertiesWithSimID.parentRelatedPropertyChanged()) {
|
||||||
|
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||||
|
propertiesWithSimID.setQueryAACube(entity->getQueryAACube());
|
||||||
|
}
|
||||||
|
|
||||||
// and make note of it now, so we can act on it right away.
|
// and make note of it now, so we can act on it right away.
|
||||||
entity->setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY);
|
entity->setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY);
|
||||||
|
@ -193,16 +203,15 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
|
||||||
QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) {
|
QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) {
|
||||||
EntityItemProperties properties = scriptSideProperties;
|
EntityItemProperties properties = scriptSideProperties;
|
||||||
EntityItemID entityID(id);
|
EntityItemID entityID(id);
|
||||||
// If we have a local entity tree set, then also update it.
|
|
||||||
if (!_entityTree) {
|
if (!_entityTree) {
|
||||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
// If we have a local entity tree set, then also update it.
|
||||||
|
|
||||||
bool updatedEntity = false;
|
bool updatedEntity = false;
|
||||||
_entityTree->withWriteLock([&] {
|
_entityTree->withWriteLock([&] {
|
||||||
if (scriptSideProperties.parentDependentPropertyChanged() ||
|
if (scriptSideProperties.parentRelatedPropertyChanged()) {
|
||||||
scriptSideProperties.parentIDChanged() || scriptSideProperties.parentJointIndexChanged()) {
|
|
||||||
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
|
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
|
||||||
// If any of these changed, pull any missing properties from the entity.
|
// If any of these changed, pull any missing properties from the entity.
|
||||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||||
|
@ -265,7 +274,24 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
||||||
entity->flagForOwnership();
|
entity->flagForOwnership();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (properties.parentRelatedPropertyChanged() && entity->computePuffedQueryAACube()) {
|
||||||
|
properties.setQueryAACube(entity->getQueryAACube());
|
||||||
|
}
|
||||||
entity->setLastBroadcast(usecTimestampNow());
|
entity->setLastBroadcast(usecTimestampNow());
|
||||||
|
|
||||||
|
// if we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
|
||||||
|
// if they've changed.
|
||||||
|
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||||
|
if (descendant->getNestableType() == NestableType::Entity) {
|
||||||
|
if (descendant->computePuffedQueryAACube()) {
|
||||||
|
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||||
|
EntityItemProperties newQueryCubeProperties;
|
||||||
|
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||||
|
queueEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties);
|
||||||
|
entityDescendant->setLastBroadcast(usecTimestampNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||||
|
|
|
@ -119,8 +119,9 @@ void EntitySimulation::sortEntitiesThatMoved() {
|
||||||
while (itemItr != _entitiesToSort.end()) {
|
while (itemItr != _entitiesToSort.end()) {
|
||||||
EntityItemPointer entity = *itemItr;
|
EntityItemPointer entity = *itemItr;
|
||||||
// check to see if this movement has sent the entity outside of the domain.
|
// check to see if this movement has sent the entity outside of the domain.
|
||||||
AACube newCube = entity->getMaximumAACube();
|
bool success;
|
||||||
if (!domainBounds.touches(newCube)) {
|
AACube newCube = entity->getQueryAACube(success);
|
||||||
|
if (success && !domainBounds.touches(newCube)) {
|
||||||
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
||||||
_entitiesToDelete.insert(entity);
|
_entitiesToDelete.insert(entity);
|
||||||
_mortalEntities.remove(entity);
|
_mortalEntities.remove(entity);
|
||||||
|
@ -200,8 +201,9 @@ void EntitySimulation::changeEntity(EntityItemPointer entity) {
|
||||||
uint32_t dirtyFlags = entity->getDirtyFlags();
|
uint32_t dirtyFlags = entity->getDirtyFlags();
|
||||||
if (dirtyFlags & Simulation::DIRTY_POSITION) {
|
if (dirtyFlags & Simulation::DIRTY_POSITION) {
|
||||||
AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE);
|
AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE);
|
||||||
AACube newCube = entity->getMaximumAACube();
|
bool success;
|
||||||
if (!domainBounds.touches(newCube)) {
|
AACube newCube = entity->getQueryAACube(success);
|
||||||
|
if (success && !domainBounds.touches(newCube)) {
|
||||||
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds.";
|
||||||
_entitiesToDelete.insert(entity);
|
_entitiesToDelete.insert(entity);
|
||||||
_mortalEntities.remove(entity);
|
_mortalEntities.remove(entity);
|
||||||
|
|
|
@ -89,6 +89,9 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
maybeNotifyNewCollisionSoundURL("", entity->getCollisionSoundURL());
|
maybeNotifyNewCollisionSoundURL("", entity->getCollisionSoundURL());
|
||||||
emit addingEntity(entity->getEntityItemID());
|
emit addingEntity(entity->getEntityItemID());
|
||||||
|
|
||||||
|
// find and hook up any entities with this entity as a (previously) missing parent
|
||||||
|
fixupMissingParents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
||||||
|
@ -142,8 +145,12 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
EntityItemProperties tempProperties;
|
EntityItemProperties tempProperties;
|
||||||
tempProperties.setLocked(wantsLocked);
|
tempProperties.setLocked(wantsLocked);
|
||||||
|
|
||||||
BoundingBoxRelatedProperties newBBRelProperties(entity, tempProperties);
|
bool success;
|
||||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties);
|
AACube queryCube = entity->getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
qCDebug(entities) << "Warning -- failed to get query-cube for" << entity->getID();
|
||||||
|
}
|
||||||
|
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
entity->setProperties(tempProperties);
|
entity->setProperties(tempProperties);
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
@ -211,8 +218,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
|
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
|
||||||
uint32_t preFlags = entity->getDirtyFlags();
|
uint32_t preFlags = entity->getDirtyFlags();
|
||||||
|
|
||||||
BoundingBoxRelatedProperties newBBRelProperties(entity, properties);
|
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, properties.getQueryAACube());
|
||||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties);
|
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
entity->setProperties(properties);
|
entity->setProperties(properties);
|
||||||
|
|
||||||
|
@ -229,14 +235,19 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
if (!childEntity) {
|
if (!childEntity) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BoundingBoxRelatedProperties newChildBBRelProperties(childEntity);
|
|
||||||
EntityTreeElementPointer containingElement = childEntity->getElement();
|
EntityTreeElementPointer containingElement = childEntity->getElement();
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
UpdateEntityOperator theChildOperator(getThisPointer(),
|
|
||||||
containingElement,
|
bool success;
|
||||||
childEntity, newChildBBRelProperties);
|
AACube queryCube = childEntity->getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
_missingParent.append(childEntity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateEntityOperator theChildOperator(getThisPointer(), containingElement, childEntity, queryCube);
|
||||||
recurseTreeWithOperator(&theChildOperator);
|
recurseTreeWithOperator(&theChildOperator);
|
||||||
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
|
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
|
||||||
if (childChild && childChild->getNestableType() == NestableType::Entity) {
|
if (childChild && childChild->getNestableType() == NestableType::Entity) {
|
||||||
|
@ -316,6 +327,11 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
||||||
// Recurse the tree and store the entity in the correct tree element
|
// Recurse the tree and store the entity in the correct tree element
|
||||||
AddEntityOperator theOperator(getThisPointer(), result);
|
AddEntityOperator theOperator(getThisPointer(), result);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
if (result->getAncestorMissing()) {
|
||||||
|
// we added the entity, but didn't know about all its ancestors, so it went into the wrong place.
|
||||||
|
// add it to a list of entities needing to be fixed once their parents are known.
|
||||||
|
_missingParent.append(result);
|
||||||
|
}
|
||||||
|
|
||||||
postAddEntity(result);
|
postAddEntity(result);
|
||||||
}
|
}
|
||||||
|
@ -757,6 +773,14 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
||||||
changedProperties[index] = QString("parentJointIndex:") + QString::number((int)value);
|
changedProperties[index] = QString("parentJointIndex:") + QString::number((int)value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.parentIDChanged()) {
|
||||||
|
int index = changedProperties.indexOf("parentID");
|
||||||
|
if (index >= 0) {
|
||||||
|
QUuid value = properties.getParentID();
|
||||||
|
changedProperties[index] = QString("parentID:") + value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
|
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
|
||||||
|
@ -918,7 +942,38 @@ void EntityTree::entityChanged(EntityItemPointer entity) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTree::fixupMissingParents() {
|
||||||
|
MovingEntitiesOperator moveOperator(getThisPointer());
|
||||||
|
|
||||||
|
QMutableVectorIterator<EntityItemWeakPointer> iter(_missingParent);
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
EntityItemWeakPointer entityWP = iter.next();
|
||||||
|
EntityItemPointer entity = entityWP.lock();
|
||||||
|
if (entity) {
|
||||||
|
bool success;
|
||||||
|
AACube newCube = entity->getQueryAACube(success);
|
||||||
|
if (success) {
|
||||||
|
// this entity's parent (or ancestry) was previously not fully known, and now is. Update its
|
||||||
|
// location in the EntityTree.
|
||||||
|
moveOperator.addEntityToMoveList(entity, newCube);
|
||||||
|
iter.remove();
|
||||||
|
entity->markAncestorMissing(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// entity was deleted before we found its parent.
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moveOperator.hasMovingEntities()) {
|
||||||
|
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||||
|
recurseTreeWithOperator(&moveOperator);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTree::update() {
|
void EntityTree::update() {
|
||||||
|
fixupMissingParents();
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_simulation->updateEntities();
|
_simulation->updateEntities();
|
||||||
|
|
|
@ -307,6 +307,9 @@ protected:
|
||||||
quint64 _totalEditDeltas = 0;
|
quint64 _totalEditDeltas = 0;
|
||||||
quint64 _maxEditDelta = 0;
|
quint64 _maxEditDelta = 0;
|
||||||
quint64 _treeResetTime = 0;
|
quint64 _treeResetTime = 0;
|
||||||
|
|
||||||
|
void fixupMissingParents();
|
||||||
|
QVector<EntityItemWeakPointer> _missingParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityTree_h
|
#endif // hifi_EntityTree_h
|
||||||
|
|
|
@ -302,8 +302,9 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
||||||
// simulation changing what's visible. consider the case where the entity contains an angular velocity
|
// simulation changing what's visible. consider the case where the entity contains an angular velocity
|
||||||
// the entity may not be in view and then in view a frame later, let the client side handle it's view
|
// the entity may not be in view and then in view a frame later, let the client side handle it's view
|
||||||
// frustum culling on rendering.
|
// frustum culling on rendering.
|
||||||
AACube entityCube = entity->getMaximumAACube();
|
bool success;
|
||||||
if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
|
AACube entityCube = entity->getQueryAACube(success);
|
||||||
|
if (!success || params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
|
||||||
includeThisEntity = false; // out of view, don't include it
|
includeThisEntity = false; // out of view, don't include it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,19 +414,29 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::containsEntityBounds(EntityItemPointer entity) const {
|
bool EntityTreeElement::containsEntityBounds(EntityItemPointer entity) const {
|
||||||
return containsBounds(entity->getMaximumAACube());
|
bool success;
|
||||||
|
auto queryCube = entity->getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return containsBounds(queryCube);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::bestFitEntityBounds(EntityItemPointer entity) const {
|
bool EntityTreeElement::bestFitEntityBounds(EntityItemPointer entity) const {
|
||||||
return bestFitBounds(entity->getMaximumAACube());
|
bool success;
|
||||||
|
auto queryCube = entity->getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return bestFitBounds(queryCube);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const {
|
bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const {
|
||||||
return containsBounds(properties.getMaximumAACube());
|
return containsBounds(properties.getQueryAACube());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) const {
|
bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) const {
|
||||||
return bestFitBounds(properties.getMaximumAACube());
|
return bestFitBounds(properties.getQueryAACube());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::containsBounds(const AACube& bounds) const {
|
bool EntityTreeElement::containsBounds(const AACube& bounds) const {
|
||||||
|
@ -526,7 +537,12 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABox entityBox = entity->getAABox();
|
bool success;
|
||||||
|
AABox entityBox = entity->getAABox(success);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float localDistance;
|
float localDistance;
|
||||||
BoxFace localFace;
|
BoxFace localFace;
|
||||||
glm::vec3 localSurfaceNormal;
|
glm::vec3 localSurfaceNormal;
|
||||||
|
@ -631,11 +647,12 @@ EntityItemPointer EntityTreeElement::getClosestEntity(glm::vec3 position) const
|
||||||
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<EntityItemPointer>& foundEntities) const {
|
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<EntityItemPointer>& foundEntities) const {
|
||||||
forEachEntity([&](EntityItemPointer entity) {
|
forEachEntity([&](EntityItemPointer entity) {
|
||||||
|
|
||||||
AABox entityBox = entity->getAABox();
|
bool success;
|
||||||
|
AABox entityBox = entity->getAABox(success);
|
||||||
|
|
||||||
// if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case
|
// if the sphere doesn't intersect with our world frame AABox, we don't need to consider the more complex case
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
if (entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
|
if (success && entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
|
||||||
|
|
||||||
glm::vec3 dimensions = entity->getDimensions();
|
glm::vec3 dimensions = entity->getDimensions();
|
||||||
|
|
||||||
|
@ -651,10 +668,13 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc
|
||||||
// maximum bounding sphere, which is actually larger than our actual radius
|
// maximum bounding sphere, which is actually larger than our actual radius
|
||||||
float entityTrueRadius = dimensions.x / 2.0f;
|
float entityTrueRadius = dimensions.x / 2.0f;
|
||||||
|
|
||||||
|
bool success;
|
||||||
if (findSphereSpherePenetration(searchPosition, searchRadius,
|
if (findSphereSpherePenetration(searchPosition, searchRadius,
|
||||||
entity->getCenterPosition(), entityTrueRadius, penetration)) {
|
entity->getCenterPosition(success), entityTrueRadius, penetration)) {
|
||||||
|
if (success) {
|
||||||
foundEntities.push_back(entity);
|
foundEntities.push_back(entity);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// determine the worldToEntityMatrix that doesn't include scale because
|
// determine the worldToEntityMatrix that doesn't include scale because
|
||||||
// we're going to use the registration aware aa box in the entity frame
|
// we're going to use the registration aware aa box in the entity frame
|
||||||
|
@ -679,7 +699,8 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc
|
||||||
|
|
||||||
void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities) {
|
void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities) {
|
||||||
forEachEntity([&](EntityItemPointer entity) {
|
forEachEntity([&](EntityItemPointer entity) {
|
||||||
AABox entityBox = entity->getAABox();
|
bool success;
|
||||||
|
AABox entityBox = entity->getAABox(success);
|
||||||
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
|
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
|
||||||
// FIXME - consider allowing the entity to determine penetration so that
|
// FIXME - consider allowing the entity to determine penetration so that
|
||||||
// entities could presumably dull actuall hull testing if they wanted to
|
// entities could presumably dull actuall hull testing if they wanted to
|
||||||
|
@ -696,7 +717,7 @@ void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointe
|
||||||
//
|
//
|
||||||
|
|
||||||
// If the entities AABox touches the search cube then consider it to be found
|
// If the entities AABox touches the search cube then consider it to be found
|
||||||
if (entityBox.touches(cube)) {
|
if (success && entityBox.touches(cube)) {
|
||||||
foundEntities.push_back(entity);
|
foundEntities.push_back(entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -704,7 +725,8 @@ void EntityTreeElement::getEntities(const AACube& cube, QVector<EntityItemPointe
|
||||||
|
|
||||||
void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities) {
|
void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities) {
|
||||||
forEachEntity([&](EntityItemPointer entity) {
|
forEachEntity([&](EntityItemPointer entity) {
|
||||||
AABox entityBox = entity->getAABox();
|
bool success;
|
||||||
|
AABox entityBox = entity->getAABox(success);
|
||||||
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
|
// FIXME - handle entity->getShapeType() == SHAPE_TYPE_SPHERE case better
|
||||||
// FIXME - consider allowing the entity to determine penetration so that
|
// FIXME - consider allowing the entity to determine penetration so that
|
||||||
// entities could presumably dull actuall hull testing if they wanted to
|
// entities could presumably dull actuall hull testing if they wanted to
|
||||||
|
@ -721,7 +743,7 @@ void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>
|
||||||
//
|
//
|
||||||
|
|
||||||
// If the entities AABox touches the search cube then consider it to be found
|
// If the entities AABox touches the search cube then consider it to be found
|
||||||
if (entityBox.touches(box)) {
|
if (success && entityBox.touches(box)) {
|
||||||
foundEntities.push_back(entity);
|
foundEntities.push_back(entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -940,7 +962,11 @@ bool EntityTreeElement::pruneChildren() {
|
||||||
void EntityTreeElement::expandExtentsToContents(Extents& extents) {
|
void EntityTreeElement::expandExtentsToContents(Extents& extents) {
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
foreach(EntityItemPointer entity, _entityItems) {
|
foreach(EntityItemPointer entity, _entityItems) {
|
||||||
extents.add(entity->getAABox());
|
bool success;
|
||||||
|
AABox aaBox = entity->getAABox(success);
|
||||||
|
if (success) {
|
||||||
|
extents.add(aaBox);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,11 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
|
||||||
// then translate back to work coordinates
|
// then translate back to work coordinates
|
||||||
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
|
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
|
||||||
distance = glm::distance(origin, hitAt);
|
distance = glm::distance(origin, hitAt);
|
||||||
surfaceNormal = glm::normalize(hitAt - getCenterPosition());
|
bool success;
|
||||||
|
surfaceNormal = glm::normalize(hitAt - getCenterPosition(success));
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
|
UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
|
||||||
EntityTreeElementPointer containingElement,
|
EntityTreeElementPointer containingElement,
|
||||||
EntityItemPointer existingEntity,
|
EntityItemPointer existingEntity,
|
||||||
const BoundingBoxRelatedProperties& newProperties) :
|
const AACube newQueryAACube) :
|
||||||
_tree(tree),
|
_tree(tree),
|
||||||
_existingEntity(existingEntity),
|
_existingEntity(existingEntity),
|
||||||
_containingElement(containingElement),
|
_containingElement(containingElement),
|
||||||
_containingElementCube(containingElement->getAACube()),
|
_containingElementCube(containingElement->getAACube()),
|
||||||
_newProperties(newProperties),
|
|
||||||
_entityItemID(existingEntity->getEntityItemID()),
|
_entityItemID(existingEntity->getEntityItemID()),
|
||||||
_foundOld(false),
|
_foundOld(false),
|
||||||
_foundNew(false),
|
_foundNew(false),
|
||||||
|
@ -41,13 +40,13 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
|
||||||
// entity into the the element, or do we want to use the entities "relaxed" bounds
|
// entity into the the element, or do we want to use the entities "relaxed" bounds
|
||||||
// which can handle all potential rotations?
|
// which can handle all potential rotations?
|
||||||
// the getMaximumAACube is the relaxed form.
|
// the getMaximumAACube is the relaxed form.
|
||||||
_oldEntityCube = _existingEntity->getMaximumAACube();
|
_oldEntityCube = _existingEntity->getQueryAACube();
|
||||||
_oldEntityBox = _oldEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds
|
_oldEntityBox = _oldEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds
|
||||||
|
|
||||||
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
||||||
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
||||||
// be the same for both parts of the update
|
// be the same for both parts of the update
|
||||||
bool oldElementBestFit = _containingElement->bestFitBounds(newProperties.getMaximumAACube());
|
bool oldElementBestFit = _containingElement->bestFitBounds(newQueryAACube);
|
||||||
|
|
||||||
// For some reason we've seen a case where the original containing element isn't a best fit for the old properties
|
// For some reason we've seen a case where the original containing element isn't a best fit for the old properties
|
||||||
// in this case we want to move it, even if the properties haven't changed.
|
// in this case we want to move it, even if the properties haven't changed.
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#ifndef hifi_UpdateEntityOperator_h
|
#ifndef hifi_UpdateEntityOperator_h
|
||||||
#define hifi_UpdateEntityOperator_h
|
#define hifi_UpdateEntityOperator_h
|
||||||
|
|
||||||
#include "BoundingBoxRelatedProperties.h"
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
#include "EntityItemProperties.h"
|
#include "EntityItemProperties.h"
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
class UpdateEntityOperator : public RecurseOctreeOperator {
|
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||||
public:
|
public:
|
||||||
UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement,
|
UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement,
|
||||||
EntityItemPointer existingEntity, const BoundingBoxRelatedProperties& newProperties);
|
EntityItemPointer existingEntity, const AACube newQueryAACube);
|
||||||
|
|
||||||
~UpdateEntityOperator();
|
~UpdateEntityOperator();
|
||||||
|
|
||||||
|
@ -34,7 +33,6 @@ private:
|
||||||
EntityItemPointer _existingEntity;
|
EntityItemPointer _existingEntity;
|
||||||
EntityTreeElementPointer _containingElement;
|
EntityTreeElementPointer _containingElement;
|
||||||
AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element
|
AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element
|
||||||
BoundingBoxRelatedProperties _newProperties;
|
|
||||||
EntityItemID _entityItemID;
|
EntityItemID _entityItemID;
|
||||||
bool _foundOld;
|
bool _foundOld;
|
||||||
bool _foundNew;
|
bool _foundNew;
|
||||||
|
|
|
@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::EntityAdd:
|
case PacketType::EntityAdd:
|
||||||
case PacketType::EntityEdit:
|
case PacketType::EntityEdit:
|
||||||
case PacketType::EntityData:
|
case PacketType::EntityData:
|
||||||
return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
|
return VERSION_ENTITITES_HAVE_QUERY_BOX;
|
||||||
case PacketType::AvatarData:
|
case PacketType::AvatarData:
|
||||||
case PacketType::BulkAvatarData:
|
case PacketType::BulkAvatarData:
|
||||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
||||||
|
|
|
@ -161,7 +161,8 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
||||||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||||
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||||
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
||||||
const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
const PacketVersion VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
||||||
|
const PacketVersion VERSION_ENTITITES_HAVE_QUERY_BOX = 53;
|
||||||
|
|
||||||
enum class AvatarMixerPacketVersion : PacketVersion {
|
enum class AvatarMixerPacketVersion : PacketVersion {
|
||||||
TranslationSupport = 17,
|
TranslationSupport = 17,
|
||||||
|
|
|
@ -23,6 +23,11 @@ AtomicUIntStat OctreePacketData::_totalBytesOfValues { 0 };
|
||||||
AtomicUIntStat OctreePacketData::_totalBytesOfPositions { 0 };
|
AtomicUIntStat OctreePacketData::_totalBytesOfPositions { 0 };
|
||||||
AtomicUIntStat OctreePacketData::_totalBytesOfRawData { 0 };
|
AtomicUIntStat OctreePacketData::_totalBytesOfRawData { 0 };
|
||||||
|
|
||||||
|
struct aaCubeData {
|
||||||
|
glm::vec3 corner;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) {
|
OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) {
|
||||||
changeSettings(enableCompression, targetSize); // does reset...
|
changeSettings(enableCompression, targetSize); // does reset...
|
||||||
}
|
}
|
||||||
|
@ -461,6 +466,17 @@ bool OctreePacketData::appendValue(const QByteArray& bytes) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OctreePacketData::appendValue(const AACube& aaCube) {
|
||||||
|
aaCubeData cube { aaCube.getCorner(), aaCube.getScale() };
|
||||||
|
const unsigned char* data = (const unsigned char*)&cube;
|
||||||
|
int length = sizeof(aaCubeData);
|
||||||
|
bool success = append(data, length);
|
||||||
|
if (success) {
|
||||||
|
_bytesOfValues += length;
|
||||||
|
_totalBytesOfValues += length;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
bool OctreePacketData::appendPosition(const glm::vec3& value) {
|
bool OctreePacketData::appendPosition(const glm::vec3& value) {
|
||||||
const unsigned char* data = (const unsigned char*)&value;
|
const unsigned char* data = (const unsigned char*)&value;
|
||||||
|
@ -638,3 +654,10 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteA
|
||||||
result = value;
|
result = value;
|
||||||
return sizeof(length) + length;
|
return sizeof(length) + length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, AACube& result) {
|
||||||
|
aaCubeData cube;
|
||||||
|
memcpy(&cube, dataBytes, sizeof(aaCubeData));
|
||||||
|
result = AACube(cube.corner, cube.scale);
|
||||||
|
return sizeof(aaCubeData);
|
||||||
|
}
|
||||||
|
|
|
@ -187,6 +187,9 @@ public:
|
||||||
/// appends a QByteArray value to the end of the stream, may fail if new data stream is too long to fit in packet
|
/// appends a QByteArray value to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||||
bool appendValue(const QByteArray& bytes);
|
bool appendValue(const QByteArray& bytes);
|
||||||
|
|
||||||
|
/// appends an AACube value to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||||
|
bool appendValue(const AACube& aaCube);
|
||||||
|
|
||||||
/// appends a position to the end of the stream, may fail if new data stream is too long to fit in packet
|
/// appends a position to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||||
bool appendPosition(const glm::vec3& value);
|
bool appendPosition(const glm::vec3& value);
|
||||||
|
|
||||||
|
@ -253,6 +256,7 @@ public:
|
||||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::vec3>& result);
|
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::vec3>& result);
|
||||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
|
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
|
||||||
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
|
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
|
||||||
|
static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// appends raw bytes, might fail if byte would cause packet to be too large
|
/// appends raw bytes, might fail if byte would cause packet to be too large
|
||||||
|
|
|
@ -374,6 +374,10 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_entity->queryAABoxNeedsUpdate()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_entity->getSimulatorID() != sessionID) {
|
if (_entity->getSimulatorID() != sessionID) {
|
||||||
// we don't own the simulation, but maybe we should...
|
// we don't own the simulation, but maybe we should...
|
||||||
if (_outgoingPriority != NO_PRORITY) {
|
if (_outgoingPriority != NO_PRORITY) {
|
||||||
|
@ -466,6 +470,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
||||||
properties.setActionData(_serverActionData);
|
properties.setActionData(_serverActionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.parentRelatedPropertyChanged() && _entity->computePuffedQueryAACube()) {
|
||||||
|
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||||
|
properties.setQueryAACube(_entity->getQueryAACube());
|
||||||
|
}
|
||||||
|
|
||||||
// set the LastEdited of the properties but NOT the entity itself
|
// set the LastEdited of the properties but NOT the entity itself
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
properties.setLastEdited(now);
|
properties.setLastEdited(now);
|
||||||
|
@ -502,6 +511,20 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
||||||
entityPacketSender->queueEditEntityMessage(PacketType::EntityEdit, id, properties);
|
entityPacketSender->queueEditEntityMessage(PacketType::EntityEdit, id, properties);
|
||||||
_entity->setLastBroadcast(usecTimestampNow());
|
_entity->setLastBroadcast(usecTimestampNow());
|
||||||
|
|
||||||
|
// if we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
|
||||||
|
// if they've changed.
|
||||||
|
_entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||||
|
if (descendant->getNestableType() == NestableType::Entity) {
|
||||||
|
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||||
|
if (descendant->computePuffedQueryAACube()) {
|
||||||
|
EntityItemProperties newQueryCubeProperties;
|
||||||
|
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||||
|
entityPacketSender->queueEditEntityMessage(PacketType::EntityEdit, descendant->getID(), newQueryCubeProperties);
|
||||||
|
entityDescendant->setLastBroadcast(usecTimestampNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
_lastStep = step;
|
_lastStep = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,15 @@ ObjectAction::~ObjectAction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
||||||
bool ownerEntityExpired = false;
|
|
||||||
quint64 expiresWhen = 0;
|
quint64 expiresWhen = 0;
|
||||||
|
EntityItemPointer ownerEntity = nullptr;
|
||||||
|
|
||||||
withReadLock([&]{
|
withReadLock([&]{
|
||||||
ownerEntityExpired = _ownerEntity.expired();
|
ownerEntity = _ownerEntity.lock();
|
||||||
expiresWhen = _expires;
|
expiresWhen = _expires;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ownerEntityExpired) {
|
if (!ownerEntity) {
|
||||||
qDebug() << "warning -- action with no entity removing self from btCollisionWorld.";
|
qDebug() << "warning -- action with no entity removing self from btCollisionWorld.";
|
||||||
btDynamicsWorld* dynamicsWorld = static_cast<btDynamicsWorld*>(collisionWorld);
|
btDynamicsWorld* dynamicsWorld = static_cast<btDynamicsWorld*>(collisionWorld);
|
||||||
if (dynamicsWorld) {
|
if (dynamicsWorld) {
|
||||||
|
@ -43,10 +43,8 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
||||||
if (expiresWhen > 0) {
|
if (expiresWhen > 0) {
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
if (now > expiresWhen) {
|
if (now > expiresWhen) {
|
||||||
EntityItemPointer ownerEntity = nullptr;
|
|
||||||
QUuid myID;
|
QUuid myID;
|
||||||
withWriteLock([&]{
|
withWriteLock([&]{
|
||||||
ownerEntity = _ownerEntity.lock();
|
|
||||||
_active = false;
|
_active = false;
|
||||||
myID = getID();
|
myID = getID();
|
||||||
});
|
});
|
||||||
|
|
|
@ -95,6 +95,9 @@ const float METERS_PER_MILLIMETER = 0.01f;
|
||||||
void Model::setScaleInternal(const glm::vec3& scale) {
|
void Model::setScaleInternal(const glm::vec3& scale) {
|
||||||
if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) {
|
if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) {
|
||||||
_scale = scale;
|
_scale = scale;
|
||||||
|
if (_scale.x == 0.0f || _scale.y == 0.0f || _scale.z == 0.0f) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
initJointTransforms();
|
initJointTransforms();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,3 +465,16 @@ AABox AACube::clamp(float min, float max) const {
|
||||||
return temp.clamp(min, max);
|
return temp.clamp(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AACube& AACube::operator += (const glm::vec3& point) {
|
||||||
|
glm::vec3 oldMaximumPoint = getMaximumPoint();
|
||||||
|
_corner = glm::vec3(glm::min(_corner.x, point.x),
|
||||||
|
glm::min(_corner.y, point.y),
|
||||||
|
glm::min(_corner.z, point.z));
|
||||||
|
|
||||||
|
glm::vec3 scaleOld = oldMaximumPoint - _corner;
|
||||||
|
glm::vec3 scalePoint = point - _corner;
|
||||||
|
_scale = glm::max(_scale, scalePoint.x, scalePoint.y, scalePoint.z);
|
||||||
|
_scale = glm::max(_scale, scaleOld.x, scaleOld.y, scaleOld.z);
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
AABox clamp(const glm::vec3& min, const glm::vec3& max) const;
|
AABox clamp(const glm::vec3& min, const glm::vec3& max) const;
|
||||||
AABox clamp(float min, float max) const;
|
AABox clamp(float min, float max) const;
|
||||||
|
|
||||||
|
AACube& operator += (const glm::vec3& point);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
|
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
|
||||||
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
|
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
|
||||||
|
|
|
@ -42,7 +42,7 @@ void registerMetaTypes(QScriptEngine* engine) {
|
||||||
qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
|
qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
|
||||||
qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue);
|
qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue);
|
||||||
qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue);
|
qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue);
|
||||||
|
qScriptRegisterMetaType(engine, aaCubeToScriptValue, aaCubeFromScriptValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) {
|
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) {
|
||||||
|
@ -238,6 +238,26 @@ QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
const glm::vec3& corner = aaCube.getCorner();
|
||||||
|
obj.setProperty("x", corner.x);
|
||||||
|
obj.setProperty("y", corner.y);
|
||||||
|
obj.setProperty("z", corner.z);
|
||||||
|
obj.setProperty("scale", aaCube.getScale());
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube) {
|
||||||
|
glm::vec3 corner;
|
||||||
|
corner.x = object.property("x").toVariant().toFloat();
|
||||||
|
corner.y = object.property("y").toVariant().toFloat();
|
||||||
|
corner.z = object.property("z").toVariant().toFloat();
|
||||||
|
float scale = object.property("scale").toVariant().toFloat();
|
||||||
|
|
||||||
|
aaCube.setBox(corner, scale);
|
||||||
|
}
|
||||||
|
|
||||||
void qColorFromScriptValue(const QScriptValue& object, QColor& color) {
|
void qColorFromScriptValue(const QScriptValue& object, QColor& color) {
|
||||||
if (object.isNumber()) {
|
if (object.isNumber()) {
|
||||||
color.setRgb(object.toUInt32());
|
color.setRgb(object.toUInt32());
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
#include "AACube.h"
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
class QColor;
|
class QColor;
|
||||||
|
@ -30,6 +31,7 @@ Q_DECLARE_METATYPE(glm::quat)
|
||||||
Q_DECLARE_METATYPE(xColor)
|
Q_DECLARE_METATYPE(xColor)
|
||||||
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
||||||
Q_DECLARE_METATYPE(QVector<float>)
|
Q_DECLARE_METATYPE(QVector<float>)
|
||||||
|
Q_DECLARE_METATYPE(AACube)
|
||||||
|
|
||||||
void registerMetaTypes(QScriptEngine* engine);
|
void registerMetaTypes(QScriptEngine* engine);
|
||||||
|
|
||||||
|
@ -67,6 +69,9 @@ QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array);
|
||||||
|
|
||||||
QVector<QUuid> qVectorQUuidFromScriptValue(const QScriptValue& array);
|
QVector<QUuid> qVectorQUuidFromScriptValue(const QScriptValue& array);
|
||||||
|
|
||||||
|
QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube);
|
||||||
|
void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube);
|
||||||
|
|
||||||
class PickRay {
|
class PickRay {
|
||||||
public:
|
public:
|
||||||
PickRay() : origin(0.0f), direction(0.0f) { }
|
PickRay() : origin(0.0f), direction(0.0f) { }
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
SpatialParentFinder() { }
|
SpatialParentFinder() { }
|
||||||
virtual ~SpatialParentFinder() { }
|
virtual ~SpatialParentFinder() { }
|
||||||
|
|
||||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const = 0;
|
virtual SpatiallyNestableWeakPointer find(QUuid parentID, bool& success) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SpatialParentFinder_h
|
#endif // hifi_SpatialParentFinder_h
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
#include "SpatiallyNestable.h"
|
#include "SpatiallyNestable.h"
|
||||||
|
|
||||||
|
const float defaultAACubeSize = 1.0f;
|
||||||
|
|
||||||
SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) :
|
SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) :
|
||||||
_nestableType(nestableType),
|
_nestableType(nestableType),
|
||||||
|
@ -24,21 +25,25 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) :
|
||||||
_transform.setRotation(glm::quat());
|
_transform.setRotation(glm::quat());
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform SpatiallyNestable::getParentTransform() const {
|
Transform SpatiallyNestable::getParentTransform(bool& success) const {
|
||||||
Transform result;
|
Transform result;
|
||||||
SpatiallyNestablePointer parent = getParentPointer();
|
SpatiallyNestablePointer parent = getParentPointer(success);
|
||||||
|
if (!success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
if (parent) {
|
if (parent) {
|
||||||
Transform parentTransform = parent->getTransform(_parentJointIndex);
|
Transform parentTransform = parent->getTransform(_parentJointIndex, success);
|
||||||
result = parentTransform.setScale(1.0f);
|
result = parentTransform.setScale(1.0f); // TODO: scaling
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
|
SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) const {
|
||||||
SpatiallyNestablePointer parent = _parent.lock();
|
SpatiallyNestablePointer parent = _parent.lock();
|
||||||
|
|
||||||
if (!parent && _parentID.isNull()) {
|
if (!parent && _parentID.isNull()) {
|
||||||
// no parent
|
// no parent
|
||||||
|
success = true;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +53,7 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
|
||||||
parent->beParentOfChild(getThisPointer());
|
parent->beParentOfChild(getThisPointer());
|
||||||
_parentKnowsMe = true;
|
_parentKnowsMe = true;
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +69,14 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
|
||||||
// we have a _parentID but no parent pointer, or our parent pointer was to the wrong thing
|
// we have a _parentID but no parent pointer, or our parent pointer was to the wrong thing
|
||||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||||
if (!parentFinder) {
|
if (!parentFinder) {
|
||||||
|
success = false;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
_parent = parentFinder->find(_parentID);
|
_parent = parentFinder->find(_parentID, success);
|
||||||
|
if (!success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
parent = _parent.lock();
|
parent = _parent.lock();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent->beParentOfChild(thisPointer);
|
parent->beParentOfChild(thisPointer);
|
||||||
|
@ -73,7 +84,9 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent || _parentID.isNull()) {
|
if (parent || _parentID.isNull()) {
|
||||||
thisPointer->parentChanged();
|
success = true;
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
|
@ -96,131 +109,255 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
||||||
_parentID = parentID;
|
_parentID = parentID;
|
||||||
_parentKnowsMe = false;
|
_parentKnowsMe = false;
|
||||||
}
|
}
|
||||||
parentChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) {
|
void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) {
|
||||||
|
_parentJointIndex = parentJointIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position,
|
||||||
|
const QUuid& parentID, int parentJointIndex,
|
||||||
|
bool& success) {
|
||||||
|
Transform result;
|
||||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||||
|
if (!parentFinder) {
|
||||||
|
success = false;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
Transform parentTransform;
|
Transform parentTransform;
|
||||||
if (parentFinder) {
|
auto parentWP = parentFinder->find(parentID, success);
|
||||||
auto parentWP = parentFinder->find(parentID);
|
if (!success) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
auto parent = parentWP.lock();
|
auto parent = parentWP.lock();
|
||||||
|
if (!parentID.isNull() && !parent) {
|
||||||
|
success = false;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parentTransform = parent->getTransform(parentJointIndex);
|
parentTransform = parent->getTransform(parentJointIndex, success);
|
||||||
parentTransform.setScale(1.0f);
|
if (!success) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
}
|
}
|
||||||
|
parentTransform.setScale(1.0f); // TODO: scale
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
|
|
||||||
Transform positionTransform;
|
Transform positionTransform;
|
||||||
positionTransform.setTranslation(position);
|
positionTransform.setTranslation(position);
|
||||||
Transform myWorldTransform;
|
Transform myWorldTransform;
|
||||||
Transform::mult(myWorldTransform, parentTransform, positionTransform);
|
Transform::mult(myWorldTransform, parentTransform, positionTransform);
|
||||||
|
|
||||||
myWorldTransform.setTranslation(position);
|
myWorldTransform.setTranslation(position);
|
||||||
Transform result;
|
|
||||||
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
||||||
return result.getTranslation();
|
return result.getTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) {
|
glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation,
|
||||||
|
const QUuid& parentID, int parentJointIndex,
|
||||||
|
bool& success) {
|
||||||
|
Transform result;
|
||||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||||
|
if (!parentFinder) {
|
||||||
|
success = false;
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
Transform parentTransform;
|
Transform parentTransform;
|
||||||
if (parentFinder) {
|
auto parentWP = parentFinder->find(parentID, success);
|
||||||
auto parentWP = parentFinder->find(parentID);
|
if (!success) {
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
auto parent = parentWP.lock();
|
auto parent = parentWP.lock();
|
||||||
|
if (!parentID.isNull() && !parent) {
|
||||||
|
success = false;
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parentTransform = parent->getTransform(parentJointIndex);
|
parentTransform = parent->getTransform(parentJointIndex, success);
|
||||||
parentTransform.setScale(1.0f);
|
if (!success) {
|
||||||
|
return glm::quat();
|
||||||
}
|
}
|
||||||
|
parentTransform.setScale(1.0f); // TODO: scale
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
|
|
||||||
Transform orientationTransform;
|
Transform orientationTransform;
|
||||||
orientationTransform.setRotation(orientation);
|
orientationTransform.setRotation(orientation);
|
||||||
Transform myWorldTransform;
|
Transform myWorldTransform;
|
||||||
Transform::mult(myWorldTransform, parentTransform, orientationTransform);
|
Transform::mult(myWorldTransform, parentTransform, orientationTransform);
|
||||||
myWorldTransform.setRotation(orientation);
|
myWorldTransform.setRotation(orientation);
|
||||||
Transform result;
|
|
||||||
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
||||||
return result.getRotation();
|
return result.getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex) {
|
glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position,
|
||||||
|
const QUuid& parentID, int parentJointIndex,
|
||||||
|
bool& success) {
|
||||||
|
Transform result;
|
||||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||||
|
if (!parentFinder) {
|
||||||
|
success = false;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
Transform parentTransform;
|
Transform parentTransform;
|
||||||
if (parentFinder) {
|
auto parentWP = parentFinder->find(parentID, success);
|
||||||
auto parentWP = parentFinder->find(parentID);
|
if (!success) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
auto parent = parentWP.lock();
|
auto parent = parentWP.lock();
|
||||||
|
if (!parentID.isNull() && !parent) {
|
||||||
|
success = false;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parentTransform = parent->getTransform(parentJointIndex);
|
parentTransform = parent->getTransform(parentJointIndex, success);
|
||||||
parentTransform.setScale(1.0f);
|
if (!success) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
}
|
}
|
||||||
|
parentTransform.setScale(1.0f); // TODO: scale
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
|
|
||||||
Transform positionTransform;
|
Transform positionTransform;
|
||||||
positionTransform.setTranslation(position);
|
positionTransform.setTranslation(position);
|
||||||
Transform result;
|
|
||||||
Transform::mult(result, parentTransform, positionTransform);
|
Transform::mult(result, parentTransform, positionTransform);
|
||||||
return result.getTranslation();
|
return result.getTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex) {
|
glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation,
|
||||||
|
const QUuid& parentID, int parentJointIndex,
|
||||||
|
bool& success) {
|
||||||
|
Transform result;
|
||||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||||
|
if (!parentFinder) {
|
||||||
|
success = false;
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
Transform parentTransform;
|
Transform parentTransform;
|
||||||
if (parentFinder) {
|
auto parentWP = parentFinder->find(parentID, success);
|
||||||
auto parentWP = parentFinder->find(parentID);
|
if (!success) {
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
auto parent = parentWP.lock();
|
auto parent = parentWP.lock();
|
||||||
|
if (!parentID.isNull() && !parent) {
|
||||||
|
success = false;
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parentTransform = parent->getTransform(parentJointIndex);
|
parentTransform = parent->getTransform(parentJointIndex, success);
|
||||||
|
if (!success) {
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
parentTransform.setScale(1.0f);
|
parentTransform.setScale(1.0f);
|
||||||
}
|
}
|
||||||
}
|
success = true;
|
||||||
|
|
||||||
Transform orientationTransform;
|
Transform orientationTransform;
|
||||||
orientationTransform.setRotation(orientation);
|
orientationTransform.setRotation(orientation);
|
||||||
Transform result;
|
|
||||||
Transform::mult(result, parentTransform, orientationTransform);
|
Transform::mult(result, parentTransform, orientationTransform);
|
||||||
return result.getRotation();
|
return result.getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 SpatiallyNestable::getPosition(bool& success) const {
|
||||||
|
return getTransform(success).getTranslation();
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getPosition() const {
|
glm::vec3 SpatiallyNestable::getPosition() const {
|
||||||
return getTransform().getTranslation();
|
bool success;
|
||||||
|
auto result = getPosition(success);
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- getPosition failed" << getID();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getPosition(int jointIndex) const {
|
glm::vec3 SpatiallyNestable::getPosition(int jointIndex, bool& success) const {
|
||||||
return getTransform(jointIndex).getTranslation();
|
return getTransform(jointIndex, success).getTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setPosition(const glm::vec3& position) {
|
void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success) {
|
||||||
Transform parentTransform = getParentTransform();
|
Transform parentTransform = getParentTransform(success);
|
||||||
Transform myWorldTransform;
|
Transform myWorldTransform;
|
||||||
_transformLock.withWriteLock([&] {
|
_transformLock.withWriteLock([&] {
|
||||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||||
myWorldTransform.setTranslation(position);
|
myWorldTransform.setTranslation(position);
|
||||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||||
});
|
});
|
||||||
|
if (success) {
|
||||||
locationChanged();
|
locationChanged();
|
||||||
|
} else {
|
||||||
|
qDebug() << "setPosition failed for" << getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpatiallyNestable::setPosition(const glm::vec3& position) {
|
||||||
|
bool success;
|
||||||
|
setPosition(position, success);
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- setPosition failed" << getID();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat SpatiallyNestable::getOrientation(bool& success) const {
|
||||||
|
return getTransform(success).getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat SpatiallyNestable::getOrientation() const {
|
glm::quat SpatiallyNestable::getOrientation() const {
|
||||||
return getTransform().getRotation();
|
bool success;
|
||||||
|
auto result = getOrientation(success);
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- getOrientation failed" << getID();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat SpatiallyNestable::getOrientation(int jointIndex) const {
|
glm::quat SpatiallyNestable::getOrientation(int jointIndex, bool& success) const {
|
||||||
return getTransform(jointIndex).getRotation();
|
return getTransform(jointIndex, success).getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setOrientation(const glm::quat& orientation) {
|
void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& success) {
|
||||||
Transform parentTransform = getParentTransform();
|
Transform parentTransform = getParentTransform(success);
|
||||||
Transform myWorldTransform;
|
Transform myWorldTransform;
|
||||||
_transformLock.withWriteLock([&] {
|
_transformLock.withWriteLock([&] {
|
||||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||||
myWorldTransform.setRotation(orientation);
|
myWorldTransform.setRotation(orientation);
|
||||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||||
});
|
});
|
||||||
|
if (success) {
|
||||||
locationChanged();
|
locationChanged();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Transform SpatiallyNestable::getTransform() const {
|
void SpatiallyNestable::setOrientation(const glm::quat& orientation) {
|
||||||
|
bool success;
|
||||||
|
setOrientation(orientation, success);
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "Warning -- setOrientation failed" << getID();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const Transform SpatiallyNestable::getTransform(bool& success) const {
|
||||||
// return a world-space transform for this object's location
|
// return a world-space transform for this object's location
|
||||||
Transform parentTransform = getParentTransform();
|
Transform parentTransform = getParentTransform(success);
|
||||||
Transform result;
|
Transform result;
|
||||||
_transformLock.withReadLock([&] {
|
_transformLock.withReadLock([&] {
|
||||||
Transform::mult(result, parentTransform, _transform);
|
Transform::mult(result, parentTransform, _transform);
|
||||||
|
@ -228,25 +365,34 @@ const Transform SpatiallyNestable::getTransform() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Transform SpatiallyNestable::getTransform(int jointIndex) const {
|
const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success) const {
|
||||||
// this returns the world-space transform for this object. It finds its parent's transform (which may
|
// this returns the world-space transform for this object. It finds its parent's transform (which may
|
||||||
// cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it.
|
// cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it.
|
||||||
Transform worldTransform = getTransform();
|
|
||||||
Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex);
|
|
||||||
Transform jointInWorldFrame;
|
Transform jointInWorldFrame;
|
||||||
Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame);
|
|
||||||
|
Transform worldTransform = getTransform(success);
|
||||||
|
if (!success) {
|
||||||
return jointInWorldFrame;
|
return jointInWorldFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setTransform(const Transform& transform) {
|
Transform jointInObjectFrame = getAbsoluteJointTransformInObjectFrame(jointIndex);
|
||||||
Transform parentTransform = getParentTransform();
|
Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame);
|
||||||
|
success = true;
|
||||||
|
return jointInWorldFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpatiallyNestable::setTransform(const Transform& transform, bool& success) {
|
||||||
|
Transform parentTransform = getParentTransform(success);
|
||||||
_transformLock.withWriteLock([&] {
|
_transformLock.withWriteLock([&] {
|
||||||
Transform::inverseMult(_transform, parentTransform, transform);
|
Transform::inverseMult(_transform, parentTransform, transform);
|
||||||
});
|
});
|
||||||
|
if (success) {
|
||||||
locationChanged();
|
locationChanged();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getScale() const {
|
glm::vec3 SpatiallyNestable::getScale() const {
|
||||||
|
// TODO: scale
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
_transformLock.withReadLock([&] {
|
_transformLock.withReadLock([&] {
|
||||||
result = _transform.getScale();
|
result = _transform.getScale();
|
||||||
|
@ -255,11 +401,12 @@ glm::vec3 SpatiallyNestable::getScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getScale(int jointIndex) const {
|
glm::vec3 SpatiallyNestable::getScale(int jointIndex) const {
|
||||||
// XXX ... something with joints
|
// TODO: scale
|
||||||
return getScale();
|
return getScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setScale(const glm::vec3& scale) {
|
void SpatiallyNestable::setScale(const glm::vec3& scale) {
|
||||||
|
// TODO: scale
|
||||||
_transformLock.withWriteLock([&] {
|
_transformLock.withWriteLock([&] {
|
||||||
_transform.setScale(scale);
|
_transform.setScale(scale);
|
||||||
});
|
});
|
||||||
|
@ -312,6 +459,7 @@ void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getLocalScale() const {
|
glm::vec3 SpatiallyNestable::getLocalScale() const {
|
||||||
|
// TODO: scale
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
_transformLock.withReadLock([&] {
|
_transformLock.withReadLock([&] {
|
||||||
result = _transform.getScale();
|
result = _transform.getScale();
|
||||||
|
@ -320,6 +468,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setLocalScale(const glm::vec3& scale) {
|
void SpatiallyNestable::setLocalScale(const glm::vec3& scale) {
|
||||||
|
// TODO: scale
|
||||||
_transformLock.withWriteLock([&] {
|
_transformLock.withWriteLock([&] {
|
||||||
_transform.setScale(scale);
|
_transform.setScale(scale);
|
||||||
});
|
});
|
||||||
|
@ -380,3 +529,83 @@ void SpatiallyNestable::locationChanged() {
|
||||||
object->locationChanged();
|
object->locationChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AACube SpatiallyNestable::getMaximumAACube(bool& success) const {
|
||||||
|
return AACube(getPosition(success) - glm::vec3(defaultAACubeSize / 2.0f), defaultAACubeSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) {
|
||||||
|
_queryAACube = queryAACube;
|
||||||
|
if (queryAACube.getScale() > 0.0f) {
|
||||||
|
_queryAACubeSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpatiallyNestable::queryAABoxNeedsUpdate() const {
|
||||||
|
bool success;
|
||||||
|
AACube currentAACube = getMaximumAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "can't getMaximumAACube for" << getID();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure children are still in their boxes, also.
|
||||||
|
bool childNeedsUpdate = false;
|
||||||
|
getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||||
|
if (!childNeedsUpdate && descendant->queryAABoxNeedsUpdate()) {
|
||||||
|
childNeedsUpdate = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (childNeedsUpdate) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_queryAACubeSet && _queryAACube.contains(currentAACube)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpatiallyNestable::computePuffedQueryAACube() {
|
||||||
|
if (!queryAABoxNeedsUpdate()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool success;
|
||||||
|
AACube currentAACube = getMaximumAACube(success);
|
||||||
|
// make an AACube with edges thrice as long and centered on the object
|
||||||
|
_queryAACube = AACube(currentAACube.getCorner() - glm::vec3(currentAACube.getScale()), currentAACube.getScale() * 3.0f);
|
||||||
|
_queryAACubeSet = true;
|
||||||
|
|
||||||
|
getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||||
|
bool success;
|
||||||
|
AACube descendantAACube = descendant->getQueryAACube(success);
|
||||||
|
if (success) {
|
||||||
|
if (_queryAACube.contains(descendantAACube)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_queryAACube += descendantAACube.getMinimumPoint();
|
||||||
|
_queryAACube += descendantAACube.getMaximumPoint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AACube SpatiallyNestable::getQueryAACube(bool& success) const {
|
||||||
|
if (_queryAACubeSet) {
|
||||||
|
success = true;
|
||||||
|
return _queryAACube;
|
||||||
|
}
|
||||||
|
success = false;
|
||||||
|
return AACube(getPosition(success) - glm::vec3(defaultAACubeSize / 2.0f), defaultAACubeSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
AACube SpatiallyNestable::getQueryAACube() const {
|
||||||
|
bool success;
|
||||||
|
auto result = getQueryAACube(success);
|
||||||
|
if (!success) {
|
||||||
|
qDebug() << "getQueryAACube failed for" << getID();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
#include "AACube.h"
|
||||||
#include "SpatialParentFinder.h"
|
#include "SpatialParentFinder.h"
|
||||||
#include "shared/ReadWriteLockable.h"
|
#include "shared/ReadWriteLockable.h"
|
||||||
|
|
||||||
|
@ -38,37 +39,49 @@ public:
|
||||||
virtual const QUuid& getID() const { return _id; }
|
virtual const QUuid& getID() const { return _id; }
|
||||||
virtual void setID(const QUuid& id) { _id = id; }
|
virtual void setID(const QUuid& id) { _id = id; }
|
||||||
|
|
||||||
virtual const QUuid getParentID() const { return _parentID; }
|
virtual QUuid getParentID() const { return _parentID; }
|
||||||
virtual void setParentID(const QUuid& parentID);
|
virtual void setParentID(const QUuid& parentID);
|
||||||
|
|
||||||
virtual quint16 getParentJointIndex() const { return _parentJointIndex; }
|
virtual quint16 getParentJointIndex() const { return _parentJointIndex; }
|
||||||
virtual void setParentJointIndex(quint16 parentJointIndex) { _parentJointIndex = parentJointIndex; }
|
virtual void setParentJointIndex(quint16 parentJointIndex);
|
||||||
|
|
||||||
static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex);
|
static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success);
|
||||||
static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex);
|
static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success);
|
||||||
|
|
||||||
static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex);
|
static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success);
|
||||||
static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex);
|
static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success);
|
||||||
|
|
||||||
// world frame
|
// world frame
|
||||||
virtual const Transform getTransform() const;
|
virtual const Transform getTransform(bool& success) const;
|
||||||
virtual void setTransform(const Transform& transform);
|
virtual void setTransform(const Transform& transform, bool& success);
|
||||||
|
|
||||||
virtual Transform getParentTransform() const;
|
virtual Transform getParentTransform(bool& success) const;
|
||||||
|
|
||||||
|
virtual glm::vec3 getPosition(bool& success) const;
|
||||||
virtual glm::vec3 getPosition() const;
|
virtual glm::vec3 getPosition() const;
|
||||||
|
virtual void setPosition(const glm::vec3& position, bool& success);
|
||||||
virtual void setPosition(const glm::vec3& position);
|
virtual void setPosition(const glm::vec3& position);
|
||||||
|
|
||||||
|
virtual glm::quat getOrientation(bool& success) const;
|
||||||
virtual glm::quat getOrientation() const;
|
virtual glm::quat getOrientation() const;
|
||||||
virtual glm::quat getOrientation(int jointIndex) const;
|
virtual glm::quat getOrientation(int jointIndex, bool& success) const;
|
||||||
|
virtual void setOrientation(const glm::quat& orientation, bool& success);
|
||||||
virtual void setOrientation(const glm::quat& orientation);
|
virtual void setOrientation(const glm::quat& orientation);
|
||||||
|
|
||||||
|
virtual AACube getMaximumAACube(bool& success) const;
|
||||||
|
virtual bool computePuffedQueryAACube();
|
||||||
|
|
||||||
|
virtual void setQueryAACube(const AACube& queryAACube);
|
||||||
|
virtual bool queryAABoxNeedsUpdate() const;
|
||||||
|
virtual AACube getQueryAACube(bool& success) const;
|
||||||
|
virtual AACube getQueryAACube() const;
|
||||||
|
|
||||||
virtual glm::vec3 getScale() const;
|
virtual glm::vec3 getScale() const;
|
||||||
virtual void setScale(const glm::vec3& scale);
|
virtual void setScale(const glm::vec3& scale);
|
||||||
|
|
||||||
// get world-frame values for a specific joint
|
// get world-frame values for a specific joint
|
||||||
virtual const Transform getTransform(int jointIndex) const;
|
virtual const Transform getTransform(int jointIndex, bool& success) const;
|
||||||
virtual glm::vec3 getPosition(int jointIndex) const;
|
virtual glm::vec3 getPosition(int jointIndex, bool& success) const;
|
||||||
virtual glm::vec3 getScale(int jointIndex) const;
|
virtual glm::vec3 getScale(int jointIndex) const;
|
||||||
|
|
||||||
// object's parent's frame
|
// object's parent's frame
|
||||||
|
@ -89,17 +102,23 @@ public:
|
||||||
|
|
||||||
// this object's frame
|
// this object's frame
|
||||||
virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const;
|
virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const;
|
||||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); }
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const = 0;
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); }
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const = 0;
|
||||||
|
|
||||||
SpatiallyNestablePointer getThisPointer() const;
|
SpatiallyNestablePointer getThisPointer() const;
|
||||||
|
|
||||||
|
void markAncestorMissing(bool value) { _missingAncestor = value; }
|
||||||
|
bool getAncestorMissing() { return _missingAncestor; }
|
||||||
|
|
||||||
|
void forEachChild(std::function<void(SpatiallyNestablePointer)> actor);
|
||||||
|
void forEachDescendant(std::function<void(SpatiallyNestablePointer)> actor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const NestableType _nestableType; // EntityItem or an AvatarData
|
const NestableType _nestableType; // EntityItem or an AvatarData
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
QUuid _parentID; // what is this thing's transform relative to?
|
QUuid _parentID; // what is this thing's transform relative to?
|
||||||
quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to?
|
quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to?
|
||||||
SpatiallyNestablePointer getParentPointer() const;
|
SpatiallyNestablePointer getParentPointer(bool& success) const;
|
||||||
mutable SpatiallyNestableWeakPointer _parent;
|
mutable SpatiallyNestableWeakPointer _parent;
|
||||||
|
|
||||||
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const;
|
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const;
|
||||||
|
@ -108,12 +127,14 @@ protected:
|
||||||
mutable ReadWriteLockable _childrenLock;
|
mutable ReadWriteLockable _childrenLock;
|
||||||
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
||||||
|
|
||||||
virtual void parentChanged() {} // called when parent pointer is updated
|
|
||||||
virtual void locationChanged(); // called when a this object's location has changed
|
virtual void locationChanged(); // called when a this object's location has changed
|
||||||
virtual void dimensionsChanged() {} // called when a this object's dimensions have changed
|
virtual void dimensionsChanged() {} // called when a this object's dimensions have changed
|
||||||
|
|
||||||
void forEachChild(std::function<void(SpatiallyNestablePointer)> actor);
|
// _queryAACube is used to decide where something lives in the octree
|
||||||
void forEachDescendant(std::function<void(SpatiallyNestablePointer)> actor);
|
mutable AACube _queryAACube;
|
||||||
|
mutable bool _queryAACubeSet { false };
|
||||||
|
|
||||||
|
bool _missingAncestor { false };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable ReadWriteLockable _transformLock;
|
mutable ReadWriteLockable _transformLock;
|
||||||
|
|
49
libraries/shared/src/ThreadSafeValueCache.h
Normal file
49
libraries/shared/src/ThreadSafeValueCache.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// ThreadSafeValueCache.h
|
||||||
|
// interface/src/avatar
|
||||||
|
//
|
||||||
|
// Copyright 2012 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_ThreadSafeValueCache_h
|
||||||
|
#define hifi_ThreadSafeValueCache_h
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
// Helper class for for sharing a value type between threads.
|
||||||
|
// It allows many threads to get or set a value atomically.
|
||||||
|
// This provides cache semantics, any get will return the last set value.
|
||||||
|
//
|
||||||
|
// For example: This can be used to copy values between C++ code running on the application thread
|
||||||
|
// and JavaScript which is running on a different thread.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ThreadSafeValueCache {
|
||||||
|
public:
|
||||||
|
ThreadSafeValueCache(const T& v) : _value { v } {}
|
||||||
|
|
||||||
|
// returns atomic copy of the cached value.
|
||||||
|
T get() const {
|
||||||
|
std::lock_guard<std::mutex> guard(_mutex);
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// will reflect copy of value into the cache.
|
||||||
|
void set(const T& v) {
|
||||||
|
std::lock_guard<std::mutex> guard(_mutex);
|
||||||
|
_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::mutex _mutex;
|
||||||
|
T _value;
|
||||||
|
|
||||||
|
// no copies
|
||||||
|
ThreadSafeValueCache(const ThreadSafeValueCache&) = delete;
|
||||||
|
ThreadSafeValueCache& operator=(const ThreadSafeValueCache&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #define hifi_ThreadSafeValueCache_h
|
|
@ -176,9 +176,34 @@ void OffscreenUi::information(const QString& title, const QString& text,
|
||||||
void OffscreenUi::question(const QString& title, const QString& text,
|
void OffscreenUi::question(const QString& title, const QString& text,
|
||||||
ButtonCallback callback,
|
ButtonCallback callback,
|
||||||
QMessageBox::StandardButtons buttons) {
|
QMessageBox::StandardButtons buttons) {
|
||||||
messageBox(title, text, callback,
|
|
||||||
|
bool waiting = true;
|
||||||
|
ButtonCallback blockingCallback = [&](QMessageBox::StandardButton response){
|
||||||
|
callback(response); // call the actual callback
|
||||||
|
waiting = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
messageBox(title, text, blockingCallback,
|
||||||
static_cast<QMessageBox::Icon>(MessageDialog::Question), buttons);
|
static_cast<QMessageBox::Icon>(MessageDialog::Question), buttons);
|
||||||
|
|
||||||
|
// block until the call back has been called
|
||||||
|
while (waiting) {
|
||||||
|
QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton OffscreenUi::question(void* ignored, const QString& title, const QString& text,
|
||||||
|
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
|
||||||
|
|
||||||
|
QMessageBox::StandardButton result = defaultButton;
|
||||||
|
|
||||||
|
OffscreenUi::question(title, text, [&](QMessageBox::StandardButton response){
|
||||||
|
result = response;
|
||||||
|
}, buttons);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OffscreenUi::warning(const QString& title, const QString& text,
|
void OffscreenUi::warning(const QString& title, const QString& text,
|
||||||
ButtonCallback callback,
|
ButtonCallback callback,
|
||||||
|
@ -187,6 +212,26 @@ void OffscreenUi::warning(const QString& title, const QString& text,
|
||||||
static_cast<QMessageBox::Icon>(MessageDialog::Warning), buttons);
|
static_cast<QMessageBox::Icon>(MessageDialog::Warning), buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton OffscreenUi::warning(void* ignored, const QString& title, const QString& text,
|
||||||
|
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
|
||||||
|
|
||||||
|
bool waiting = true;
|
||||||
|
QMessageBox::StandardButton result = defaultButton;
|
||||||
|
|
||||||
|
OffscreenUi::warning(title, text, [&](QMessageBox::StandardButton response){
|
||||||
|
result = response;
|
||||||
|
waiting = false;
|
||||||
|
}, buttons);
|
||||||
|
|
||||||
|
// block until the call back has been called
|
||||||
|
while (waiting) {
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OffscreenUi::critical(const QString& title, const QString& text,
|
void OffscreenUi::critical(const QString& title, const QString& text,
|
||||||
ButtonCallback callback,
|
ButtonCallback callback,
|
||||||
QMessageBox::StandardButtons buttons) {
|
QMessageBox::StandardButtons buttons) {
|
||||||
|
|
|
@ -45,14 +45,25 @@ public:
|
||||||
ButtonCallback callback = NO_OP_CALLBACK,
|
ButtonCallback callback = NO_OP_CALLBACK,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
/// Note: will block until user clicks a response to the question
|
||||||
static void question(const QString& title, const QString& text,
|
static void question(const QString& title, const QString& text,
|
||||||
ButtonCallback callback = NO_OP_CALLBACK,
|
ButtonCallback callback = NO_OP_CALLBACK,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No));
|
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No));
|
||||||
|
|
||||||
|
/// Same design as QMessageBox::question(), will block, returns result
|
||||||
|
static QMessageBox::StandardButton question(void* ignored, const QString& title, const QString& text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
|
||||||
|
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||||
|
|
||||||
static void warning(const QString& title, const QString& text,
|
static void warning(const QString& title, const QString& text,
|
||||||
ButtonCallback callback = NO_OP_CALLBACK,
|
ButtonCallback callback = NO_OP_CALLBACK,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
/// Same design as QMessageBox::warning(), will block, returns result
|
||||||
|
static QMessageBox::StandardButton warning(void* ignored, const QString& title, const QString& text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
|
||||||
|
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||||
|
|
||||||
static void critical(const QString& title, const QString& text,
|
static void critical(const QString& title, const QString& text,
|
||||||
ButtonCallback callback = NO_OP_CALLBACK,
|
ButtonCallback callback = NO_OP_CALLBACK,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
Loading…
Reference in a new issue