diff --git a/libs/selectionlib.h b/libs/selectionlib.h index 5f0a248f5f..3cdba36518 100644 --- a/libs/selectionlib.h +++ b/libs/selectionlib.h @@ -4,6 +4,7 @@ #include "iselection.h" #include "ibrush.h" #include "igroupnode.h" +#include "iselectiongroup.h" #include "iscenegraph.h" #include "ientity.h" #include "ipatch.h" @@ -222,4 +223,30 @@ inline bool curSelectionIsSuitableForReparent() return true; } +// Replaces the group assignments of the given node with the given groups +inline void assignNodeToSelectionGroups(const scene::INodePtr& node, const IGroupSelectable::GroupIds& groups) +{ + auto groupSelectable = std::dynamic_pointer_cast(node); + + if (!groupSelectable) + { + return; + } + + const auto& groupIds = groupSelectable->getGroupIds(); + + auto previousGroups = groupSelectable->getGroupIds(); + + for (auto id : previousGroups) + { + groupSelectable->removeFromGroup(id); + } + + // Add one by one, keeping the order intact + for (auto id : groupIds) + { + groupSelectable->addToGroup(id); + } +} + } // namespace selection diff --git a/radiantcore/patch/algorithm/General.cpp b/radiantcore/patch/algorithm/General.cpp index f71634817a..c959fdb787 100644 --- a/radiantcore/patch/algorithm/General.cpp +++ b/radiantcore/patch/algorithm/General.cpp @@ -314,7 +314,13 @@ void weldPatches(const PatchNodePtr& patchNode1, const PatchNodePtr& patchNode2) patchNode1->getParent()->addChildNode(mergedPatch); mergedPatch->assignToLayers(patchNode1->getLayers()); - // TODO: selection grouping + + auto patch1GroupSelectable = std::dynamic_pointer_cast(patchNode1); + + if (patch1GroupSelectable) + { + selection::assignNodeToSelectionGroups(mergedPatch, patch1GroupSelectable->getGroupIds()); + } std::dynamic_pointer_cast(mergedPatch)->getPatch().scaleTextureNaturally(); diff --git a/test/PatchWelding.cpp b/test/PatchWelding.cpp index c13aa44b6e..803b29a212 100644 --- a/test/PatchWelding.cpp +++ b/test/PatchWelding.cpp @@ -2,6 +2,7 @@ #include "icommandsystem.h" #include "iselection.h" +#include "iselectiongroup.h" #include "ipatch.h" #include "algorithm/Scene.h" #include "scenelib.h" @@ -24,7 +25,7 @@ inline scene::INodePtr findPatchWithNumber(const std::string& number) return algorithm::findFirstPatchWithMaterial(GlobalMapModule().getRoot(), "textures/numbers/" + number); } -void performPatchWeldingTest(const std::string& number1, const std::string& number2, int expectedRows, int expectedCols) +scene::INodePtr performPatchWelding(const std::string& number1, const std::string& number2) { auto firstPatch = findPatchWithNumber(number1); auto secondPatch = findPatchWithNumber(number2); @@ -41,7 +42,12 @@ void performPatchWeldingTest(const std::string& number1, const std::string& numb EXPECT_FALSE(firstPatch->getParent()); EXPECT_FALSE(secondPatch->getParent()); - auto merged = std::dynamic_pointer_cast(GlobalSelectionSystem().ultimateSelected()); + return GlobalSelectionSystem().ultimateSelected(); +} + +void verifyPatchDimensions(const scene::INodePtr& mergedPatchNode, int expectedRows, int expectedCols) +{ + auto merged = std::dynamic_pointer_cast(mergedPatchNode); EXPECT_EQ(merged->getPatch().getHeight(), expectedRows); EXPECT_EQ(merged->getPatch().getWidth(), expectedCols); } @@ -78,7 +84,7 @@ TEST_P(PatchWelding3x3, WeldWithOther3x3Patch) auto expectedRows = std::get<2>(GetParam()); auto expectedColumns = std::get<3>(GetParam()); - performPatchWeldingTest(firstPatch, secondPatch, expectedRows, expectedColumns); + verifyPatchDimensions(performPatchWelding(firstPatch, secondPatch), expectedRows, expectedColumns); } // Patch 1 is sharing its first row @@ -148,7 +154,43 @@ TEST_F(PatchWeldingTest, WeldStackedCylinders) loadMap("weld_patches.mapx"); // Welding the two cylinders produce a 5rows x 9cols patch - performPatchWeldingTest("11", "12", 5, 9); + verifyPatchDimensions(performPatchWelding("11", "12"), 5, 9); +} + +TEST_F(PatchWeldingTest, WeldedPatchInheritsLayers) +{ + loadMap("weld_patches.mapx"); + + auto firstPatch = findPatchWithNumber("1"); + auto firstPatchLayers = firstPatch->getLayers(); + + // Check the setup + EXPECT_EQ(firstPatchLayers, scene::LayerList({ 0, 1 })) << "Patch 1 doesn't have the layers it's expected to, test map changed?"; + + // Patch 1 has layers (Default,2), Patch 2 has Layer 2 only + // After merging we expect the merged patch to have the layers as patch 1 had + auto mergedNode = performPatchWelding("1", "2"); + + EXPECT_EQ(mergedNode->getLayers(), firstPatchLayers); +} + +TEST_F(PatchWeldingTest, WeldedPatchInheritsSelectionGroups) +{ + loadMap("weld_patches.mapx"); + + auto firstPatch = findPatchWithNumber("1"); + + auto firstPatchSelectionGroup = std::dynamic_pointer_cast(firstPatch); + auto firstPatchGroups = firstPatchSelectionGroup->getGroupIds(); + + // Check the setup + //EXPECT_EQ(firstPatch, scene::LayerList({ 0, 1 })) << "Patch 1 doesn't have the layers it's expected to, test map changed?"; + + // After merging we expect the merged patch to have the same groups as patch 1 had + auto mergedNode = performPatchWelding("1", "2"); + auto mergedNodeSelectionGroup = std::dynamic_pointer_cast(firstPatch); + + EXPECT_EQ(mergedNodeSelectionGroup->getGroupIds(), firstPatchGroups); } }