Skip to content

Commit

Permalink
#5235: Implement "SelectItemsByModel" & "DeselectItemsByModel" commands
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Oct 9, 2020
1 parent 1afb5a9 commit be81e5e
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 0 deletions.
46 changes: 46 additions & 0 deletions libs/scene/EntitySelector.h
@@ -0,0 +1,46 @@
#pragma once

#include "inode.h"
#include "ientity.h"
#include "iselectable.h"

namespace scene
{

/**
* Scene walker (de-)selecting all entities
* matching the predicate passed to the constructor.
*/
class EntitySelector :
public scene::NodeVisitor
{
private:
std::function<bool(const Entity&)> _predicate;
bool _select;

public:
EntitySelector(const std::function<bool(const Entity&)>& predicate, bool select) :
_predicate(predicate),
_select(select)
{}

bool pre(const scene::INodePtr& node) override
{
if (!Node_isEntity(node))
{
return true;
}

const auto* entity = Node_getEntity(node);
assert(entity != nullptr);

if (_predicate(*entity))
{
Node_setSelected(node, _select);
}

return false; // don't go deeper
}
};

}
64 changes: 64 additions & 0 deletions radiantcore/selection/algorithm/Entity.cpp
Expand Up @@ -3,6 +3,7 @@
#include <limits>
#include "i18n.h"
#include "itransformable.h"
#include "ieclass.h"
#include "selectionlib.h"
#include "imainframe.h"
#include "iregistry.h"
Expand All @@ -12,6 +13,7 @@
#include "gamelib.h"
#include "command/ExecutionFailure.h"
#include "command/ExecutionNotPossible.h"
#include "scene/EntitySelector.h"

#include "selection/algorithm/General.h"
#include "selection/algorithm/Shader.h"
Expand Down Expand Up @@ -243,5 +245,67 @@ void connectSelectedEntities(const cmd::ArgumentList& args)
}
}

bool entityReferencesModel(const Entity& entity, const std::string& searchString)
{
auto model = entity.getKeyValue("model");

if (searchString == model)
{
return true;
}

// The entity might still reference the model through a model def
auto modelDef = GlobalEntityClassManager().findModel(model);

return modelDef && modelDef->mesh == searchString;
}

void selectItemsByModel(const std::string& model)
{
if (!GlobalSceneGraph().root()) return;

scene::EntitySelector selector([&](const Entity& entity)
{
return entityReferencesModel(entity, model);
}, true);

GlobalSceneGraph().root()->traverse(selector);
}

void deselectItemsByModel(const std::string& model)
{
if (!GlobalSceneGraph().root()) return;

scene::EntitySelector deselector([&](const Entity& entity)
{
return entityReferencesModel(entity, model);
}, false);

GlobalSceneGraph().root()->traverse(deselector);
}

// Command target to (de-)select items by model
void selectItemsByModelCmd(const cmd::ArgumentList& args)
{
if (args.size() != 1)
{
rMessage() << "Usage: SelectItemsByModel <modelpath>" << std::endl;
return;
}

selectItemsByModel(args[0].getString());
}

void deselectItemsByModelCmd(const cmd::ArgumentList& args)
{
if (args.size() != 1)
{
rMessage() << "Usage: DeselectItemsByModel <modelpath>" << std::endl;
return;
}

deselectItemsByModel(args[0].getString());
}

} // namespace algorithm
} // namespace selection
11 changes: 11 additions & 0 deletions radiantcore/selection/algorithm/Entity.h
Expand Up @@ -37,5 +37,16 @@ void bindEntities(const cmd::ArgumentList& args);
*/
void connectSelectedEntities(const cmd::ArgumentList& args);

/**
* greebo: (De-)selects all entities that reference the given model path
* in their "model" spawnarg.
*/
void selectItemsByModel(const std::string& model);
void deselectItemsByModel(const std::string& model);

// Command target to (de-)select items by model
void selectItemsByModelCmd(const cmd::ArgumentList& args);
void deselectItemsByModelCmd(const cmd::ArgumentList& args);

} // namespace algorithm
} // namespace selection
3 changes: 3 additions & 0 deletions radiantcore/selection/algorithm/General.cpp
Expand Up @@ -970,6 +970,9 @@ void registerCommands()
GlobalCommandSystem().addCommand("SelectItemsByShader", selectItemsByShaderCmd, { cmd::ARGTYPE_STRING });
GlobalCommandSystem().addCommand("DeselectItemsByShader", deselectItemsByShaderCmd, { cmd::ARGTYPE_STRING });

GlobalCommandSystem().addCommand("SelectItemsByModel", selectItemsByModelCmd, { cmd::ARGTYPE_STRING });
GlobalCommandSystem().addCommand("DeselectItemsByModel", deselectItemsByModelCmd, { cmd::ARGTYPE_STRING });

GlobalCommandSystem().addCommand("FlipTextureX", flipTextureS);
GlobalCommandSystem().addCommand("FlipTextureY", flipTextureT);

Expand Down
1 change: 1 addition & 0 deletions tools/msvc/scenelib.vcxproj
Expand Up @@ -129,6 +129,7 @@
<ClInclude Include="..\..\libs\scene\ChildPrimitives.h" />
<ClInclude Include="..\..\libs\scene\Clone.h" />
<ClInclude Include="..\..\libs\scene\EntityBreakdown.h" />
<ClInclude Include="..\..\libs\scene\EntitySelector.h" />
<ClInclude Include="..\..\libs\scene\Group.h" />
<ClInclude Include="..\..\libs\scene\GroupNodeChecker.h" />
<ClInclude Include="..\..\libs\scene\InstanceWalkers.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/scenelib.vcxproj.filters
Expand Up @@ -88,5 +88,8 @@
<ClInclude Include="..\..\libs\scene\Group.h">
<Filter>scene</Filter>
</ClInclude>
<ClInclude Include="..\..\libs\scene\EntitySelector.h">
<Filter>scene</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit be81e5e

Please sign in to comment.