trying to fix entity editing bugs, needs testing

This commit is contained in:
SamGondelman 2017-08-29 18:14:27 -07:00 committed by Andrew Meadows
parent 6c066605cd
commit 0ad5f47bfd
8 changed files with 45 additions and 18 deletions

View file

@ -12,6 +12,7 @@
#include "EntityPriorityQueue.h" #include "EntityPriorityQueue.h"
const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f; const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f;
const float PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY = 1.0f;
void ConicalView::set(const ViewFrustum& viewFrustum) { void ConicalView::set(const ViewFrustum& viewFrustum) {
// The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part. // The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.

View file

@ -40,12 +40,14 @@ private:
class PrioritizedEntity { class PrioritizedEntity {
public: public:
static const float DO_NOT_SEND; static const float DO_NOT_SEND;
static const float WHEN_IN_DOUBT_PRIORITY;
PrioritizedEntity(EntityItemPointer entity, float priority) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority) {} PrioritizedEntity(EntityItemPointer entity, float priority, bool forceSend = false) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority), _forceSend(forceSend) {}
float updatePriority(const ConicalView& view); float updatePriority(const ConicalView& view);
EntityItemPointer getEntity() const { return _weakEntity.lock(); } EntityItemPointer getEntity() const { return _weakEntity.lock(); }
EntityItem* getRawEntityPointer() const { return _rawEntityPointer; } EntityItem* getRawEntityPointer() const { return _rawEntityPointer; }
float getPriority() const { return _priority; } float getPriority() const { return _priority; }
bool shouldForceSend() const { return _forceSend; }
class Compare { class Compare {
public: public:
@ -57,6 +59,7 @@ private:
EntityItemWeakPointer _weakEntity; EntityItemWeakPointer _weakEntity;
EntityItem* _rawEntityPointer; EntityItem* _rawEntityPointer;
float _priority; float _priority;
bool _forceSend;
}; };
using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector<PrioritizedEntity>, PrioritizedEntity::Compare >; using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector<PrioritizedEntity>, PrioritizedEntity::Compare >;

View file

@ -22,6 +22,7 @@
EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) : EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node) :
OctreeSendThread(myServer, node) OctreeSendThread(myServer, node)
{ {
connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::editingEntityPointer, this, &EntityTreeSendThread::editingEntityPointer, Qt::QueuedConnection);
connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::deletingEntityPointer, this, &EntityTreeSendThread::deletingEntityPointer, Qt::QueuedConnection); connect(std::static_pointer_cast<EntityTree>(myServer->getOctree()).get(), &EntityTree::deletingEntityPointer, this, &EntityTreeSendThread::deletingEntityPointer, Qt::QueuedConnection);
} }
@ -108,29 +109,29 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
// Re-add elements from previous traversal if they still need to be sent // Re-add elements from previous traversal if they still need to be sent
while (!prevSendQueue.empty()) { while (!prevSendQueue.empty()) {
EntityItemPointer entity = prevSendQueue.top().getEntity(); EntityItemPointer entity = prevSendQueue.top().getEntity();
bool forceSend = prevSendQueue.top().shouldForceSend();
prevSendQueue.pop(); prevSendQueue.pop();
if (entity) { if (entity) {
bool success = false; bool success = false;
AACube cube = entity->getQueryAACube(success); AACube cube = entity->getQueryAACube(success);
if (success) { if (success) {
if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { if (forceSend || _traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
float priority = _conicalView.computePriority(cube); float priority = _conicalView.computePriority(cube);
if (priority != PrioritizedEntity::DO_NOT_SEND) { if (forceSend || priority != PrioritizedEntity::DO_NOT_SEND) {
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(), float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
cube, cube,
_traversal.getCurrentRootSizeScale(), _traversal.getCurrentRootSizeScale(),
lodLevelOffset); lodLevelOffset);
// Only send entities if they are large enough to see // Only send entities if they are large enough to see, or we need to update them to be out of view
if (renderAccuracy > 0.0f) { if (forceSend || renderAccuracy > 0.0f) {
_sendQueue.push(PrioritizedEntity(entity, priority)); _sendQueue.push(PrioritizedEntity(entity, priority));
_entitiesInQueue.insert(entity.get()); _entitiesInQueue.insert(entity.get());
} }
} }
} }
} else { } else {
const float WHEN_IN_DOUBT_PRIORITY = 1.0f; _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
_sendQueue.push(PrioritizedEntity(entity, WHEN_IN_DOUBT_PRIORITY));
_entitiesInQueue.insert(entity.get()); _entitiesInQueue.insert(entity.get());
} }
} }
@ -274,8 +275,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
} }
} }
} else { } else {
const float WHEN_IN_DOUBT_PRIORITY = 1.0f; _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
_sendQueue.push(PrioritizedEntity(entity, WHEN_IN_DOUBT_PRIORITY));
_entitiesInQueue.insert(entity.get()); _entitiesInQueue.insert(entity.get());
} }
}); });
@ -310,8 +310,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
} }
} }
} else { } else {
const float WHEN_IN_DOUBT_PRIORITY = 1.0f; _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
_sendQueue.push(PrioritizedEntity(entity, WHEN_IN_DOUBT_PRIORITY));
_entitiesInQueue.insert(entity.get()); _entitiesInQueue.insert(entity.get());
} }
} }
@ -364,8 +363,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
} }
} }
} else { } else {
const float WHEN_IN_DOUBT_PRIORITY = 1.0f; _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
_sendQueue.push(PrioritizedEntity(entity, WHEN_IN_DOUBT_PRIORITY));
_entitiesInQueue.insert(entity.get()); _entitiesInQueue.insert(entity.get());
} }
} }
@ -454,6 +452,23 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
#endif // SEND_SORTED_ENTITIES #endif // SEND_SORTED_ENTITIES
} }
void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer entity) {
if (entity) {
if (_entitiesInQueue.find(entity.get()) == _entitiesInQueue.end() && _knownState.find(entity.get()) != _knownState.end()) {
bool success = false;
AACube cube = entity->getQueryAACube(success);
if (success) {
float priority = _conicalView.computePriority(cube);
_sendQueue.push(PrioritizedEntity(entity, priority, true));
_entitiesInQueue.insert(entity.get());
} else {
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true));
_entitiesInQueue.insert(entity.get());
}
}
}
}
void EntityTreeSendThread::deletingEntityPointer(EntityItem* entity) { void EntityTreeSendThread::deletingEntityPointer(EntityItem* entity) {
_knownState.erase(entity); _knownState.erase(entity);
} }

