diff --git a/radiantcore/CMakeLists.txt b/radiantcore/CMakeLists.txt
index 8c961043fe..4389cd16cc 100644
--- a/radiantcore/CMakeLists.txt
+++ b/radiantcore/CMakeLists.txt
@@ -235,6 +235,7 @@ add_library(radiantcore MODULE
selection/algorithm/Planes.cpp
selection/algorithm/Primitives.cpp
selection/algorithm/Shader.cpp
+ selection/algorithm/Texturing.cpp
selection/algorithm/Transformation.cpp
selection/clipboard/Clipboard.cpp
selection/group/SelectionGroupInfoFileModule.cpp
diff --git a/radiantcore/selection/algorithm/Texturing.cpp b/radiantcore/selection/algorithm/Texturing.cpp
new file mode 100644
index 0000000000..5c35fec474
--- /dev/null
+++ b/radiantcore/selection/algorithm/Texturing.cpp
@@ -0,0 +1,37 @@
+#include "Texturing.h"
+
+namespace selection
+{
+
+namespace algorithm
+{
+
+TextureFlipper::TextureFlipper(const Vector2& flipCenter, int axis)
+{
+ auto flipMatrix = Matrix3::getIdentity();
+
+ if (axis == 0)
+ {
+ flipMatrix.xx() = -1;
+ }
+ else // axis == 1
+ {
+ flipMatrix.yy() = -1;
+ }
+
+ _transform = Matrix3::getTranslation(-flipCenter);
+ _transform.premultiplyBy(flipMatrix);
+ _transform.premultiplyBy(Matrix3::getTranslation(+flipCenter));
+}
+
+bool TextureFlipper::operator()(const textool::INode::Ptr& node)
+{
+ node->beginTransformation();
+ node->transform(_transform);
+ node->commitTransformation();
+ return true;
+}
+
+}
+
+}
diff --git a/radiantcore/selection/algorithm/Texturing.h b/radiantcore/selection/algorithm/Texturing.h
new file mode 100644
index 0000000000..4ea613a485
--- /dev/null
+++ b/radiantcore/selection/algorithm/Texturing.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "itexturetoolmodel.h"
+#include "math/Matrix3.h"
+
+namespace selection
+{
+
+namespace algorithm
+{
+
+// Flips all the visited node about the given axis and the given flip center point (in UV space)
+class TextureFlipper
+{
+private:
+ Matrix3 _transform;
+
+public:
+ TextureFlipper(const Vector2& flipCenter, int axis);
+
+ // Function operator, makes this class suitable to pass to e.g. ITextureToolSelectionSystem.foreachSelected()
+ bool operator()(const textool::INode::Ptr& node);
+};
+
+}
+
+}
diff --git a/radiantcore/selection/textool/TextureToolSelectionSystem.cpp b/radiantcore/selection/textool/TextureToolSelectionSystem.cpp
index 2371613611..11037b34f0 100644
--- a/radiantcore/selection/textool/TextureToolSelectionSystem.cpp
+++ b/radiantcore/selection/textool/TextureToolSelectionSystem.cpp
@@ -9,6 +9,7 @@
#include "selection/SelectionPool.h"
#include "string/case_conv.h"
#include "math/Matrix3.h"
+#include "selection/algorithm/Texturing.h"
namespace textool
{
@@ -697,30 +698,11 @@ void TextureToolSelectionSystem::flipSelected(int axis)
// Move center to origin, flip around the specified axis, and move back
Vector2 flipCenter(selectionBounds.origin.x(), selectionBounds.origin.y());
- auto flipMatrix = Matrix3::getIdentity();
-
- if (axis == 0)
- {
- flipMatrix.xx() = -1;
- }
- else // axis == 1
- {
- flipMatrix.yy() = -1;
- }
-
- auto flipTransformation = Matrix3::getTranslation(-flipCenter);
- flipTransformation.premultiplyBy(flipMatrix);
- flipTransformation.premultiplyBy(Matrix3::getTranslation(+flipCenter));
UndoableCommand cmd("flipSelectedTexcoords " + string::to_string(axis));
- foreachSelectedNode([&](const INode::Ptr& node)
- {
- node->beginTransformation();
- node->transform(flipTransformation);
- node->commitTransformation();
- return true;
- });
+ selection::algorithm::TextureFlipper flipper(flipCenter, axis);
+ foreachSelectedNode(flipper);
radiant::TextureChangedMessage::Send();
}
diff --git a/tools/msvc/DarkRadiantCore.vcxproj b/tools/msvc/DarkRadiantCore.vcxproj
index a4e412a7ca..ab497dc39e 100644
--- a/tools/msvc/DarkRadiantCore.vcxproj
+++ b/tools/msvc/DarkRadiantCore.vcxproj
@@ -648,6 +648,7 @@
+
@@ -1003,6 +1004,7 @@
+
diff --git a/tools/msvc/DarkRadiantCore.vcxproj.filters b/tools/msvc/DarkRadiantCore.vcxproj.filters
index 85e3eea392..3ebbf6d242 100644
--- a/tools/msvc/DarkRadiantCore.vcxproj.filters
+++ b/tools/msvc/DarkRadiantCore.vcxproj.filters
@@ -1108,6 +1108,9 @@
src\selection\textool
+
+ src\selection\algorithm
+
@@ -2253,5 +2256,8 @@
src\selection\textool
+
+ src\selection\algorithm
+
\ No newline at end of file