fix zones for real this time

This commit is contained in:
SamGondelman 2019-05-10 14:52:26 -07:00
parent 0d28932181
commit dfdace8cdc
2 changed files with 46 additions and 40 deletions

View file

@ -591,7 +591,7 @@ void EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSet<EntityItemI
if (contains) { if (contains) {
// if this entity is a zone and visible, add it to our layered zones // if this entity is a zone and visible, add it to our layered zones
if (isZone && entity->getVisible() && renderableIdForEntity(entity) != render::Item::INVALID_ITEM_ID) { if (isZone && entity->getVisible() && renderableIdForEntity(entity) != render::Item::INVALID_ITEM_ID) {
_layeredZones.emplace(std::dynamic_pointer_cast<ZoneEntityItem>(entity)); _layeredZones.emplace_back(std::dynamic_pointer_cast<ZoneEntityItem>(entity));
} }
if ((!hasScript && isZone) || scriptHasLoaded) { if ((!hasScript && isZone) || scriptHasLoaded) {
@ -600,6 +600,7 @@ void EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSet<EntityItemI
} }
} }
_layeredZones.sort();
if (!_layeredZones.equals(oldLayeredZones)) { if (!_layeredZones.equals(oldLayeredZones)) {
applyLayeredZones(); applyLayeredZones();
} }
@ -1187,66 +1188,73 @@ void EntityTreeRenderer::updateEntityRenderStatus(bool shouldRenderEntities) {
void EntityTreeRenderer::updateZone(const EntityItemID& id) { void EntityTreeRenderer::updateZone(const EntityItemID& id) {
if (auto zone = std::dynamic_pointer_cast<ZoneEntityItem>(getTree()->findEntityByEntityItemID(id))) { if (auto zone = std::dynamic_pointer_cast<ZoneEntityItem>(getTree()->findEntityByEntityItemID(id))) {
_layeredZones.update(zone, _avatarPosition, this); if (_layeredZones.update(zone, _avatarPosition, this)) {
applyLayeredZones(); applyLayeredZones();
}
} }
} }
bool EntityTreeRenderer::LayeredZones::clearDomainAndNonOwnedZones(const QUuid& sessionUUID) { bool EntityTreeRenderer::LayeredZones::clearDomainAndNonOwnedZones(const QUuid& sessionUUID) {
bool zonesChanged = false; bool zonesChanged = false;
auto it = c.begin(); auto it = begin();
while (it != c.end()) { while (it != end()) {
auto zone = it->zone.lock(); auto zone = it->zone.lock();
if (!zone || !(zone->isLocalEntity() || (zone->isAvatarEntity() && zone->getOwningAvatarID() == sessionUUID))) { if (!zone || !(zone->isLocalEntity() || (zone->isAvatarEntity() && zone->getOwningAvatarID() == sessionUUID))) {
zonesChanged = true; zonesChanged = true;
it = c.erase(it); it = erase(it);
} else { } else {
it++; it++;
} }
} }
if (zonesChanged) { if (zonesChanged) {
std::make_heap(c.begin(), c.end(), comp); sort();
} }
return zonesChanged; return zonesChanged;
} }
std::pair<bool, bool> EntityTreeRenderer::LayeredZones::getZoneInteractionProperties() const { std::pair<bool, bool> EntityTreeRenderer::LayeredZones::getZoneInteractionProperties() const {
auto it = c.cbegin(); for (auto it = cbegin(); it != cend(); it++) {
while (it != c.cend()) {
auto zone = it->zone.lock(); auto zone = it->zone.lock();
if (zone && zone->isDomainEntity()) { if (zone && zone->isDomainEntity()) {
return { zone->getFlyingAllowed(), zone->getGhostingAllowed() }; return { zone->getFlyingAllowed(), zone->getGhostingAllowed() };
} }
it++;
} }
return { true, true }; return { true, true };
} }
void EntityTreeRenderer::LayeredZones::remove(const std::shared_ptr<ZoneEntityItem>& zone) { bool EntityTreeRenderer::LayeredZones::update(std::shared_ptr<ZoneEntityItem> zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer) {
auto it = c.begin();
while (it != c.end()) {
if (it->zone.lock() == zone) {
break;
}
it++;
}
if (it != c.end()) {
c.erase(it);
std::make_heap(c.begin(), c.end(), comp);
}
}
void EntityTreeRenderer::LayeredZones::update(std::shared_ptr<ZoneEntityItem> zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer) {
// When a zone's position or visibility changes, we call this method // When a zone's position or visibility changes, we call this method
// In order to resort our zones, we first remove the changed zone, and then re-insert it if necessary // In order to resort our zones, we first remove the changed zone, and then re-insert it if necessary
remove(zone);
bool needsResort = false;
{
auto it = begin();
while (it != end()) {
if (it->zone.lock() == zone) {
break;
}
it++;
}
if (it != end()) {
erase(it);
needsResort = true;
}
}
// Only call contains if the zone is rendering // Only call contains if the zone is rendering
if (zone->isVisible() && entityTreeRenderer->renderableIdForEntity(zone) != render::Item::INVALID_ITEM_ID && zone->contains(position)) { if (zone->isVisible() && entityTreeRenderer->renderableIdForEntity(zone) != render::Item::INVALID_ITEM_ID && zone->contains(position)) {
emplace(zone); emplace_back(zone);
needsResort = true;
} }
if (needsResort) {
sort();
}
return needsResort;
} }
bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const { bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const {
@ -1254,9 +1262,9 @@ bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const {
return false; return false;
} }
auto it = c.cbegin(); auto it = cbegin();
auto otherIt = other.c.cbegin(); auto otherIt = other.cbegin();
while (it != c.cend()) { while (it != cend()) {
if (*it != *otherIt) { if (*it != *otherIt) {
return false; return false;
} }
@ -1268,15 +1276,13 @@ bool EntityTreeRenderer::LayeredZones::equals(const LayeredZones& other) const {
} }
void EntityTreeRenderer::LayeredZones::appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const { void EntityTreeRenderer::LayeredZones::appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const {
auto it = c.cbegin(); for (auto it = cbegin(); it != cend(); it++) {
while (it != c.cend()) {
if (it->zone.lock()) { if (it->zone.lock()) {
auto id = entityTreeRenderer->renderableIdForEntityId(it->id); auto id = entityTreeRenderer->renderableIdForEntityId(it->id);
if (id != render::Item::INVALID_ITEM_ID) { if (id != render::Item::INVALID_ITEM_ID) {
list.push_back(id); list.push_back(id);
} }
} }
it++;
} }
} }

View file

@ -213,24 +213,24 @@ private:
public: public:
LayeredZone(std::shared_ptr<ZoneEntityItem> zone) : zone(zone), id(zone->getID()), volume(zone->getVolumeEstimate()) {} LayeredZone(std::shared_ptr<ZoneEntityItem> zone) : zone(zone), id(zone->getID()), volume(zone->getVolumeEstimate()) {}
bool operator>(const LayeredZone& r) const { return volume > r.volume; } // We need to sort on volume AND id so that different clients sort zones with identical volumes the same way
bool operator==(const LayeredZone& r) const { return zone.lock() == r.zone.lock(); } bool operator<(const LayeredZone& r) const { return volume < r.volume || (volume == r.volume && id < r.id); }
bool operator==(const LayeredZone& r) const { return zone.lock() && zone.lock() == r.zone.lock(); }
bool operator!=(const LayeredZone& r) const { return !(*this == r); } bool operator!=(const LayeredZone& r) const { return !(*this == r); }
bool operator>=(const LayeredZone& r) const { return (*this > r) || (*this == r); } bool operator<=(const LayeredZone& r) const { return (*this < r) || (*this == r); }
std::weak_ptr<ZoneEntityItem> zone; std::weak_ptr<ZoneEntityItem> zone;
QUuid id; QUuid id;
float volume; float volume;
}; };
class LayeredZones : public std::priority_queue<LayeredZone, std::vector<LayeredZone>, std::greater<LayeredZone>> { class LayeredZones : public std::vector<LayeredZone> {
public: public:
void clear() { *this = LayeredZones(); }
bool clearDomainAndNonOwnedZones(const QUuid& sessionUUID); bool clearDomainAndNonOwnedZones(const QUuid& sessionUUID);
void sort() { std::sort(begin(), end(), std::less<LayeredZone>()); }
bool equals(const LayeredZones& other) const; bool equals(const LayeredZones& other) const;
void remove(const std::shared_ptr<ZoneEntityItem>& zone); bool update(std::shared_ptr<ZoneEntityItem> zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer);
void update(std::shared_ptr<ZoneEntityItem> zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer);
void appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const; void appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const;
std::pair<bool, bool> getZoneInteractionProperties() const; std::pair<bool, bool> getZoneInteractionProperties() const;