Skip to content

Commit

Permalink
#5613: Working on the key value logic
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Oct 16, 2021
1 parent d122fef commit 20b508e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 21 deletions.
73 changes: 59 additions & 14 deletions libs/selection/CollectiveSpawnargs.h
Expand Up @@ -3,6 +3,7 @@
#include "ientity.h"
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <sigc++/signal.h>

Expand All @@ -15,14 +16,25 @@ namespace selection
*/
class CollectiveSpawnargs
{
public:
struct KeyValueSet
{
KeyValueSet() :
valueIsEqualOnAllEntities(false)
{}

bool valueIsEqualOnAllEntities;
std::set<Entity*> entities;
};

private:
using KeyValues = std::map<std::string, std::string>;

// Map Entity instances to key value pairs
std::map<Entity*, KeyValues> _keyValuesByEntity;

// Map Keys to Entities
std::map<std::string, std::set<Entity*>> _entitiesByKey;
// Map Keys to KeyValueSets
std::map<std::string, KeyValueSet> _entitiesByKey;

sigc::signal<void(const std::string&, const std::string&)> _sigKeyAdded;
sigc::signal<void(const std::string&)> _sigKeyRemoved;
Expand All @@ -47,7 +59,7 @@ class CollectiveSpawnargs
return _sigKeyRemoved;
}

void foreachKey(const std::function<void(const std::string&, const std::set<Entity*>&)>& functor)
void foreachKey(const std::function<void(const std::string&, const KeyValueSet&)>& functor)
{
for (const auto& pair : _entitiesByKey)
{
Expand All @@ -57,21 +69,38 @@ class CollectiveSpawnargs

void onKeyInsert(Entity* entity, const std::string& key, EntityKeyValue& value)
{
const auto& valueString = value.get();

auto kv = _keyValuesByEntity.try_emplace(entity);
kv.first->second.emplace(key, value.get());
kv.first->second.emplace(key, valueString);

auto entityList = _entitiesByKey.try_emplace(key);
auto result = entityList.first->second.emplace(entity);

if (result.second)
auto& keyValueSet = entityList.first->second;
keyValueSet.entities.emplace(entity);

if (keyValueSet.entities.size() == 1)
{
// The set was newly created, this was a new (and therefore unique) keyvalue
keyValueSet.valueIsEqualOnAllEntities = true;
_sigKeyAdded.emit(key, value.get());
}
else
// This was not the first entity using this key, check if the values are unique
// We only bother checking if the already existing set had the same value
else if (keyValueSet.valueIsEqualOnAllEntities)
{
// The set was already present, check if the values are unique
// TODO
// Value was the shared before, let's check it now
auto valueIsUnique = std::all_of(
keyValueSet.entities.begin(), keyValueSet.entities.end(), [&](Entity* entity)
{
return entity->getKeyValue(key) == valueString;
});

if (!valueIsUnique)
{
keyValueSet.valueIsEqualOnAllEntities = false;
_sigKeyValueSetChanged.emit(key, "");
}
}
}

Expand All @@ -85,21 +114,35 @@ class CollectiveSpawnargs

void onKeyErase(Entity* entity, const std::string& key, EntityKeyValue& value)
{
auto kv = _keyValuesByEntity.try_emplace(entity);
kv.first->second.erase(key);
auto kv = _keyValuesByEntity.find(entity);

if (kv != _keyValuesByEntity.end())
{
kv->second.erase(key);

if (kv->second.empty())
{
// The entity-specific map is now empty, remove it
_keyValuesByEntity.erase(kv);
}
}

auto entityList = _entitiesByKey.find(key);

if (entityList != _entitiesByKey.end())
{
entityList->second.erase(entity);
entityList->second.entities.erase(entity);

if (entityList->second.empty())
if (entityList->second.entities.empty())
{
_entitiesByKey.erase(entityList);
// This was the last occurrence of this key, remove it
_sigKeyRemoved.emit(key);
}
else
{

}
}
}

Expand All @@ -110,7 +153,9 @@ class CollectiveSpawnargs
// Remove the entity from all key-mapped lists
for (auto& entityList : _entitiesByKey)
{
entityList.second.erase(entity);
entityList.second.entities.erase(entity);

// TODO: Check uniqueness
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion libs/selection/EntitySelection.h
Expand Up @@ -138,7 +138,7 @@ class EntitySelection final
});
}

void foreachKey(const std::function<void(const std::string&, const std::set<Entity*>&)>& functor)
void foreachKey(const std::function<void(const std::string&, const CollectiveSpawnargs::KeyValueSet&)>& functor)
{
_spawnargs.foreachKey(functor);
}
Expand Down
12 changes: 6 additions & 6 deletions radiant/ui/einspector/EntityInspector.cpp
Expand Up @@ -1569,11 +1569,11 @@ void EntityInspector::updateTreeView()
// Reset the sorting when changing entities
_keyValueTreeView->ResetSortingOnAllColumns();

_entitySelection->foreachKey([&](const std::string& key, const std::set<Entity*>& entities)
_entitySelection->foreachKey([&](const std::string& key, const selection::CollectiveSpawnargs::KeyValueSet& set)
{
if (entities.size() == 1)
if (set.valueIsEqualOnAllEntities)
{
auto entity = *entities.begin();
auto entity = *set.entities.begin();
onKeyChange(entity, key, entity->getKeyValue(key));
}
else
Expand Down Expand Up @@ -1622,11 +1622,11 @@ void EntityInspector::changeSelectedEntity(const scene::INodePtr& newEntity, con
// Reset the sorting when changing entities
_keyValueTreeView->ResetSortingOnAllColumns();

_entitySelection->foreachKey([&](const std::string& key, const std::set<Entity*>& entities)
_entitySelection->foreachKey([&](const std::string& key, const selection::CollectiveSpawnargs::KeyValueSet& set)
{
if (entities.size() == 1)
if (set.valueIsEqualOnAllEntities)
{
auto entity = *entities.begin();
auto entity = *set.entities.begin();
onKeyChange(key, entity->getKeyValue(key));
}
else
Expand Down

0 comments on commit 20b508e

Please sign in to comment.