be more careful about fixing up entities which arrived before their parents

This commit is contained in:
Seth Alves 2017-05-19 12:13:43 -07:00
parent 735e4b7d05
commit 936d0e2d50

View file

@ -122,7 +122,7 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
_simulation->addEntity(entity); _simulation->addEntity(entity);
} }
if (!entity->isParentIDValid()) { if (!entity->getParentID().isNull()) {
QWriteLocker locker(&_missingParentLock); QWriteLocker locker(&_missingParentLock);
_missingParent.append(entity); _missingParent.append(entity);
} }
@ -1212,73 +1212,61 @@ void EntityTree::entityChanged(EntityItemPointer entity) {
void EntityTree::fixupMissingParents() { void EntityTree::fixupMissingParents() {
MovingEntitiesOperator moveOperator(getThisPointer()); MovingEntitiesOperator moveOperator(getThisPointer());
QList<EntityItemPointer> missingParents; QWriteLocker locker(&_missingParentLock);
{ QMutableVectorIterator<EntityItemWeakPointer> iter(_missingParent);
QWriteLocker locker(&_missingParentLock); while (iter.hasNext()) {
QMutableVectorIterator<EntityItemWeakPointer> iter(_missingParent); EntityItemWeakPointer entityWP = iter.next();
while (iter.hasNext()) { EntityItemPointer entity = entityWP.lock();
EntityItemWeakPointer entityWP = iter.next(); if (!entity) {
EntityItemPointer entity = entityWP.lock(); // entity was deleted before we found its parent
if (entity) { iter.remove();
if (entity->isParentIDValid()) { }
iter.remove(); bool queryAACubeSuccess;
} else { AACube newCube = entity->getQueryAACube(queryAACubeSuccess);
missingParents.append(entity); if (queryAACubeSuccess) {
} // make sure queryAACube encompasses maxAACube
} else { bool maxAACubeSuccess;
// entity was deleted before we found its parent. AACube maxAACube = entity->getMaximumAACube(maxAACubeSuccess);
iter.remove(); if (maxAACubeSuccess && !newCube.contains(maxAACube)) {
newCube = maxAACube;
} }
} }
}
for (EntityItemPointer entity : missingParents) { bool doMove = false;
if (entity) { if (entity->isParentIDValid()) {
bool queryAACubeSuccess; iter.remove(); // this entity is all hooked up; we can remove it from the list
AACube newCube = entity->getQueryAACube(queryAACubeSuccess); // this entity's parent was previously not known, and now is. Update its location in the EntityTree...
if (queryAACubeSuccess) { doMove = true;
// make sure queryAACube encompasses maxAACube // the bounds on the render-item may need to be updated, the rigid body in the physics engine may
bool maxAACubeSuccess; // need to be moved.
AACube maxAACube = entity->getMaximumAACube(maxAACubeSuccess); entity->markDirtyFlags(Simulation::DIRTY_MOTION_TYPE |
if (maxAACubeSuccess && !newCube.contains(maxAACube)) { Simulation::DIRTY_COLLISION_GROUP |
newCube = maxAACube; Simulation::DIRTY_TRANSFORM);
entityChanged(entity);
entity->forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer descendantEntity = std::static_pointer_cast<EntityItem>(object);
descendantEntity->markDirtyFlags(Simulation::DIRTY_MOTION_TYPE |
Simulation::DIRTY_COLLISION_GROUP |
Simulation::DIRTY_TRANSFORM);
entityChanged(descendantEntity);
} }
});
entity->locationChanged(true);
} else if (getIsServer() && _avatarIDs.contains(entity->getParentID())) {
// this is a child of an avatar, which the entity server will never have
// a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves.
if (!_childrenOfAvatars.contains(entity->getParentID())) {
_childrenOfAvatars[entity->getParentID()] = QSet<EntityItemID>();
} }
_childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID();
doMove = true;
iter.remove(); // and pull it out of the list
}
bool doMove = false; if (queryAACubeSuccess && doMove) {
if (entity->isParentIDValid()) { moveOperator.addEntityToMoveList(entity, newCube);
// this entity's parent was previously not known, and now is. Update its location in the EntityTree... entity->markAncestorMissing(false);
doMove = true;
// the bounds on the render-item may need to be updated, the rigid body in the physics engine may
// need to be moved.
entity->markDirtyFlags(Simulation::DIRTY_MOTION_TYPE |
Simulation::DIRTY_COLLISION_GROUP |
Simulation::DIRTY_TRANSFORM);
entityChanged(entity);
entity->forEachDescendant([&](SpatiallyNestablePointer object) {
if (object->getNestableType() == NestableType::Entity) {
EntityItemPointer descendantEntity = std::static_pointer_cast<EntityItem>(object);
descendantEntity->markDirtyFlags(Simulation::DIRTY_MOTION_TYPE |
Simulation::DIRTY_COLLISION_GROUP |
Simulation::DIRTY_TRANSFORM);
entityChanged(descendantEntity);
}
});
entity->locationChanged(true);
} else if (getIsServer() && _avatarIDs.contains(entity->getParentID())) {
// this is a child of an avatar, which the entity server will never have
// a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves.
if (!_childrenOfAvatars.contains(entity->getParentID())) {
_childrenOfAvatars[entity->getParentID()] = QSet<EntityItemID>();
}
_childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID();
doMove = true;
}
if (queryAACubeSuccess && doMove) {
moveOperator.addEntityToMoveList(entity, newCube);
entity->markAncestorMissing(false);
}
} }
} }