diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60ae1843d6..e5d5e696a1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3963,9 +3963,14 @@ void Application::calibrateEyeTracker5Points() { } #endif -bool Application::exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset) { +bool Application::exportEntities(const QString& filename, + const QVector& entityIDs, + const glm::vec3* givenOffset) { QHash entities; + auto nodeList = DependencyManager::get(); + const QUuid myAvatarID = nodeList->getSessionUUID(); + auto entityTree = getEntities()->getTree(); auto exportTree = std::make_shared(); exportTree->createRootElement(); @@ -3981,8 +3986,12 @@ bool Application::exportEntities(const QString& filename, const QVectorgetParentID(); - if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) { - auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties. + bool parentIsAvatar = (parentID == AVATAR_SELF_ID || parentID == myAvatarID); + if (!parentIsAvatar && (parentID.isInvalidID() || + !entityIDs.contains(parentID) || + !entityTree->findEntityByEntityItemID(parentID))) { + // If parent wasn't selected, we want absolute position, which isn't in properties. + auto position = entityItem->getPosition(); root.x = glm::min(root.x, position.x); root.y = glm::min(root.y, position.y); root.z = glm::min(root.z, position.z); @@ -4002,12 +4011,16 @@ bool Application::exportEntities(const QString& filename, const QVectorgetProperties(); EntityItemID parentID = properties.getParentID(); - if (parentID.isInvalidID()) { - properties.setPosition(properties.getPosition() - root); + bool parentIsAvatar = (parentID == AVATAR_SELF_ID || parentID == myAvatarID); + if (parentIsAvatar) { + properties.setParentID(AVATAR_SELF_ID); + } else { + if (parentID.isInvalidID()) { + properties.setPosition(properties.getPosition() - root); + } else if (!entities.contains(parentID)) { + entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); + } // else valid parent -- don't offset } - else if (!entities.contains(parentID)) { - entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); - } // else valid parent -- don't offset exportTree->addEntity(entityDatum->getEntityItemID(), properties); } }); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 10e2202553..5d82405aee 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3238,3 +3238,9 @@ void MyAvatar::setModelScale(float scale) { emit sensorToWorldScaleChanged(sensorToWorldScale); } } + +SpatialParentTree* MyAvatar::getParentTree() const { + auto entityTreeRenderer = qApp->getEntities(); + EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; + return entityTree.get(); +} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9620d61a49..952315a85f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -544,6 +544,8 @@ public: float getUserHeight() const; float getUserEyeHeight() const; + virtual SpatialParentTree* getParentTree() const override; + public slots: void increaseSize(); void decreaseSize(); diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index a34240483b..42425932df 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -305,3 +305,9 @@ Transform Base3DOverlay::evalRenderTransform() { void Base3DOverlay::setRenderTransform(const Transform& transform) { _renderTransform = transform; } + +SpatialParentTree* Base3DOverlay::getParentTree() const { + auto entityTreeRenderer = qApp->getEntities(); + EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; + return entityTree.get(); +} diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index d90caf5c4d..436cfbf97b 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -55,7 +55,7 @@ public: virtual AABox getBounds() const override = 0; void update(float deltatime) override; - + void notifyRenderTransformChange() const; void setProperties(const QVariantMap& properties) override; @@ -69,6 +69,8 @@ public: return findRayIntersection(origin, direction, distance, face, surfaceNormal); } + virtual SpatialParentTree* getParentTree() const override; + protected: virtual void locationChanged(bool tellPhysics = true) override; virtual void parentDeleted() override; diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index ee0fcf8218..f93b6a49ec 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -45,7 +45,7 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type, } EntityItemPointer entity = entityTree->findEntityByEntityItemID(entityItemID); if (!entity) { - qCDebug(entities) << "EntityEditPacketSender::queueEditEntityMessage can't find entity."; + qCDebug(entities) << "EntityEditPacketSender::queueEditAvatarEntityMessage can't find entity: " << entityItemID; return; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index fa386ae090..d16aeaa6e1 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1848,7 +1848,13 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void QHash::iterator iter = args->map->find(oldID); if (iter == args->map->end()) { - EntityItemID newID = QUuid::createUuid(); + EntityItemID newID; + if (oldID == AVATAR_SELF_ID) { + auto nodeList = DependencyManager::get(); + newID = EntityItemID(nodeList->getSessionUUID()); + } else { + newID = QUuid::createUuid(); + } args->map->insert(oldID, newID); return newID; } @@ -1865,8 +1871,8 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void properties.setPosition(properties.getPosition() + args->root); } else { EntityItemPointer parentEntity = args->ourTree->findEntityByEntityItemID(oldParentID); - if (parentEntity) { // map the parent - properties.setParentID(getMapped(parentEntity->getID())); + if (parentEntity || oldParentID == AVATAR_SELF_ID) { // map the parent + properties.setParentID(getMapped(oldParentID)); // But do not add root offset in this case. } else { // Should not happen, but let's try to be helpful... item->globalizeProperties(properties, "Cannot find %3 parent of %2 %1", args->root); @@ -1941,6 +1947,12 @@ bool EntityTree::readFromMap(QVariantMap& map) { entityItemID = EntityItemID(QUuid::createUuid()); } + if (properties.getClientOnly()) { + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + properties.setOwningAvatarID(myNodeID); + } + EntityItemPointer entity = addEntity(entityItemID, properties); if (!entity) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 8ea38f5f13..8c43632456 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -102,8 +102,11 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) cons if (parent && parent->getID() == parentID) { // parent pointer is up-to-date if (!_parentKnowsMe) { - parent->beParentOfChild(getThisPointer()); - _parentKnowsMe = true; + SpatialParentTree* parentTree = parent->getParentTree(); + if (!parentTree || parentTree == getParentTree()) { + parent->beParentOfChild(getThisPointer()); + _parentKnowsMe = true; + } } success = true; return parent; @@ -129,8 +132,15 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) cons parent = _parent.lock(); if (parent) { - parent->beParentOfChild(getThisPointer()); - _parentKnowsMe = true; + + // it's possible for an entity with a parent of AVATAR_SELF_ID can be imported into a side-tree + // such as the clipboard's. if this is the case, we don't want the parent to consider this a + // child. + SpatialParentTree* parentTree = parent->getParentTree(); + if (!parentTree || parentTree == getParentTree()) { + parent->beParentOfChild(getThisPointer()); + _parentKnowsMe = true; + } } success = (parent || parentID.isNull()); diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index e9e25b058b..d6d80541ee 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -222,7 +222,7 @@ getControllerJointIndex = function (hand) { return controllerJointIndex; } - return MyAvatar.getJointIndex("Head"); + return -1; }; propsArePhysical = function (props) {