Skip to content

Commit

Permalink
#5613: Next iteration, this now shows all the keys of all entities.
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Oct 15, 2021
1 parent 24b0da8 commit 5599d14
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 22 deletions.
64 changes: 55 additions & 9 deletions libs/selection/EntitySelection.h
Expand Up @@ -44,6 +44,7 @@ class EntitySelection final
}

_entity->detachObserver(this);
_owner.cleanupEntity(_entity);
}

scene::INodePtr getNode() const
Expand All @@ -69,13 +70,15 @@ class EntitySelection final

std::list<SpawnargTracker> _trackedEntities;

public:
EntitySelection()
{}
using KeyValues = std::map<std::string, std::string>;

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

~EntitySelection()
{}
// Map Keys to Entities
std::map<std::string, std::set<Entity*>> _entitiesByKey;

public:
std::size_t size() const
{
return _trackedEntities.size();
Expand Down Expand Up @@ -130,6 +133,14 @@ class EntitySelection final
});
}

void foreachKey(const std::function<void(const std::string&, const std::set<Entity*>&)>& functor)
{
for (const auto& pair : _entitiesByKey)
{
functor(pair.first, pair.second);
}
}

private:
scene::INodePtr getEntityForNode(const scene::INodePtr& selected)
{
Expand Down Expand Up @@ -169,14 +180,49 @@ class EntitySelection final

void onKeyInsert(Entity* entity, const std::string& key, EntityKeyValue& value)
{

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

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

void onKeyChange(Entity* entity, const std::string& key, const std::string& val)
{ }
void onKeyChange(Entity* entity, const std::string& key, const std::string& value)
{
auto kv = _keyValuesByEntity.try_emplace(entity);
kv.first->second[key] = value;

// On key change, we don't need to update the entitiesByKey map
}

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

auto entityList = _entitiesByKey.find(key);

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

if (entityList->second.empty())
{
_entitiesByKey.erase(entityList);
}
}
}

void cleanupEntity(Entity* entity)
{
_keyValuesByEntity.erase(entity);

// Remove the entity from all key-mapped lists
for (auto& entityList : _entitiesByKey)
{
entityList.second.erase(entity);
}
}
};

}
87 changes: 74 additions & 13 deletions radiant/ui/einspector/EntityInspector.cpp
Expand Up @@ -192,6 +192,12 @@ void EntityInspector::onKeyInsert(const std::string& key,
}

void EntityInspector::onKeyChange(const std::string& key,
const std::string& value)
{
onKeyChange(nullptr, key, value);
}

void EntityInspector::onKeyChange(Entity* entity, const std::string& key,
const std::string& value)
{
wxDataViewItem keyValueIter;
Expand Down Expand Up @@ -219,19 +225,25 @@ void EntityInspector::onKeyChange(const std::string& key,
// Get the type for this key if it exists, and the options
PropertyParms parms = getPropertyParmsForKey(key);

assert(!_selectedEntity.expired());
Entity* selectedEntity = Node_getEntity(_selectedEntity.lock());
//assert(!_selectedEntity.expired());
//Entity* selectedEntity = Node_getEntity(_selectedEntity.lock());
auto selectedEntity = entity;

// Check the entityclass (which will return blank if not found)
IEntityClassConstPtr eclass = selectedEntity->getEntityClass();
const EntityClassAttribute& attr = eclass->getAttribute(key);
bool hasDescription = false;

if (parms.type.empty())
if (selectedEntity != nullptr)
{
parms.type = attr.getType();
}
// Check the entityclass (which will return blank if not found)
auto eclass = selectedEntity->getEntityClass();
const auto& attr = eclass->getAttribute(key);

if (parms.type.empty())
{
parms.type = attr.getType();
}

bool hasDescription = !attr.getDescription().empty();
hasDescription = !attr.getDescription().empty();
}

// Set the values for the row
wxutil::TreeModel::Row row(keyValueIter, *_kvStore);
Expand Down Expand Up @@ -1447,7 +1459,6 @@ void EntityInspector::getEntityFromSelectionSystem()
{
_entitySelection->update();

// A single entity must be selected
auto numSelectedEntities = _entitySelection->size();

if (numSelectedEntities == 0)
Expand All @@ -1456,13 +1467,15 @@ void EntityInspector::getEntityFromSelectionSystem()
_primitiveNumLabel->SetLabelText("");
return;
}
else if (numSelectedEntities > 1)

if (numSelectedEntities > 1)
{
changeSelectedEntity(scene::INodePtr(), scene::INodePtr());
_primitiveNumLabel->SetLabelText(fmt::format("[{0} Entities]", numSelectedEntities));
return;
}

updateTreeView();

#if 0
if (GlobalSelectionSystem().countSelected() != 1)
{
Expand All @@ -1473,8 +1486,9 @@ void EntityInspector::getEntityFromSelectionSystem()

auto selectedNode = GlobalSelectionSystem().ultimateSelected();
#endif
#if 0
auto selectedNode = _entitySelection->getSingleSelectedEntity();

#endif
#if 0
// The root node must not be selected (this can happen if Invert Selection is
// activated with an empty scene, or by direct selection in the entity list).
Expand All @@ -1486,6 +1500,7 @@ void EntityInspector::getEntityFromSelectionSystem()
}
#endif

#if 0
// Try both the selected node (if an entity is selected) or the parent node
// (if a brush is selected).
Entity* newSelectedEntity = Node_getEntity(selectedNode);
Expand Down Expand Up @@ -1539,10 +1554,38 @@ void EntityInspector::getEntityFromSelectionSystem()
_primitiveNumLabel->SetLabelText("-");
}
}
#endif
}

