Skip to content

Commit

Permalink
#5824: Implement the special algorithm for removing all entities from…
Browse files Browse the repository at this point in the history
… the selection
  • Loading branch information
codereader committed Nov 27, 2021
1 parent 55adce1 commit 92b2fe6
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
24 changes: 24 additions & 0 deletions libs/selection/CollectiveSpawnargs.h
Expand Up @@ -294,6 +294,30 @@ class CollectiveSpawnargs
}
}

// Special case handling of all entities having been deselected at once
// Takes a few shortcuts and issues removal events of all listed keys (no change or add events)
void onAllEntitiesRemoved()
{
// Send a remove event for all keys that are currently listed
// (They are the ones that exist on all known entities)
for (auto& pair : _entitiesByKey)
{
const auto& key = pair.first;
auto& keyValueSet = pair.second;

// The entity count for this key must be equal to the count of all known entities
// then the key is listed (unique or non-unique, this doesn't matter here)
if (keyValueSet.entities.size() == _keyValuesByEntity.size())
{
_sigKeyRemoved.emit(key);
}
}

// Clear out both mappings
_keyValuesByEntity.clear();
_entitiesByKey.clear();
}

private:
void removeKey(Entity* entity, const std::string& key)
{
Expand Down
38 changes: 33 additions & 5 deletions libs/selection/EntitySelection.h
Expand Up @@ -40,12 +40,14 @@ class EntitySelection final :
CollectiveSpawnargs& _spawnargCollection;
Entity* _entity;
scene::INodeWeakPtr _node;
bool _destroySilently;

public:
SpawnargTracker(CollectiveSpawnargs& spawnargCollection, const scene::INodePtr& node) :
_spawnargCollection(spawnargCollection),
_entity(Node_getEntity(node)),
_node(node)
_node(node),
_destroySilently(false)
{
assert(_entity != nullptr);
_entity->attachObserver(this);
Expand All @@ -58,10 +60,13 @@ class EntitySelection final :

~SpawnargTracker()
{
// Call the onEntityRemoved method instead of relying on the onKeyErase()
// invocations when detaching the observer. This allows us to keep some
// assumptions about entity count in the CollectiveSpawnargs::onKeyErase method
_spawnargCollection.onEntityRemoved(_entity);
if (!_destroySilently)
{
// Call the onEntityRemoved method instead of relying on the onKeyErase()
// invocations when detaching the observer. This allows us to keep some
// assumptions about entity count in the CollectiveSpawnargs::onKeyErase method
_spawnargCollection.onEntityRemoved(_entity);
}

// Clear the reference to disable the observer callbacks
auto entity = _entity;
Expand Down Expand Up @@ -96,6 +101,12 @@ class EntitySelection final :
if (!_entity) return;
_spawnargCollection.onKeyErase(_entity, key, value);
}

// Instruct the tracker to not fire any callbacks on destruction
void setDestroySilently(bool value)
{
_destroySilently = value;
}
};

std::list<SpawnargTracker> _trackedEntities;
Expand Down Expand Up @@ -216,6 +227,23 @@ class EntitySelection final :
}
});

// We take a shortcut in case a previous selection was fully cleared
if (selectedEntities.empty() && !_trackedEntities.empty())
{
// Prevent the spawnarg trackers from firing any callbacks on destruction
for (auto& tracked : _trackedEntities)
{
tracked.setDestroySilently(true);
}

_trackedEntities.clear();

// This will notify the collection that all entities are gone.
// It will fire remove events to properly clean up the client code
_spawnargs.onAllEntitiesRemoved();
return;
}

auto trackerCountChanged = false;

// Untrack all nodes that have been deleted or deselected in the meantime
Expand Down

0 comments on commit 92b2fe6

Please sign in to comment.