Skip to content

Commit

Permalink
#5746: Implement handling of UnselectSelectionRequests in TextureTool…
Browse files Browse the repository at this point in the history
…SelectionSystem.
  • Loading branch information
codereader committed Sep 23, 2021
1 parent 50ebe76 commit aeff001
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 1 deletion.
6 changes: 6 additions & 0 deletions include/itexturetoolmodel.h
Expand Up @@ -160,6 +160,12 @@ class ITextureToolSelectionSystem :
// Collection should not be modified during iteration
virtual void foreachSelectedComponentNode(const std::function<bool(const INode::Ptr&)>& functor) = 0;

virtual std::size_t countSelected() = 0;
virtual std::size_t countSelectedComponentNodes() = 0;

virtual void clearSelection() = 0;
virtual void clearComponentSelection() = 0;

virtual SelectionMode getMode() const = 0;
virtual void setMode(SelectionMode mode) = 0;
virtual sigc::signal<void, SelectionMode>& signal_selectionModeChanged() = 0;
Expand Down
86 changes: 85 additions & 1 deletion radiantcore/selection/textool/TextureToolSelectionSystem.cpp
@@ -1,6 +1,7 @@
#include "TextureToolSelectionSystem.h"

#include "itextstream.h"
#include "iradiant.h"
#include "module/StaticModule.h"
#include "../textool/TextureToolRotateManipulator.h"
#include "../textool/TextureToolDragManipulator.h"
Expand All @@ -18,7 +19,8 @@ const std::string& TextureToolSelectionSystem::getName() const

const StringSet& TextureToolSelectionSystem::getDependencies() const
{
static StringSet _dependencies{ MODULE_TEXTOOL_SCENEGRAPH, MODULE_COMMANDSYSTEM };
static StringSet _dependencies{ MODULE_TEXTOOL_SCENEGRAPH,
MODULE_COMMANDSYSTEM, MODULE_RADIANT_CORE };
return _dependencies;
}

Expand All @@ -41,10 +43,17 @@ void TextureToolSelectionSystem::initialiseModule(const IApplicationContext& ctx
GlobalCommandSystem().addCommand("ToggleTextureToolSelectionMode",
std::bind(&TextureToolSelectionSystem::toggleSelectionModeCmd, this, std::placeholders::_1),
{ cmd::ARGTYPE_STRING });

_unselectListener = GlobalRadiantCore().getMessageBus().addListener(
radiant::IMessage::Type::UnselectSelectionRequest,
radiant::TypeListener<selection::UnselectSelectionRequest>(
sigc::mem_fun(this, &TextureToolSelectionSystem::handleUnselectRequest)));
}

void TextureToolSelectionSystem::shutdownModule()
{
GlobalRadiantCore().getMessageBus().removeListener(_unselectListener);

_sigSelectionModeChanged.clear();
_sigActiveManipulatorChanged.clear();
_manipulators.clear();
Expand Down Expand Up @@ -173,6 +182,81 @@ void TextureToolSelectionSystem::foreachSelectedNodeOfAnyType(const std::functio
}
}

std::size_t TextureToolSelectionSystem::countSelected()
{
std::size_t count = 0;

foreachSelectedNode([&](const INode::Ptr& node)
{
++count;
return true;
});

return count;
}

std::size_t TextureToolSelectionSystem::countSelectedComponentNodes()
{
std::size_t count = 0;

foreachSelectedComponentNode([&](const INode::Ptr& node)
{
++count;
return true;
});

return count;
}

void TextureToolSelectionSystem::clearSelection()
{
foreachSelectedNode([&](const INode::Ptr& node)
{
node->setSelected(false);
return true;
});
}

void TextureToolSelectionSystem::clearComponentSelection()
{
foreachSelectedComponentNode([&](const INode::Ptr& node)
{
auto componentSelectable = std::dynamic_pointer_cast<IComponentSelectable>(node);

if (componentSelectable)
{
componentSelectable->clearComponentSelection();
}

return true;
});
}

void TextureToolSelectionSystem::handleUnselectRequest(selection::UnselectSelectionRequest& request)
{
if (getMode() == SelectionMode::Vertex)
{
if (countSelectedComponentNodes() > 0)
{
clearComponentSelection();
}
else // no selection, just switch modes
{
setMode(SelectionMode::Surface);
}

request.setHandled(true);
}
else
{
if (countSelected() > 0)
{
clearSelection();
request.setHandled(true);
}
}
}