void EntityInspector::updateTreeView()
{
// Clear the view. If the old entity has been destroyed before we had
// a chance to disconnect the list store might contain remnants
_keyValueIterMap.clear();
_kvStore->Clear();
_mergeActions.clear();
_conflictActions.clear();

// Reset the sorting when changing entities
_keyValueTreeView->ResetSortingOnAllColumns();

_entitySelection->foreachKey([&](const std::string& key, const std::set<Entity*>& entities)
{
if (entities.size() == 1)
{
auto entity = *entities.begin();
onKeyChange(entity, key, entity->getKeyValue(key));
}
else
{
onKeyChange(key, _("[multiple values]"));
}
});
}

void EntityInspector::changeSelectedEntity(const scene::INodePtr& newEntity, const scene::INodePtr& selectedNode)
{
#if 0
// Check what we need to do with the existing entity
scene::INodePtr oldEntity = _selectedEntity.lock();

Expand All @@ -1561,10 +1604,13 @@ void EntityInspector::changeSelectedEntity(const scene::INodePtr& newEntity, con
return;
}
}
#endif

#if 0
// At this point, we either disconnected from the old entity or
// it has already been deleted (no disconnection necessary)
_selectedEntity.reset();
#endif

// Clear the view. If the old entity has been destroyed before we had
// a chance to disconnect the list store might contain remnants
Expand All @@ -1576,6 +1622,20 @@ 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)
{
if (entities.size() == 1)
{
auto entity = *entities.begin();
onKeyChange(key, entity->getKeyValue(key));
}
else
{
onKeyChange(key, _("[multiple values]"));
}
});

#if 0
// Attach to new entity if it is non-NULL
if (newEntity && newEntity->getNodeType() == scene::INode::Type::Entity)
{
Expand All @@ -1593,6 +1653,7 @@ void EntityInspector::changeSelectedEntity(const scene::INodePtr& newEntity, con
addClassProperties();
}
}
#endif
}

void EntityInspector::handleKeyValueMergeAction(const scene::merge::IEntityKeyValueMergeAction::Ptr& mergeAction)
Expand Down
2 changes: 2 additions & 0 deletions radiant/ui/einspector/EntityInspector.h
Expand Up @@ -239,6 +239,7 @@ class EntityInspector :

// Update tree view contents and property editor
void updateGUIElements();
void updateTreeView();

// Release the current entity and rescan the selection
void refresh();
Expand Down Expand Up @@ -273,6 +274,7 @@ class EntityInspector :
/* Entity::Observer implementation */
void onKeyInsert(const std::string& key, EntityKeyValue& value);
void onKeyChange(const std::string& key, const std::string& value);
void onKeyChange(Entity* entity, const std::string& key, const std::string& value);
void onKeyErase(const std::string& key, EntityKeyValue& value);

// greebo: Tells the inspector to reload the window settings from the registry.
Expand Down

0 comments on commit 5599d14

Please sign in to comment.