View file

@ -54,6 +54,7 @@ private:
uint16_t _numEntities { 0 }; uint16_t _numEntities { 0 };
private slots: private slots:
void editingEntityPointer(const EntityItemPointer entity);
void deletingEntityPointer(EntityItem* entity); void deletingEntityPointer(EntityItem* entity);
}; };

View file

@ -32,7 +32,8 @@
#include "EntitySimulation.h" #include "EntitySimulation.h"
#include "EntityDynamicFactoryInterface.h" #include "EntityDynamicFactoryInterface.h"
Q_DECLARE_METATYPE(EntityItemPointer);
int entityItemPointernMetaTypeId = qRegisterMetaType<EntityItemPointer>();
int EntityItem::_maxActionsDataSize = 800; int EntityItem::_maxActionsDataSize = 800;
quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND;

View file

@ -62,7 +62,8 @@ class MeshProxyList;
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
/// one directly, instead you must only construct one of it's derived classes with additional features. /// one directly, instead you must only construct one of it's derived classes with additional features.
class EntityItem : public SpatiallyNestable, public ReadWriteLockable { class EntityItem : public QObject, public SpatiallyNestable, public ReadWriteLockable {
Q_OBJECT
// These two classes manage lists of EntityItem pointers and must be able to cleanup pointers when an EntityItem is deleted. // These two classes manage lists of EntityItem pointers and must be able to cleanup pointers when an EntityItem is deleted.
// To make the cleanup robust each EntityItem has backpointers to its manager classes (which are only ever set/cleared by // To make the cleanup robust each EntityItem has backpointers to its manager classes (which are only ever set/cleared by
// the managers themselves, hence they are fiends) whose NULL status can be used to determine which managers still need to // the managers themselves, hence they are fiends) whose NULL status can be used to determine which managers still need to

View file

@ -307,7 +307,9 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
} }
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube); UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube);
recurseTreeWithOperator(&theOperator); recurseTreeWithOperator(&theOperator);
entity->setProperties(tempProperties); if (entity->setProperties(tempProperties)) {
emit editingEntityPointer(entity);
}
_isDirty = true; _isDirty = true;
} }
} }
@ -382,7 +384,9 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
} }
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newQueryAACube); UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newQueryAACube);
recurseTreeWithOperator(&theOperator); recurseTreeWithOperator(&theOperator);
entity->setProperties(properties); if (entity->setProperties(properties)) {
emit editingEntityPointer(entity);
}
// if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse // if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse
QQueue<SpatiallyNestablePointer> toProcess; QQueue<SpatiallyNestablePointer> toProcess;
@ -1257,7 +1261,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
if (!isPhysics) { if (!isPhysics) {
properties.setLastEditedBy(senderNode->getUUID()); properties.setLastEditedBy(senderNode->getUUID());
} }
updateEntity(entityItemID, properties, senderNode); updateEntity(existingEntity, properties, senderNode);
existingEntity->markAsChangedOnServer(); existingEntity->markAsChangedOnServer();
endUpdate = usecTimestampNow(); endUpdate = usecTimestampNow();
_totalUpdates++; _totalUpdates++;

View file

@ -271,6 +271,7 @@ signals:
void deletingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID);
void deletingEntityPointer(EntityItem* entityID); void deletingEntityPointer(EntityItem* entityID);
void addingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID);
void editingEntityPointer(const EntityItemPointer& entityID);
void entityScriptChanging(const EntityItemID& entityItemID, const bool reload); void entityScriptChanging(const EntityItemID& entityItemID, const bool reload);
void entityServerScriptChanging(const EntityItemID& entityItemID, const bool reload); void entityServerScriptChanging(const EntityItemID& entityItemID, const bool reload);
void newCollisionSoundURL(const QUrl& url, const EntityItemID& entityID); void newCollisionSoundURL(const QUrl& url, const EntityItemID& entityID);