From 7b08d047b19598784cfa03c67d67329a6351724a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 22 Oct 2015 16:59:56 -0700 Subject: [PATCH] when EntityTree::updateEntityWithElement is called on an entity, call it on all the children of that entity --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/AvatarData.h | 5 +- .../src/BoundingBoxRelatedProperties.cpp | 83 ++++++++++++++ .../src/BoundingBoxRelatedProperties.h | 30 ++++++ libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 33 +++++- libraries/entities/src/EntityTypes.h | 4 +- .../entities/src/UpdateEntityOperator.cpp | 101 ++++-------------- libraries/entities/src/UpdateEntityOperator.h | 6 +- libraries/shared/src/SpatiallyNestable.cpp | 24 ++++- libraries/shared/src/SpatiallyNestable.h | 28 +++-- 11 files changed, 213 insertions(+), 105 deletions(-) create mode 100644 libraries/entities/src/BoundingBoxRelatedProperties.cpp create mode 100644 libraries/entities/src/BoundingBoxRelatedProperties.h diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index fc9d9c75a7..a1db573d8d 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -37,7 +37,7 @@ const glm::vec3 DEFAULT_LOCAL_AABOX_CORNER(-0.5f); const glm::vec3 DEFAULT_LOCAL_AABOX_SCALE(1.0f); AvatarData::AvatarData() : - _sessionUUID(), + SpatiallyNestable(NestableTypes::Avatar, QUuid()), _handPosition(0.0f), _targetScale(1.0f), _handState(0), diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4f826eafde..8a0a9ac38a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -172,7 +172,7 @@ public: virtual bool isMyAvatar() const { return false; } - const QUuid& getSessionUUID() const { return _sessionUUID; } + const QUuid& getSessionUUID() const { return getID(); } glm::vec3 getHandPosition() const; void setHandPosition(const glm::vec3& handPosition); @@ -327,7 +327,7 @@ public slots: void setBillboardFromNetworkReply(); void setJointMappingsFromNetworkReply(); - void setSessionUUID(const QUuid& sessionUUID) { _sessionUUID = sessionUUID; } + void setSessionUUID(const QUuid& sessionUUID) { setID(sessionUUID); } bool isPlaying(); bool isPaused(); @@ -353,7 +353,6 @@ public slots: void stopPlaying(); protected: - QUuid _sessionUUID; glm::vec3 _handPosition; // Body scale diff --git a/libraries/entities/src/BoundingBoxRelatedProperties.cpp b/libraries/entities/src/BoundingBoxRelatedProperties.cpp new file mode 100644 index 0000000000..e9ee302300 --- /dev/null +++ b/libraries/entities/src/BoundingBoxRelatedProperties.cpp @@ -0,0 +1,83 @@ +// +// 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); +} diff --git a/libraries/entities/src/BoundingBoxRelatedProperties.h b/libraries/entities/src/BoundingBoxRelatedProperties.h new file mode 100644 index 0000000000..811c885fd2 --- /dev/null +++ b/libraries/entities/src/BoundingBoxRelatedProperties.h @@ -0,0 +1,30 @@ +// +// 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 diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f8e191cde1..46d5635fc5 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -37,7 +37,7 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; EntityItem::EntityItem(const EntityItemID& entityItemID) : - SpatiallyNestable(entityItemID), + SpatiallyNestable(NestableTypes::Entity, entityItemID), _type(EntityTypes::Unknown), _lastSimulated(0), _lastUpdated(0), diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 24c13ae28e..257e3e0ed2 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -143,8 +143,11 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI if (!wantsLocked) { EntityItemProperties tempProperties; tempProperties.setLocked(wantsLocked); - UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, tempProperties); + + BoundingBoxRelatedProperties newBBRelProperties(entity, tempProperties); + UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties); recurseTreeWithOperator(&theOperator); + entity->setProperties(tempProperties); _isDirty = true; } } @@ -205,8 +208,34 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI quint64 entityScriptTimestampBefore = entity->getScriptTimestamp(); QString collisionSoundURLBefore = entity->getCollisionSoundURL(); uint32_t preFlags = entity->getDirtyFlags(); - UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, properties); + + BoundingBoxRelatedProperties newBBRelProperties(entity, properties); + UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties); recurseTreeWithOperator(&theOperator); + entity->setProperties(properties); + + // if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse + QQueue toProcess; + foreach (SpatiallyNestablePointer child, entity->getChildren()) { + if (child && child->getNestableType() == NestableTypes::Entity) { + toProcess.enqueue(child); + } + } + + while (!toProcess.empty()) { + EntityItemPointer childEntity = std::static_pointer_cast(toProcess.dequeue()); + BoundingBoxRelatedProperties newChildBBRelProperties(childEntity); + UpdateEntityOperator theChildOperator(getThisPointer(), + childEntity->getElement(), + childEntity, newChildBBRelProperties); + recurseTreeWithOperator(&theChildOperator); + foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { + if (childChild && childChild->getNestableType() == NestableTypes::Entity) { + toProcess.enqueue(childChild); + } + } + } + _isDirty = true; uint32_t newFlags = entity->getDirtyFlags() & ~preFlags; diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 30b6edbc07..3536327d18 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -20,8 +20,8 @@ #include // for RenderArgs class EntityItem; -typedef std::shared_ptr EntityItemPointer; -typedef std::weak_ptr EntityItemWeakPointer; +using EntityItemPointer = std::shared_ptr; +using EntityItemWeakPointer = std::weak_ptr; inline uint qHash(const EntityItemPointer& a, uint seed) { return qHash(a.get(), seed); diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 617663f48a..4acc386333 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -14,12 +14,12 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement, EntityItemPointer existingEntity, - const EntityItemProperties& properties) : + const BoundingBoxRelatedProperties& newProperties) : _tree(tree), _existingEntity(existingEntity), _containingElement(containingElement), _containingElementCube(containingElement->getAACube()), - _properties(properties), + _newProperties(newProperties), _entityItemID(existingEntity->getEntityItemID()), _foundOld(false), _foundNew(false), @@ -44,83 +44,32 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree, _oldEntityCube = _existingEntity->getMaximumAACube(); _oldEntityBox = _oldEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds - // If the old properties doesn't contain the properties required to calculate a bounding box, - // get them from the existing entity. Registration point is required to correctly calculate - // the bounding box. - if (!_properties.registrationPointChanged()) { - _properties.setRegistrationPoint(_existingEntity->getRegistrationPoint()); - } - - // If the new properties has position OR dimension changes, but not both, we need to - // get the old property value and set it in our properties in order for our bounds - // calculations to work. - if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) { - glm::vec3 oldDimensions= _existingEntity->getDimensions(); - _properties.setDimensions(oldDimensions); - - if (_wantDebug) { - qCDebug(entities) << " ** setting properties dimensions - had position change, no dimension change **"; - } - - } - if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) { - glm::vec3 oldPosition= _existingEntity->getPosition(); - _properties.setPosition(oldPosition); - - if (_wantDebug) { - qCDebug(entities) << " ** setting properties position - had dimensions change, no position change **"; - } - } - - // 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 + // 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 same for both parts of the update - bool oldElementBestFit = _containingElement->bestFitBounds(_properties); - - // if we don't have bounds properties, then use our old clamped box to determine best fit - if (!_properties.containsBoundsProperties()) { - oldElementBestFit = _containingElement->bestFitBounds(_oldEntityBox); + bool oldElementBestFit = _containingElement->bestFitBounds(newProperties.getMaximumAACube()); - if (_wantDebug) { - qCDebug(entities) << " ** old Element best fit - no dimensions change, no position change **"; - } - - } - // 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. - if (!_properties.containsBoundsProperties() && !oldElementBestFit) { + if (!oldElementBestFit) { _newEntityCube = _oldEntityCube; _removeOld = true; // our properties are going to move us, so remember this for later processing if (_wantDebug) { qCDebug(entities) << " **** UNUSUAL CASE **** no changes, but not best fit... consider it a move.... **"; } - - - } else if (!_properties.containsBoundsProperties() || oldElementBestFit) { + } else { _foundOld = true; _newEntityCube = _oldEntityCube; _dontMove = true; if (_wantDebug) { - qCDebug(entities) << " **** TYPICAL NO MOVE CASE ****"; - qCDebug(entities) << " _properties.containsBoundsProperties():" << _properties.containsBoundsProperties(); - qCDebug(entities) << " oldElementBestFit:" << oldElementBestFit; - } - - } else { - _newEntityCube = _properties.getMaximumAACube(); - _removeOld = true; // our properties are going to move us, so remember this for later processing - - if (_wantDebug) { - qCDebug(entities) << " **** TYPICAL MOVE CASE ****"; + qCDebug(entities) << " **** TYPICAL NO MOVE CASE **** oldElementBestFit:" << oldElementBestFit; } } _newEntityBox = _newEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds - if (_wantDebug) { qCDebug(entities) << " _entityItemID:" << _entityItemID; qCDebug(entities) << " _containingElementCube:" << _containingElementCube; @@ -176,7 +125,7 @@ bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElementPointer element bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); - + // In Pre-recursion, we're generally deciding whether or not we want to recurse this // path of the tree. For this operation, we want to recurse the branch of the tree if // and of the following are true: @@ -185,7 +134,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { // // Note: it's often the case that the branch in question contains both the old entity // and the new entity. - + bool keepSearching = false; // assume we don't need to search any more bool subtreeContainsOld = subTreeContainsOldEntity(element); @@ -257,7 +206,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { qCDebug(entities) << " NEW TREE CASE...."; qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get(); qCDebug(entities) << " _containingElement=" << _containingElement.get(); - qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox); + qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)=" + << entityTreeElement->bestFitBounds(_newEntityBox); } // If this element is the best fit for the new entity properties, then add/or update it @@ -270,16 +220,9 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { EntityTreeElementPointer oldElement = _existingEntity->getElement(); // if we are the existing containing element, then we can just do the update of the entity properties if (entityTreeElement == oldElement) { - if (_wantDebug) { qCDebug(entities) << " *** This is the same OLD ELEMENT ***"; } - - // set the entity properties and mark our element as changed. - _existingEntity->setProperties(_properties); - if (_wantDebug) { - qCDebug(entities) << " *** set properties ***"; - } } else { // otherwise, this is an add case. if (oldElement) { @@ -290,11 +233,6 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { } entityTreeElement->addEntityItem(_existingEntity); _tree->setContainingElement(_entityItemID, entityTreeElement); - - _existingEntity->setProperties(_properties); // still need to update the properties! - if (_wantDebug) { - qCDebug(entities) << " *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***"; - } } _foundNew = true; // we found the new element _removeOld = false; // and it has already been removed from the old @@ -308,7 +246,6 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { qCDebug(entities) << "--------------------------------------------------"; } - return keepSearching; // if we haven't yet found it, keep looking } @@ -329,9 +266,9 @@ bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) { } // It's not OK to prune if we have the potential of deleting the original containig element. - // because if we prune the containing element then new might end up reallocating the same memory later + // because if we prune the containing element then new might end up reallocating the same memory later // and that will confuse our logic. - // + // // it's ok to prune if: // 1) we're not removing the old // 2) we are removing the old, but this subtree doesn't contain the old @@ -340,17 +277,17 @@ bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) { EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves } - + return keepSearching; // if we haven't yet found it, keep looking } -OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { +OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { // If we're getting called, it's because there was no child element at this index while recursing. // We only care if this happens while still searching for the new entity location. - // Check to see if + // Check to see if if (!_foundNew) { float childElementScale = element->getScale() / 2.0f; // all of our children will be half our scale - + // Note: because the entity's bounds might have been clamped to the domain. We want to check if the // bounds of the clamped box would fit in our child elements. It may be the case that the actual // bounds of the element would hang outside of the child elements cells. @@ -365,5 +302,5 @@ OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPo } } } - return NULL; + return NULL; } diff --git a/libraries/entities/src/UpdateEntityOperator.h b/libraries/entities/src/UpdateEntityOperator.h index 46322997f7..aac442d415 100644 --- a/libraries/entities/src/UpdateEntityOperator.h +++ b/libraries/entities/src/UpdateEntityOperator.h @@ -12,6 +12,7 @@ #ifndef hifi_UpdateEntityOperator_h #define hifi_UpdateEntityOperator_h +#include "BoundingBoxRelatedProperties.h" #include "EntitiesLogging.h" #include "EntityItem.h" #include "EntityItemProperties.h" @@ -21,7 +22,8 @@ class UpdateEntityOperator : public RecurseOctreeOperator { public: UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement, - EntityItemPointer existingEntity, const EntityItemProperties& properties); + EntityItemPointer existingEntity, const BoundingBoxRelatedProperties& newProperties); + ~UpdateEntityOperator(); virtual bool preRecursion(OctreeElementPointer element); @@ -32,7 +34,7 @@ private: EntityItemPointer _existingEntity; EntityTreeElementPointer _containingElement; AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element - EntityItemProperties _properties; + BoundingBoxRelatedProperties _newProperties; EntityItemID _entityItemID; bool _foundOld; bool _foundNew; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index b3723cf3b7..a813a37bfe 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -32,10 +32,13 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { return nullptr; } + SpatiallyNestableConstPointer constThisPointer = shared_from_this(); + SpatiallyNestablePointer thisPointer = std::const_pointer_cast(constThisPointer); // ermahgerd !!! + if (parent && parent->getID() == _parentID) { // parent pointer is up-to-date if (!_parentKnowsMe) { - parent->beParentOfChild(shared_from_this()); + parent->beParentOfChild(thisPointer); _parentKnowsMe = true; } return parent; @@ -43,7 +46,7 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { if (parent) { // we have a parent pointer but our _parentID doesn't indicate this parent. - parent->forgetChild(shared_from_this()); + parent->forgetChild(thisPointer); _parentKnowsMe = false; _parent.reset(); } @@ -53,17 +56,17 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const { _parent = parentFinder->find(_parentID); parent = _parent.lock(); if (parent) { - parent->beParentOfChild(shared_from_this()); + parent->beParentOfChild(thisPointer); _parentKnowsMe = true; } return parent; } -void SpatiallyNestable::beParentOfChild(SpatiallyNestableConstPointer newChild) const { +void SpatiallyNestable::beParentOfChild(SpatiallyNestablePointer newChild) const { _children[newChild->getID()] = newChild; } -void SpatiallyNestable::forgetChild(SpatiallyNestableConstPointer newChild) const { +void SpatiallyNestable::forgetChild(SpatiallyNestablePointer newChild) const { _children.remove(newChild->getID()); } @@ -153,3 +156,14 @@ const glm::vec3& SpatiallyNestable::getLocalScale() const { void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { _transform.setScale(scale); } + +QList SpatiallyNestable::getChildren() const { + QList children; + foreach (SpatiallyNestableWeakPointer childWP, _children.values()) { + SpatiallyNestablePointer child = childWP.lock(); + if (child) { + children << child; + } + } + return children; +} diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 7ba5493340..e0ee5bdb74 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -24,11 +24,21 @@ using SpatiallyNestableWeakConstPointer = std::weak_ptr using SpatiallyNestablePointer = std::shared_ptr; using SpatiallyNestableConstPointer = std::shared_ptr; -class SpatiallyNestable : public std::enable_shared_from_this { - +class NestableTypes { public: - SpatiallyNestable() : _transform() { } // XXX get rid of this one? - SpatiallyNestable(QUuid id) : _id(id), _transform() { } + using NestableType = enum NestableType_t { + Entity, + Avatar + }; +}; + +class SpatiallyNestable : public std::enable_shared_from_this { +public: + // SpatiallyNestable() : _transform() { } // XXX get rid of this one? + SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id) : + _nestableType(nestableType), + _id(id), + _transform() { } virtual ~SpatiallyNestable() { } virtual const QUuid& getID() const { return _id; } @@ -68,16 +78,20 @@ public: virtual const glm::vec3& getLocalScale() const; virtual void setLocalScale(const glm::vec3& scale); + QList getChildren() const; + NestableTypes::NestableType getNestableType() const { return _nestableType; } + protected: + NestableTypes::NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; QUuid _parentID; // what is this thing's transform relative to? quint16 _parentJointIndex; // which joint of the parent is this relative to? SpatiallyNestablePointer getParentPointer() const; mutable SpatiallyNestableWeakPointer _parent; - virtual void beParentOfChild(SpatiallyNestableConstPointer newChild) const; - virtual void forgetChild(SpatiallyNestableConstPointer newChild) const; - mutable QHash _children; + virtual void beParentOfChild(SpatiallyNestablePointer newChild) const; + virtual void forgetChild(SpatiallyNestablePointer newChild) const; + mutable QHash _children; private: Transform _transform; // this is to be combined with parent's world-transform to produce this' world-transform.