From 5d314e9c837de121c931432568ad395d38a635b6 Mon Sep 17 00:00:00 2001 From: codereader Date: Tue, 14 Sep 2021 19:50:56 +0200 Subject: [PATCH] #5746: Every textool node is selectable, add foreachSelectedNode method --- include/itexturetoolmodel.h | 8 +++- .../TextureToolRotateManipulator.cpp | 2 +- radiantcore/selection/textool/NodeBase.h | 14 ++++++ .../textool/TextureToolSceneGraph.cpp | 15 +++++++ .../selection/textool/TextureToolSceneGraph.h | 1 + test/TextureTool.cpp | 44 +++++++++++++++++++ 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/itexturetoolmodel.h b/include/itexturetoolmodel.h index 2c2085f5ee..97aae4a85e 100644 --- a/include/itexturetoolmodel.h +++ b/include/itexturetoolmodel.h @@ -3,6 +3,7 @@ #include "imodule.h" #include "inode.h" #include "Bounded.h" +#include "iselection.h" class Matrix3; @@ -31,7 +32,8 @@ class ITransformable // The base element of every node in the ITextureToolSceneGraph class INode : public ITransformable, - public Bounded + public Bounded, + public ISelectable { public: virtual ~INode() {} @@ -60,6 +62,10 @@ class ITextureToolSceneGraph : // Iterate over every node in this graph calling the given functor // Collection should not be modified during iteration virtual void foreachNode(const std::function& functor) = 0; + + // Iterate over every selected node in this graph calling the given functor + // Collection should not be modified during iteration + virtual void foreachSelectedNode(const std::function& functor) = 0; }; } diff --git a/radiantcore/selection/manipulators/TextureToolRotateManipulator.cpp b/radiantcore/selection/manipulators/TextureToolRotateManipulator.cpp index 95a729283a..7ea91e7104 100644 --- a/radiantcore/selection/manipulators/TextureToolRotateManipulator.cpp +++ b/radiantcore/selection/manipulators/TextureToolRotateManipulator.cpp @@ -1,6 +1,7 @@ #include "TextureToolRotateManipulator.h" #include "iselectiontest.h" +#include "itexturetoolmodel.h" #include "selection/BestPoint.h" #include "selection/SelectionPool.h" #include "pivot.h" @@ -145,7 +146,6 @@ void TextureToolRotateManipulator::renderComponents(const Matrix4& pivot2World) void TextureToolRotateManipulator::rotateSelected(double angle) { - // TODO } } diff --git a/radiantcore/selection/textool/NodeBase.h b/radiantcore/selection/textool/NodeBase.h index a31acfb7bd..af833f827c 100644 --- a/radiantcore/selection/textool/NodeBase.h +++ b/radiantcore/selection/textool/NodeBase.h @@ -1,6 +1,7 @@ #pragma once #include "itexturetoolmodel.h" +#include "../BasicSelectable.h" namespace textool { @@ -8,6 +9,19 @@ namespace textool class NodeBase : public INode { +private: + selection::BasicSelectable _selectable; + +public: + virtual void setSelected(bool select) override + { + _selectable.setSelected(select); + } + + virtual bool isSelected() const override + { + return _selectable.isSelected(); + } }; } diff --git a/radiantcore/selection/textool/TextureToolSceneGraph.cpp b/radiantcore/selection/textool/TextureToolSceneGraph.cpp index dcaa4e5543..dda71709e0 100644 --- a/radiantcore/selection/textool/TextureToolSceneGraph.cpp +++ b/radiantcore/selection/textool/TextureToolSceneGraph.cpp @@ -57,6 +57,21 @@ void TextureToolSceneGraph::foreachNode(const std::function& functor) +{ + ensureSceneIsAnalysed(); + + for (const auto& node : _nodes) + { + if (!node->isSelected()) continue; + + if (!functor(node)) + { + break; + } + } +} + void TextureToolSceneGraph::ensureSceneIsAnalysed() { if (!_selectionNeedsRescan) return; diff --git a/radiantcore/selection/textool/TextureToolSceneGraph.h b/radiantcore/selection/textool/TextureToolSceneGraph.h index 040d86a734..2a515b902b 100644 --- a/radiantcore/selection/textool/TextureToolSceneGraph.h +++ b/radiantcore/selection/textool/TextureToolSceneGraph.h @@ -26,6 +26,7 @@ class TextureToolSceneGraph : void shutdownModule() override; void foreachNode(const std::function& functor) override; + void foreachSelectedNode(const std::function& functor) override; private: void onSceneSelectionChanged(const ISelectable& selectable); diff --git a/test/TextureTool.cpp b/test/TextureTool.cpp index 68c1eded0f..e635e1a047 100644 --- a/test/TextureTool.cpp +++ b/test/TextureTool.cpp @@ -1,5 +1,6 @@ #include "RadiantTest.h" +#include #include "imap.h" #include "ipatch.h" #include "iselectable.h" @@ -153,4 +154,47 @@ TEST_F(TextureToolTest, PatchNodeBounds) "Bounds mismatch, got " << node->localAABB().getExtents() << " instead of " << checkedBounds.getExtents(); } +TEST_F(TextureToolTest, ForeachSelectedNode) +{ + 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); + 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 selectedNodes; + std::size_t i = 0; + + // Selected every odd node + GlobalTextureToolSceneGraph().foreachNode([&](const textool::INode::Ptr& node) + { + if (++i % 2 == 1) + { + node->setSelected(true); + selectedNodes.emplace(node); + } + + return true; + }); + + std::size_t selectedCount = 0; + GlobalTextureToolSceneGraph().foreachSelectedNode([&](const textool::INode::Ptr& node) + { + ++selectedCount; + EXPECT_TRUE(selectedNodes.count(node) > 0) << "Node shouldn't be selected"; + return true; + }); + + EXPECT_EQ(selectedCount, selectedNodes.size()) << "Selection count didn't match"; +} + }