std::size_t TextureToolSelectionSystem::registerManipulator(const selection::ITextureToolManipulator::Ptr& manipulator)
{
std::size_t newId = 1;
Expand Down
11 changes: 11 additions & 0 deletions radiantcore/selection/textool/TextureToolSelectionSystem.h
Expand Up @@ -3,6 +3,7 @@
#include "itexturetoolmodel.h"
#include "icommandsystem.h"
#include "TextureToolManipulationPivot.h"
#include "messages/UnselectSelectionRequest.h"

namespace textool
{
Expand All @@ -24,6 +25,8 @@ class TextureToolSelectionSystem :

TextureToolManipulationPivot _manipulationPivot;

std::size_t _unselectListener;

public:
const std::string& getName() const override;
const StringSet& getDependencies() const override;
Expand All @@ -37,6 +40,12 @@ class TextureToolSelectionSystem :
void foreachSelectedNode(const std::function<bool(const INode::Ptr&)>& functor) override;
void foreachSelectedComponentNode(const std::function<bool(const INode::Ptr&)>& functor) override;

std::size_t countSelected() override;
std::size_t countSelectedComponentNodes() override;

void clearSelection() override;
void clearComponentSelection() override;

void selectPoint(SelectionTest& test, SelectionSystem::EModifier modifier) override;
void selectArea(SelectionTest& test, SelectionSystem::EModifier modifier) override;

Expand All @@ -58,6 +67,8 @@ class TextureToolSelectionSystem :
void onManipulationCancelled() override;

private:
void handleUnselectRequest(selection::UnselectSelectionRequest& request);

// Internally switches between the selection modes and iterates over the corresponding collection
void foreachSelectedNodeOfAnyType(const std::function<bool(const INode::Ptr&)>& functor);

Expand Down
88 changes: 88 additions & 0 deletions test/TextureTool.cpp
Expand Up @@ -644,6 +644,94 @@ TEST_F(TextureToolTest, TestSelectPatchByArea)
EXPECT_TRUE(std::dynamic_pointer_cast<textool::IPatchNode>(selectedNodes.front())) << "Couldn't cast to special type";
}

TEST_F(TextureToolTest, ClearSelectionUsingCommand)
{
auto worldspawn = GlobalMapModule().findOrInsertWorldspawn();
auto brush1 = algorithm::createCubicBrush(worldspawn, Vector3(0, 0, 0), "textures/numbers/1");
auto brush2 = algorithm::createCubicBrush(worldspawn, Vector3(0, 256, 256), "textures/numbers/1");
auto patchNode = GlobalPatchModule().createPatch(patch::PatchDefType::Def2);
scene::addNodeToContainer(patchNode, worldspawn);
Node_getIPatch(patchNode)->setDims(3, 3);
Node_getIPatch(patchNode)->setShader("textures/numbers/1");

Node_setSelected(brush1, true);
Node_setSelected(brush2, true);
Node_setSelected(patchNode, true);
EXPECT_EQ(GlobalSelectionSystem().countSelected(), 3) << "3 items must be selected";

// We don't know how many tex tool nodes there are, but it should be more than 0
EXPECT_GT(getTextureToolNodeCount(), 0) << "There should be some tex tool nodes now";

std::set<textool::INode::Ptr> selectedNodes;
std::size_t i = 0;

// Select every single node
GlobalTextureToolSceneGraph().foreachNode([&](const textool::INode::Ptr& node)
{
node->setSelected(true);
selectedNodes.emplace(node);
return true;
});

// We should have a non-empty selection
EXPECT_GT(GlobalTextureToolSelectionSystem().countSelected(), 0) << "No nodes selected";

// Switch to vertex mode
GlobalTextureToolSelectionSystem().setMode(textool::SelectionMode::Vertex);

// Get the texture space bounds of this patch
render::TextureToolView view;
auto bounds = getTextureSpaceBounds(*Node_getIPatch(patchNode));
bounds.extents *= 1.2f;
view.constructFromTextureSpaceBounds(bounds, TEXTOOL_WIDTH, TEXTOOL_HEIGHT);

// Select patch vertices
foreachPatchVertex(*Node_getIPatch(patchNode), [&](const PatchControl& control)
{
performPointSelection(control.texcoord, view);
});

// Select face vertices
auto faceUp = algorithm::findBrushFaceWithNormal(Node_getIBrush(brush1), Vector3(0, 0, 1));

// Get the texture space bounds of this face
bounds = getTextureSpaceBounds(*faceUp);
bounds.extents *= 1.2f;
view.constructFromTextureSpaceBounds(bounds, TEXTOOL_WIDTH, TEXTOOL_HEIGHT);

for (const auto& vertex : faceUp->getWinding())
{
performPointSelection(vertex.texcoord, view);
}

// We should have two selected component nodes
EXPECT_GT(GlobalTextureToolSelectionSystem().countSelectedComponentNodes(), 0) << "No components selected";
EXPECT_GT(GlobalSelectionSystem().countSelected(), 0) << "Scene selection count should be > 0";

// Hitting ESC once will deselect the components
GlobalCommandSystem().executeCommand("UnSelectSelection");

EXPECT_EQ(GlobalTextureToolSelectionSystem().countSelectedComponentNodes(), 0) << "Component selection should be gone";
EXPECT_GT(GlobalTextureToolSelectionSystem().countSelected(), 0) << "Surface selection should not have been touched";
EXPECT_GT(GlobalSelectionSystem().countSelected(), 0) << "Scene selection count should still be > 0";
EXPECT_EQ(GlobalTextureToolSelectionSystem().getMode(), textool::SelectionMode::Vertex) << "We should still be in vertex mode";

// Next deselection will exit vertex mode
GlobalCommandSystem().executeCommand("UnSelectSelection");
EXPECT_EQ(GlobalTextureToolSelectionSystem().getMode(), textool::SelectionMode::Surface) << "We should be in Surface mode now";
EXPECT_GT(GlobalTextureToolSelectionSystem().countSelected(), 0) << "Surface selection should not have been touched";
EXPECT_GT(GlobalSelectionSystem().countSelected(), 0) << "Scene selection count should still be > 0";

// Next will de-select the regular selection
GlobalCommandSystem().executeCommand("UnSelectSelection");
EXPECT_EQ(GlobalTextureToolSelectionSystem().countSelected(), 0) << "Surface selection should be gone now";
EXPECT_GT(GlobalSelectionSystem().countSelected(), 0) << "Scene selection count should still be > 0";

// Now that the tex tool selection is gone, we should affect the scene selection
GlobalCommandSystem().executeCommand("UnSelectSelection");
EXPECT_EQ(GlobalSelectionSystem().countSelected(), 0) << "Scene selection should be gone now";
}

inline std::vector<Vector2> getTexcoords(const IFace* face)
{
std::vector<Vector2> uvs;
Expand Down

0 comments on commit aeff001

Please sign in to comment.