mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 04:24:47 +02:00
hacking on more support for virtual entities
This commit is contained in:
parent
2c5209d1e7
commit
5e5af9ceea
6 changed files with 277 additions and 35 deletions
|
@ -42,6 +42,11 @@ bool EntityTypes::registerEntityTypeName(EntityType_t entityType, const QString&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityItem* EntityTypes::constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
|
return new EntityItem(entityID, properties); // for now, needs to support registration of constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool registered = EntityTypes::registerEntityTypeName(EntityTypes::Base, "Base")
|
bool registered = EntityTypes::registerEntityTypeName(EntityTypes::Base, "Base")
|
||||||
&& EntityTypes::registerEntityTypeName(EntityTypes::Model, "Model"); // TODO: move this to model subclass
|
&& EntityTypes::registerEntityTypeName(EntityTypes::Model, "Model"); // TODO: move this to model subclass
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
|
|
||||||
class EntityItem;
|
class EntityItem;
|
||||||
|
class EntityItemID;
|
||||||
class EntityEditPacketSender;
|
class EntityEditPacketSender;
|
||||||
class EntityItemProperties;
|
class EntityItemProperties;
|
||||||
class EntitysScriptingInterface;
|
class EntitysScriptingInterface;
|
||||||
|
@ -73,7 +74,8 @@ public:
|
||||||
} EntityType_t;
|
} EntityType_t;
|
||||||
|
|
||||||
static const QString& getEntityTypeName(EntityType_t entityType);
|
static const QString& getEntityTypeName(EntityType_t entityType);
|
||||||
static bool registerEntityTypeName(EntityType_t entityType, const QString& name);
|
static bool registerEntityType(EntityType_t entityType, const QString& name);
|
||||||
|
static EntityItem* constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
private:
|
private:
|
||||||
static QHash<EntityType_t, QString> _typeNameHash;
|
static QHash<EntityType_t, QString> _typeNameHash;
|
||||||
};
|
};
|
||||||
|
@ -122,11 +124,14 @@ public:
|
||||||
|
|
||||||
glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
||||||
glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
||||||
|
AACube getAACube() const { return AACube(getMinimumPoint(), getSize()); } /// AACube in domain scale units (0.0 - 1.0)
|
||||||
void debugDump() const;
|
void debugDump() const;
|
||||||
|
|
||||||
// properties of all entities
|
// properties of all entities
|
||||||
|
EntityTypes::EntityType_t getType() const { return _type; }
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
float getRadius() const { return _radius; }
|
float getRadius() const { return _radius; }
|
||||||
|
glm::vec3 getSize() const { return glm::vec3(_radius, _radius, _radius) * 2.0f; }
|
||||||
const glm::quat& getRotation() const { return _rotation; }
|
const glm::quat& getRotation() const { return _rotation; }
|
||||||
bool getShouldBeDeleted() const { return _shouldBeDeleted; }
|
bool getShouldBeDeleted() const { return _shouldBeDeleted; }
|
||||||
|
|
||||||
|
@ -134,6 +139,9 @@ public:
|
||||||
void setPosition(const glm::vec3& value) { _position = value; _positionChanged = true; }
|
void setPosition(const glm::vec3& value) { _position = value; _positionChanged = true; }
|
||||||
void setRadius(float value) { _radius = value; _radiusChanged = true; }
|
void setRadius(float value) { _radius = value; _radiusChanged = true; }
|
||||||
void setShouldBeDeleted(bool shouldBeDeleted) { _shouldBeDeleted = shouldBeDeleted; _shouldBeDeletedChanged = true; }
|
void setShouldBeDeleted(bool shouldBeDeleted) { _shouldBeDeleted = shouldBeDeleted; _shouldBeDeletedChanged = true; }
|
||||||
|
|
||||||
|
// NOTE: how do we handle _defaultSettings???
|
||||||
|
bool containsBoundsProperties() const { return (_positionChanged || _radiusChanged); }
|
||||||
|
|
||||||
#if 0 // def HIDE_SUBCLASS_METHODS
|
#if 0 // def HIDE_SUBCLASS_METHODS
|
||||||
// properties we want to move to just models and particles
|
// properties we want to move to just models and particles
|
||||||
|
@ -161,6 +169,7 @@ private:
|
||||||
bool _idSet;
|
bool _idSet;
|
||||||
quint64 _lastEdited;
|
quint64 _lastEdited;
|
||||||
|
|
||||||
|
EntityTypes::EntityType_t _type;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
float _radius;
|
float _radius;
|
||||||
glm::quat _rotation;
|
glm::quat _rotation;
|
||||||
|
@ -311,7 +320,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// attributes applicable to all entity types
|
// attributes applicable to all entity types
|
||||||
quint32 getType() const { return _type; }
|
EntityTypes::EntityType_t getType() const { return _type; }
|
||||||
const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0)
|
const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0)
|
||||||
void setPosition(const glm::vec3& value) { _position = value; } /// set position in domain scale units (0.0 - 1.0)
|
void setPosition(const glm::vec3& value) { _position = value; } /// set position in domain scale units (0.0 - 1.0)
|
||||||
|
|
||||||
|
@ -378,7 +387,7 @@ protected:
|
||||||
static std::map<uint32_t,uint32_t> _tokenIDsToIDs;
|
static std::map<uint32_t,uint32_t> _tokenIDsToIDs;
|
||||||
|
|
||||||
quint32 _id;
|
quint32 _id;
|
||||||
quint32 _type;
|
EntityTypes::EntityType_t _type;
|
||||||
uint32_t _creatorTokenID;
|
uint32_t _creatorTokenID;
|
||||||
bool _newlyCreated;
|
bool _newlyCreated;
|
||||||
quint64 _lastUpdated;
|
quint64 _lastUpdated;
|
||||||
|
|
|
@ -218,17 +218,205 @@ void EntityTree::storeEntity(const EntityItem& model, const SharedNodePointer& s
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
|
||||||
EntityItem updateItem(entityID);
|
|
||||||
|
|
||||||
bool wantDebug = false;
|
/// Give an EntityItemID and EntityItemProperties, this will either find the correct entity that already exists
|
||||||
if (wantDebug) {
|
/// in the tree or it will create a new entity of the type specified by the properties and return that item.
|
||||||
qDebug() << "EntityTree::updateEntity(entityID, properties) line:" << __LINE__ << "updateItem:";
|
EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
updateItem.debugDump();
|
EntityItem* result = NULL;
|
||||||
|
|
||||||
|
// we need to first see if we already have the entity in our tree by finding the containing element of the entity
|
||||||
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
|
if (containingElement) {
|
||||||
|
result = containingElement->getEntityWithEntityItemID(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the element does not exist, then create a new one of the specified type...
|
||||||
|
if (!result) {
|
||||||
|
EntityTypes::EntityType_t type = properties.getType();
|
||||||
|
result = EntityTypes::constructEntityItem(type, entityID, properties);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||||
|
public:
|
||||||
|
UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement,
|
||||||
|
EntityItem* oldEntity, const EntityItemProperties& properties);
|
||||||
|
virtual bool PreRecursion(OctreeElement* element);
|
||||||
|
virtual bool PostRecursion(OctreeElement* element);
|
||||||
|
virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||||
|
private:
|
||||||
|
EntityTree* _tree;
|
||||||
|
const EntityItem* _newEntity;
|
||||||
|
const EntityItem* _oldEntity;
|
||||||
|
EntityTreeElement* _containingElement;
|
||||||
|
bool _foundOld;
|
||||||
|
bool _foundNew;
|
||||||
|
quint64 _changeTime;
|
||||||
|
AABox _oldEntityCube;
|
||||||
|
AABox _newEntityCube;
|
||||||
|
|
||||||
|
bool subTreeContainsOldEntity(OctreeElement* element);
|
||||||
|
bool subTreeContainsNewEntity(OctreeElement* element);
|
||||||
|
};
|
||||||
|
|
||||||
|
UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
||||||
|
EntityTreeElement* containingElement,
|
||||||
|
EntityItem* oldEntity,
|
||||||
|
const EntityItemProperties& properties) :
|
||||||
|
_tree(tree),
|
||||||
|
_newEntity(NULL),
|
||||||
|
_oldEntity(oldEntity),
|
||||||
|
_containingElement(containingElement),
|
||||||
|
_foundOld(false),
|
||||||
|
_foundNew(false),
|
||||||
|
_changeTime(usecTimestampNow())
|
||||||
|
{
|
||||||
|
// caller must have verified existence of containingElement and oldEntity
|
||||||
|
assert(_containingElement && _oldEntity);
|
||||||
|
|
||||||
|
_oldEntityCube = _oldEntity->getAACube();
|
||||||
|
|
||||||
|
// 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
|
||||||
|
if (!properties.containsBoundsProperties() || _containingElement->bestFitBounds(properties)) {
|
||||||
|
_foundOld = true;
|
||||||
|
_newEntityCube = _oldEntityCube;
|
||||||
|
} else {
|
||||||
|
_newEntityCube = _oldEntity->getAACube();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// does this model tree element contain the old model
|
||||||
|
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
|
||||||
|
bool containsEntity = false;
|
||||||
|
|
||||||
|
// If we don't have an old model, then we don't contain the model, otherwise
|
||||||
|
// check the bounds
|
||||||
|
if (_oldEntity) {
|
||||||
|
AACube elementCube = element->getAACube();
|
||||||
|
AACube modelCube = _oldEntity->getAACube();
|
||||||
|
containsEntity = elementCube.contains(modelCube);
|
||||||
|
}
|
||||||
|
return containsEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
|
||||||
|
AACube elementCube = element->getAACube();
|
||||||
|
AACube modelCube = _newEntity.getAACube();
|
||||||
|
return elementCube.contains(modelCube);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
||||||
|
EntityTreeElement* modelTreeElement = static_cast<EntityTreeElement*>(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:
|
||||||
|
// * We have not yet found the old model, and this branch contains our old model
|
||||||
|
// * We have not yet found the new model, and this branch contains our new model
|
||||||
|
//
|
||||||
|
// Note: it's often the case that the branch in question contains both the old model
|
||||||
|
// and the new model.
|
||||||
|
|
||||||
|
bool keepSearching = false; // assume we don't need to search any more
|
||||||
|
|
||||||
|
// If we haven't yet found the old model, and this subTreeContains our old
|
||||||
|
// model, then we need to keep searching.
|
||||||
|
if (!_foundOld && subTreeContainsOldEntity(element)) {
|
||||||
|
|
||||||
|
// If this is the element we're looking for, then ask it to remove the old model
|
||||||
|
// and we can stop searching.
|
||||||
|
if (modelTreeElement == _containingElement) {
|
||||||
|
|
||||||
|
// If the containgElement IS NOT the best fit for the new model properties
|
||||||
|
// then we need to remove it, and the updateEntity below will store it in the
|
||||||
|
// correct element.
|
||||||
|
if (!_containingElement->bestFitEntityBounds(&_newEntity)) {
|
||||||
|
modelTreeElement->removeEntityWithEntityItemID(_newEntity.getEntityItemID());
|
||||||
|
|
||||||
|
// If we haven't yet found the new location, then we need to
|
||||||
|
// make sure to remove our model to element map, because for
|
||||||
|
// now we're not in that map
|
||||||
|
if (!_foundNew) {
|
||||||
|
_tree->setContainingElement(_newEntity.getEntityItemID(), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_foundOld = true;
|
||||||
|
} else {
|
||||||
|
// if this isn't the element we're looking for, then keep searching
|
||||||
|
keepSearching = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't yet found the new model, and this subTreeContains our new
|
||||||
|
// model, then we need to keep searching.
|
||||||
|
if (!_foundNew && subTreeContainsNewEntity(element)) {
|
||||||
|
|
||||||
|
// Note: updateEntity() will only operate on correctly found models and/or add them
|
||||||
|
// to the element if they SHOULD be stored there.
|
||||||
|
if (modelTreeElement->updateEntity(_newEntity)) {
|
||||||
|
//qDebug() << "UpdateEntityOperator::PreRecursion()... model was updated!";
|
||||||
|
_foundNew = true;
|
||||||
|
// NOTE: don't change the keepSearching here, if it came in here
|
||||||
|
// false then we stay false, if it came in here true, then it
|
||||||
|
// means we're still searching for our old model and this branch
|
||||||
|
// contains our old model. In which case we want to keep searching.
|
||||||
|
|
||||||
|
} else {
|
||||||
|
keepSearching = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keepSearching; // if we haven't yet found it, keep looking
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdateEntityOperator::PostRecursion(OctreeElement* element) {
|
||||||
|
// Post-recursion is the unwinding process. For this operation, while we
|
||||||
|
// unwind we want to mark the path as being dirty if we changed it below.
|
||||||
|
// We might have two paths, one for the old model and one for the new model.
|
||||||
|
bool keepSearching = !_foundOld || !_foundNew;
|
||||||
|
|
||||||
|
// As we unwind, if we're in either of these two paths, we mark our element
|
||||||
|
// as dirty.
|
||||||
|
if ((_foundOld && subTreeContainsOldEntity(element)) ||
|
||||||
|
(_foundNew && subTreeContainsNewEntity(element))) {
|
||||||
|
element->markWithChangedTime();
|
||||||
|
}
|
||||||
|
return keepSearching; // if we haven't yet found it, keep looking
|
||||||
|
}
|
||||||
|
|
||||||
|
OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* 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 model location.
|
||||||
|
// Check to see if
|
||||||
|
if (!_foundNew) {
|
||||||
|
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntity.getAACube());
|
||||||
|
|
||||||
|
if (childIndex == indexOfChildContainingNewEntity) {
|
||||||
|
return element->addChildAtIndex(childIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: This should only be called on entities that are known to exist. If the entity can not be found, the method
|
||||||
|
// will exit without any changes to tree state
|
||||||
|
//
|
||||||
|
// NOTE: If the properties contain position/scale/rotation, then there is a potential that the entity could need to
|
||||||
|
// move to a different EntityTreeElement, otherwise it will not move. If the entity can not move, then the dirty path
|
||||||
|
// can be determined to just be the path to the entity
|
||||||
|
void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
|
EntityItem* updateItem = NULL;
|
||||||
|
|
||||||
|
bool entityMightMove = properties.containsBoundsProperties();
|
||||||
|
|
||||||
// since the properties might not be complete, they may only contain some values,
|
// since the properties might not be complete, they may only contain some values,
|
||||||
// we need to first see if we already have the model in our tree, and make a copy of
|
// we need to first see if we already have the entity in our tree, and make a copy of
|
||||||
// its existing properties first
|
// its existing properties first
|
||||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
|
|
||||||
|
@ -259,6 +447,8 @@ void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updateItem) {
|
||||||
updateItem.setProperties(properties);
|
updateItem.setProperties(properties);
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
|
|
|
@ -50,6 +50,8 @@ public:
|
||||||
virtual bool rootElementHasData() const { return true; }
|
virtual bool rootElementHasData() const { return true; }
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
|
EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
void storeEntity(const EntityItem& model, const SharedNodePointer& senderNode = SharedNodePointer());
|
void storeEntity(const EntityItem& model, const SharedNodePointer& senderNode = SharedNodePointer());
|
||||||
void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||||
void addEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
void addEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||||
|
|
|
@ -175,14 +175,30 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::containsEntityBounds(const EntityItem* entity) const {
|
bool EntityTreeElement::containsEntityBounds(const EntityItem* entity) const {
|
||||||
glm::vec3 clampedMin = glm::clamp(entity->getMinimumPoint(), 0.0f, 1.0f);
|
return containsBounds(entity->getMinimumPoint(), entity->getMaximumPoint());
|
||||||
glm::vec3 clampedMax = glm::clamp(entity->getMaximumPoint(), 0.0f, 1.0f);
|
|
||||||
return _cube.contains(clampedMin) && _cube.contains(clampedMax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const {
|
bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const {
|
||||||
glm::vec3 clampedMin = glm::clamp(entity->getMinimumPoint(), 0.0f, 1.0f);
|
return bestFitBounds(entity->getMinimumPoint(), entity->getMaximumPoint());
|
||||||
glm::vec3 clampedMax = glm::clamp(entity->getMaximumPoint(), 0.0f, 1.0f);
|
}
|
||||||
|
|
||||||
|
bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const {
|
||||||
|
return containsBounds(properties.getMinimumPoint(), properties.getMaximumPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) const {
|
||||||
|
return bestFitBounds(properties.getMinimumPoint(), properties.getMaximumPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTreeElement::containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const {
|
||||||
|
glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, 1.0f);
|
||||||
|
glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, 1.0f);
|
||||||
|
return _cube.contains(clampedMin) && _cube.contains(clampedMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const {
|
||||||
|
glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, 1.0f);
|
||||||
|
glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, 1.0f);
|
||||||
if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) {
|
if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) {
|
||||||
int childForMinimumPoint = getMyChildContainingPoint(clampedMin);
|
int childForMinimumPoint = getMyChildContainingPoint(clampedMin);
|
||||||
int childForMaximumPoint = getMyChildContainingPoint(clampedMax);
|
int childForMaximumPoint = getMyChildContainingPoint(clampedMax);
|
||||||
|
@ -200,6 +216,7 @@ bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EntityTreeElement::update(EntityTreeUpdateArgs& args) {
|
void EntityTreeElement::update(EntityTreeUpdateArgs& args) {
|
||||||
args._totalElements++;
|
args._totalElements++;
|
||||||
// update our contained entities
|
// update our contained entities
|
||||||
|
@ -246,7 +263,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
|
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
|
||||||
bool somethingIntersected = false;
|
bool somethingIntersected = false;
|
||||||
while(entityItr != entityEnd) {
|
while(entityItr != entityEnd) {
|
||||||
EntityItem& entity = (*entityItr);
|
EntityItem* entity = (*entityItr);
|
||||||
|
|
||||||
AACube entityCube = entity.getAACube();
|
AACube entityCube = entity.getAACube();
|
||||||
float localDistance;
|
float localDistance;
|
||||||
|
@ -371,14 +388,14 @@ bool EntityTreeElement::updateEntity(const EntityItem& entity) {
|
||||||
// (guaranteed that num entities per elemen is small?)
|
// (guaranteed that num entities per elemen is small?)
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
EntityItem& thisEntity = (*_entityItems)[i];
|
EntityItem* thisEntity = (*_entityItems)[i];
|
||||||
if (thisEntity.getID() == entity.getID()) {
|
if (thisEntity->getID() == entity.getID()) {
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << "found entity with id";
|
qDebug() << "found entity with id";
|
||||||
}
|
}
|
||||||
int difference = thisEntity.getLastUpdated() - entity.getLastUpdated();
|
int difference = thisEntity->getLastUpdated() - entity.getLastUpdated();
|
||||||
bool changedOnServer = thisEntity.getLastEdited() <= entity.getLastEdited();
|
bool changedOnServer = thisEntity->getLastEdited() <= entity.getLastEdited();
|
||||||
bool localOlder = thisEntity.getLastUpdated() < entity.getLastUpdated();
|
bool localOlder = thisEntity->getLastUpdated() < entity.getLastUpdated();
|
||||||
if (changedOnServer || localOlder) {
|
if (changedOnServer || localOlder) {
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug("local entity [id:%d] %s and %s than server entity by %d, entity.isNewlyCreated()=%s",
|
qDebug("local entity [id:%d] %s and %s than server entity by %d, entity.isNewlyCreated()=%s",
|
||||||
|
@ -387,7 +404,7 @@ bool EntityTreeElement::updateEntity(const EntityItem& entity) {
|
||||||
difference, debug::valueOf(entity.isNewlyCreated()) );
|
difference, debug::valueOf(entity.isNewlyCreated()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
thisEntity.copyChangedProperties(entity);
|
thisEntity->copyChangedProperties(entity);
|
||||||
markWithChangedTime();
|
markWithChangedTime();
|
||||||
|
|
||||||
// seems like we shouldn't need this
|
// seems like we shouldn't need this
|
||||||
|
@ -421,30 +438,30 @@ void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args)
|
||||||
bool wantDebug = false;
|
bool wantDebug = false;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
EntityItem& thisEntity = (*_entityItems)[i];
|
EntityItem* thisEntity = (*_entityItems)[i];
|
||||||
|
|
||||||
if (!args->creatorTokenFound) {
|
if (!args->creatorTokenFound) {
|
||||||
// first, we're looking for matching creatorTokenIDs, if we find that, then we fix it to know the actual ID
|
// first, we're looking for matching creatorTokenIDs, if we find that, then we fix it to know the actual ID
|
||||||
if (thisEntity.getCreatorTokenID() == args->creatorTokenID) {
|
if (thisEntity->getCreatorTokenID() == args->creatorTokenID) {
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << "EntityTreeElement::updateEntityItemID()... found the entity... updating it's ID... "
|
qDebug() << "EntityTreeElement::updateEntityItemID()... found the entity... updating it's ID... "
|
||||||
<< "creatorTokenID=" << args->creatorTokenID
|
<< "creatorTokenID=" << args->creatorTokenID
|
||||||
<< "entityID=" << args->entityID;
|
<< "entityID=" << args->entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
thisEntity.setID(args->entityID);
|
thisEntity->setID(args->entityID);
|
||||||
args->creatorTokenFound = true;
|
args->creatorTokenFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're in an isViewing tree, we also need to look for an kill any viewed entities
|
// if we're in an isViewing tree, we also need to look for an kill any viewed entities
|
||||||
if (!args->viewedEntityFound && args->isViewing) {
|
if (!args->viewedEntityFound && args->isViewing) {
|
||||||
if (thisEntity.getCreatorTokenID() == UNKNOWN_ENTITY_TOKEN && thisEntity.getID() == args->entityID) {
|
if (thisEntity->getCreatorTokenID() == UNKNOWN_ENTITY_TOKEN && thisEntity->getID() == args->entityID) {
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
qDebug() << "EntityTreeElement::updateEntityItemID()... VIEWED entity FOUND??? "
|
qDebug() << "EntityTreeElement::updateEntityItemID()... VIEWED entity FOUND??? "
|
||||||
<< "args->creatorTokenID=" << args->creatorTokenID
|
<< "args->creatorTokenID=" << args->creatorTokenID
|
||||||
<< "thisEntity.getCreatorTokenID()=" << thisEntity.getCreatorTokenID()
|
<< "thisEntity->getCreatorTokenID()=" << thisEntity->getCreatorTokenID()
|
||||||
<< "args->entityID=" << args->entityID;
|
<< "args->entityID=" << args->entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +481,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const
|
||||||
float closestEntityDistance = FLT_MAX;
|
float closestEntityDistance = FLT_MAX;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
float distanceToEntity = glm::distance(position, (*_entityItems)[i].getPosition());
|
float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPosition());
|
||||||
if (distanceToEntity < closestEntityDistance) {
|
if (distanceToEntity < closestEntityDistance) {
|
||||||
closestEntity = &(*_entityItems)[i];
|
closestEntity = &(*_entityItems)[i];
|
||||||
}
|
}
|
||||||
|
@ -506,8 +523,8 @@ const EntityItem* EntityTreeElement::getEntityWithID(uint32_t id) const {
|
||||||
const EntityItem* foundEntity = NULL;
|
const EntityItem* foundEntity = NULL;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
if ((*_entityItems)[i].getID() == id) {
|
if ((*_entityItems)[i]->getID() == id) {
|
||||||
foundEntity = &(*_entityItems)[i];
|
foundEntity = (*_entityItems)[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,12 +532,23 @@ const EntityItem* EntityTreeElement::getEntityWithID(uint32_t id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
|
const EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
|
||||||
// NOTE: this lookup is O(N) but maybe we don't care? (guaranteed that num entities per elemen is small?)
|
|
||||||
const EntityItem* foundEntity = NULL;
|
const EntityItem* foundEntity = NULL;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
if ((*_entityItems)[i].getEntityItemID() == id) {
|
if ((*_entityItems)[i]->getEntityItemID() == id) {
|
||||||
foundEntity = &(*_entityItems)[i];
|
foundEntity = (*_entityItems)[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) {
|
||||||
|
EntityItem* foundEntity = NULL;
|
||||||
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
|
if ((*_entityItems)[i]->getEntityItemID() == id) {
|
||||||
|
foundEntity = (*_entityItems)[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,7 +559,7 @@ bool EntityTreeElement::removeEntityWithID(uint32_t id) {
|
||||||
bool foundEntity = false;
|
bool foundEntity = false;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
if ((*_entityItems)[i].getID() == id) {
|
if ((*_entityItems)[i]->getID() == id) {
|
||||||
foundEntity = true;
|
foundEntity = true;
|
||||||
_entityItems->removeAt(i);
|
_entityItems->removeAt(i);
|
||||||
|
|
||||||
|
@ -545,7 +573,7 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
|
||||||
bool foundEntity = false;
|
bool foundEntity = false;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
if ((*_entityItems)[i].getEntityItemID() == id) {
|
if ((*_entityItems)[i]->getEntityItemID() == id) {
|
||||||
foundEntity = true;
|
foundEntity = true;
|
||||||
_entityItems->removeAt(i);
|
_entityItems->removeAt(i);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -139,12 +139,20 @@ public:
|
||||||
const EntityItem* getEntityWithID(uint32_t id) const;
|
const EntityItem* getEntityWithID(uint32_t id) const;
|
||||||
const EntityItem* getEntityWithEntityItemID(const EntityItemID& id) const;
|
const EntityItem* getEntityWithEntityItemID(const EntityItemID& id) const;
|
||||||
|
|
||||||
|
EntityItem* getEntityWithEntityItemID(const EntityItemID& id);
|
||||||
|
|
||||||
bool removeEntityWithID(uint32_t id);
|
bool removeEntityWithID(uint32_t id);
|
||||||
bool removeEntityWithEntityItemID(const EntityItemID& id);
|
bool removeEntityWithEntityItemID(const EntityItemID& id);
|
||||||
|
|
||||||
bool containsEntityBounds(const EntityItem* entity) const;
|
bool containsEntityBounds(const EntityItem* entity) const;
|
||||||
bool bestFitEntityBounds(const EntityItem* entity) const;
|
bool bestFitEntityBounds(const EntityItem* entity) const;
|
||||||
|
|
||||||
|
bool containsBounds(const EntityItemProperties& properties) const;
|
||||||
|
bool bestFitBounds(const EntityItemProperties& properties) const;
|
||||||
|
|
||||||
|
bool containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||||
|
bool bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void init(unsigned char * octalCode);
|
virtual void init(unsigned char * octalCode);
|
||||||
EntityTree* _myTree;
|
EntityTree* _myTree;
|
||||||
|
|
Loading…
Reference in a new issue