From 9fd25e8b10b1291525a18c8b3e34256ca6151dd6 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Mar 2025 11:50:31 +0000 Subject: Add ManyPtr which tracks specified subclasses This removes the need to repeated dynamic_cast the pointer. Provides interface which enforces the fastest option for the required types. --- ui/gameMainWindow.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index d88bab5..b58f3dc 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -75,9 +75,9 @@ GameMainWindow::render() const void GameMainWindow::content(const SceneShader & shader, const Frustum & frustum) const { - for (const auto & [id, asset] : gameState->assets) { - if (const auto r = std::dynamic_pointer_cast(asset)) { - r->render(shader, frustum); + for (const auto & [assetId, asset] : gameState->assets) { + if (const auto renderable = asset.getAs()) { + renderable->render(shader, frustum); } } gameState->world.apply(&Renderable::render, shader, frustum); @@ -99,9 +99,9 @@ GameMainWindow::lights(const SceneShader & shader) const void GameMainWindow::shadows(const ShadowMapper & shadowMapper, const Frustum & frustum) const { - for (const auto & [id, asset] : gameState->assets) { - if (const auto r = std::dynamic_pointer_cast(asset)) { - r->shadows(shadowMapper, frustum); + for (const auto & [assetId, asset] : gameState->assets) { + if (const auto renderable = asset.getAs()) { + renderable->shadows(shadowMapper, frustum); } } gameState->world.apply(&Renderable::shadows, shadowMapper, frustum); -- cgit v1.2.3 From fcca8bc835db65ac170d1148d52a815df8838d53 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Mar 2025 12:17:57 +0000 Subject: Invert how shared/unique is specified for Collection Template param is a pointer now, typedefs added for ease. --- game/gamestate.h | 2 +- game/network/network.h | 2 +- game/orders.h | 2 +- game/vehicles/train.h | 2 +- game/water.h | 2 +- lib/collection.h | 9 ++++++--- test/test-assetFactory.cpp | 2 +- test/test-collection.cpp | 6 +++--- ui/editNetwork.h | 2 +- ui/gameMainWindow.cpp | 2 +- ui/mainApplication.h | 2 +- ui/toolbar.h | 2 +- ui/windowContent.h | 2 +- 13 files changed, 20 insertions(+), 17 deletions(-) (limited to 'ui') diff --git a/game/gamestate.h b/game/gamestate.h index 189417d..c5ad239 100644 --- a/game/gamestate.h +++ b/game/gamestate.h @@ -16,7 +16,7 @@ public: NO_MOVE(GameState); NO_COPY(GameState); - Collection world; + SharedCollection world; std::shared_ptr terrain; std::shared_ptr environment; AssetFactory::Assets assets; diff --git a/game/network/network.h b/game/network/network.h index 291c4ec..73c3788 100644 --- a/game/network/network.h +++ b/game/network/network.h @@ -77,7 +77,7 @@ class NetworkOf : public Network, public Renderable, public NetworkLinkHolder
  • links; + SharedCollection links; void joinLinks(const Link::Ptr &) const; protected: diff --git a/game/orders.h b/game/orders.h index ca5cfdb..840aa3c 100644 --- a/game/orders.h +++ b/game/orders.h @@ -5,7 +5,7 @@ class Objective; -class Orders : public Collection { +class Orders : public SharedCollection { public: [[nodiscard]] Objective * current() const; Objective * next(); diff --git a/game/vehicles/train.h b/game/vehicles/train.h index 4933347..88e30f9 100644 --- a/game/vehicles/train.h +++ b/game/vehicles/train.h @@ -15,7 +15,7 @@ class SceneShader; class ShadowMapper; template class Ray; -class Train : public Vehicle, public Collection, public Can, public Can { +class Train : public Vehicle, public UniqueCollection, public Can, public Can { public: explicit Train(const Link::CPtr & link, float linkDist = 0) : Vehicle {link, linkDist} { } diff --git a/game/water.h b/game/water.h index f9fe080..07d9ae1 100644 --- a/game/water.h +++ b/game/water.h @@ -29,6 +29,6 @@ private: void generateMeshes(); std::shared_ptr geoData; - Collection, false> meshes; + UniqueCollection> meshes; Texture::Ptr water; }; diff --git a/lib/collection.h b/lib/collection.h index 6802bcb..2deefb9 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -6,11 +6,11 @@ #include #include -template class Collection { +template class Collection { public: virtual ~Collection() = default; - using Ptr = std::conditional_t, std::unique_ptr>; + using Object = Ptr::element_type; using Objects = std::vector; Objects objects; @@ -19,7 +19,7 @@ public: create(Params &&... params) requires std::is_base_of_v { - if constexpr (shared) { + if constexpr (requires(Ptr ptr) { ptr = std::make_shared(std::forward(params)...); }) { auto obj = std::make_shared(std::forward(params)...); objects.emplace_back(obj); return obj; @@ -129,3 +129,6 @@ protected: }); } }; + +template using SharedCollection = Collection>; +template using UniqueCollection = Collection>; diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 03319da..72f13b3 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -71,7 +71,7 @@ public: sceneRenderer.render(*this); } - Collection objects; + SharedCollection objects; private: SceneRenderer sceneRenderer; diff --git a/test/test-collection.cpp b/test/test-collection.cpp index 00204fc..00298bb 100644 --- a/test/test-collection.cpp +++ b/test/test-collection.cpp @@ -34,10 +34,10 @@ public: } }; -using TestCollection = Collection; +using TestCollection = SharedCollection; -BOOST_TEST_DONT_PRINT_LOG_VALUE(Collection::Objects::const_iterator) -BOOST_TEST_DONT_PRINT_LOG_VALUE(Collection::Objects::const_reverse_iterator) +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_iterator) +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_reverse_iterator) BOOST_FIXTURE_TEST_SUITE(tc, TestCollection) diff --git a/ui/editNetwork.h b/ui/editNetwork.h index ae887bd..2fc102a 100644 --- a/ui/editNetwork.h +++ b/ui/editNetwork.h @@ -36,7 +36,7 @@ public: using Ptr = std::unique_ptr; protected: - Collection candidateLinks; + SharedCollection candidateLinks; }; private: diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index b58f3dc..07901b3 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -32,7 +32,7 @@ GameMainWindow::GameMainWindow(size_t w, size_t h) : WindowContent {w, h}, Scene { uiComponents.create(glm::vec2 {310'727'624, 494'018'810}); auto gms = uiComponents.create(&camera, ScreenAbsCoord {w, h}); - uiComponents.create(gms.get()); + uiComponents.create(gms); } GameMainWindow::~GameMainWindow() { } diff --git a/ui/mainApplication.h b/ui/mainApplication.h index a6cb126..1489587 100644 --- a/ui/mainApplication.h +++ b/ui/mainApplication.h @@ -6,7 +6,7 @@ class MainApplication : public ApplicationBase { public: - using Windows = Collection; + using Windows = SharedCollection; void mainLoop(); protected: diff --git a/ui/toolbar.h b/ui/toolbar.h index ea560f5..b0480e2 100644 --- a/ui/toolbar.h +++ b/ui/toolbar.h @@ -19,5 +19,5 @@ public: bool handleInput(const SDL_Event & e, const Position & parentPos) override; - Collection icons; + UniqueCollection icons; }; diff --git a/ui/windowContent.h b/ui/windowContent.h index 474445a..5437da6 100644 --- a/ui/windowContent.h +++ b/ui/windowContent.h @@ -21,6 +21,6 @@ public: virtual bool handleInput(const SDL_Event & e); protected: - ::Collection uiComponents; + UniqueCollection uiComponents; UIShader uiShader; }; -- cgit v1.2.3 From 163c8f75265054a168cc1e2750a0adb40fb08d83 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Mar 2025 13:01:14 +0000 Subject: Make Collections::objects protected, extend interface Keeps all required features accessible, but through a controlled interface. --- application/main.cpp | 2 +- game/network/network.impl.h | 8 +++--- game/network/rail.cpp | 2 +- lib/collection.h | 44 +++++++++++++++++++++++++++-- test/test-assetFactory.cpp | 10 +++---- test/test-network.cpp | 68 ++++++++++++++++++++++----------------------- ui/builders/freeExtend.cpp | 4 +-- ui/builders/join.cpp | 2 +- ui/builders/straight.cpp | 2 +- 9 files changed, 90 insertions(+), 52 deletions(-) (limited to 'ui') diff --git a/application/main.cpp b/application/main.cpp index 514fab6..1ca2192 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -113,7 +113,7 @@ public: mainLoop(); - world.objects.clear(); + world.removeAll(); return 0; } }; diff --git a/game/network/network.impl.h b/game/network/network.impl.h index 0a2f9ca..294f696 100644 --- a/game/network/network.impl.h +++ b/game/network/network.impl.h @@ -8,7 +8,7 @@ template void NetworkOf::joinLinks(const Link::Ptr & l) const { - for (const auto & ol : links.objects) { + for (const auto & ol : links) { Network::joinLinks(l, ol); } } @@ -18,11 +18,11 @@ Link::Ptr NetworkOf::intersectRayLinks(const Ray & ray) const { // Click link - if (const auto link = std::find_if(links.objects.begin(), links.objects.end(), + if (const auto link = std::find_if(links.begin(), links.end(), [&ray](const std::shared_ptr & link) { return link->intersectRay(ray); }); - link != links.objects.end()) { + link != links.end()) { return *link; } return {}; @@ -32,7 +32,7 @@ template float NetworkOf::findNodeDirection(Node::AnyCPtr n) const { - for (const auto & l : links.objects) { + for (const auto & l : links) { for (const auto & e : l->ends) { // cppcheck-suppress useStlAlgorithm if (e.node.get() == n.get()) { diff --git a/game/network/rail.cpp b/game/network/rail.cpp index 5ce6036..dfe1dca 100644 --- a/game/network/rail.cpp +++ b/game/network/rail.cpp @@ -168,7 +168,7 @@ namespace { void RailLinks::render(const SceneShader & shader, const Frustum &) const { - if (!links.objects.empty()) { + if (!links.empty()) { texture->bind(); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1, 0); diff --git a/lib/collection.h b/lib/collection.h index 2deefb9..c843bad 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -12,7 +12,19 @@ public: using Object = Ptr::element_type; using Objects = std::vector; - Objects objects; + + Collection & + operator=(Objects && other) + { + objects = std::move(other); + return *this; + } + + const Ptr & + operator[](size_t idx) const + { + return objects[idx]; + } template auto @@ -91,19 +103,45 @@ public: }); } - auto + [[nodiscard]] auto + begin() const + { + return objects.begin(); + } + + [[nodiscard]] auto end() const { return objects.end(); } - auto + [[nodiscard]] auto + rbegin() const + { + return objects.rbegin(); + } + + [[nodiscard]] auto rend() const { return objects.rend(); } + [[nodiscard]] bool + empty() const + { + return objects.empty(); + } + + auto + emplace(Ptr && ptr) + { + return objects.emplace_back(std::move(ptr)); + } + protected: + Objects objects; + template auto apply_internal(const auto begin, const auto end, const auto & m, Params &&... params) const diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 72f13b3..68ce6a6 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(brush47xml, *boost::unit_test::timeout(5)) BOOST_REQUIRE(brush47rvc->bogies.back()); auto railVehicle = std::make_shared(brush47rvc); - objects.objects.push_back(brush47rvc); + objects.emplace(brush47rvc); render(10000); } @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) auto plant2 = std::make_shared(tree_01_1_f, Location {{3000, -4000, 0}, {0, 1, 0}}); auto plant3 = std::make_shared(tree_01_1_f, Location {{-2000, -4000, 0}, {0, 2, 0}}); auto plant4 = std::make_shared(tree_01_1_f, Location {{3000, 2000, 0}, {0, 3, 0}}); - objects.objects.push_back(tree_01_1_f); + objects.emplace(tree_01_1_f); render(6000); } @@ -160,13 +160,13 @@ BOOST_AUTO_TEST_CASE(lights, *boost::unit_test::timeout(5)) auto light2 = std::make_shared(rlight_f, Location {{-4000, 0, 0}, {0, 2, 0}}); auto light3 = std::make_shared(rlight_f, Location {{-4000, -4000, 0}, {0, 1, 0}}); auto light4 = std::make_shared(oldlamp_f, Location {{3000, 4600, 0}, {0, 2, 0}}); - objects.objects.push_back(rlight_f); - objects.objects.push_back(oldlamp_f); + objects.emplace(rlight_f); + objects.emplace(oldlamp_f); // yes I'm hacking some floor to light up as though its a bush auto floorf = mf->assets.at("floor").dynamicCast(); auto floor = std::make_shared(floorf, Location {}); - objects.objects.push_back(floorf); + objects.emplace(floorf); render(6000); } diff --git a/test/test-network.cpp b/test/test-network.cpp index 51fea8b..19a740e 100644 --- a/test/test-network.cpp +++ b/test/test-network.cpp @@ -139,83 +139,83 @@ BOOST_DATA_TEST_CASE(newNodeAt_new, INVALID_NODES, p) BOOST_AUTO_TEST_CASE(network_joins) { // Ends - BOOST_CHECK(links.objects[2]->ends[1].nexts.empty()); + BOOST_CHECK(links[2]->ends[1].nexts.empty()); // Join 0 <-> 1 - BOOST_REQUIRE_EQUAL(links.objects[0]->ends[1].nexts.size(), 2); - BOOST_CHECK_EQUAL(links.objects[0]->ends[1].nexts[0].first.lock().get(), links.objects[1].get()); - BOOST_CHECK_EQUAL(links.objects[0]->ends[1].nexts[0].second, 0); - BOOST_CHECK_EQUAL(links.objects[0]->ends[1].nexts[1].first.lock().get(), links.objects[5].get()); - BOOST_CHECK_EQUAL(links.objects[0]->ends[1].nexts[1].second, 0); - BOOST_REQUIRE_EQUAL(links.objects[1]->ends[0].nexts.size(), 2); - BOOST_CHECK_EQUAL(links.objects[1]->ends[0].nexts[0].first.lock().get(), links.objects[0].get()); - BOOST_CHECK_EQUAL(links.objects[1]->ends[0].nexts[0].second, 1); - BOOST_CHECK_EQUAL(links.objects[1]->ends[0].nexts[1].first.lock().get(), links.objects[5].get()); - BOOST_CHECK_EQUAL(links.objects[1]->ends[0].nexts[1].second, 0); + BOOST_REQUIRE_EQUAL(links[0]->ends[1].nexts.size(), 2); + BOOST_CHECK_EQUAL(links[0]->ends[1].nexts[0].first.lock().get(), links[1].get()); + BOOST_CHECK_EQUAL(links[0]->ends[1].nexts[0].second, 0); + BOOST_CHECK_EQUAL(links[0]->ends[1].nexts[1].first.lock().get(), links[5].get()); + BOOST_CHECK_EQUAL(links[0]->ends[1].nexts[1].second, 0); + BOOST_REQUIRE_EQUAL(links[1]->ends[0].nexts.size(), 2); + BOOST_CHECK_EQUAL(links[1]->ends[0].nexts[0].first.lock().get(), links[0].get()); + BOOST_CHECK_EQUAL(links[1]->ends[0].nexts[0].second, 1); + BOOST_CHECK_EQUAL(links[1]->ends[0].nexts[1].first.lock().get(), links[5].get()); + BOOST_CHECK_EQUAL(links[1]->ends[0].nexts[1].second, 0); // Join 1 <-> 2 - BOOST_REQUIRE_EQUAL(links.objects[1]->ends[1].nexts.size(), 2); - BOOST_CHECK_EQUAL(links.objects[1]->ends[1].nexts[0].first.lock().get(), links.objects[2].get()); - BOOST_CHECK_EQUAL(links.objects[1]->ends[1].nexts[0].second, 0); - BOOST_REQUIRE_EQUAL(links.objects[2]->ends[0].nexts.size(), 2); - BOOST_CHECK_EQUAL(links.objects[2]->ends[0].nexts[0].first.lock().get(), links.objects[1].get()); - BOOST_CHECK_EQUAL(links.objects[2]->ends[0].nexts[0].second, 1); + BOOST_REQUIRE_EQUAL(links[1]->ends[1].nexts.size(), 2); + BOOST_CHECK_EQUAL(links[1]->ends[1].nexts[0].first.lock().get(), links[2].get()); + BOOST_CHECK_EQUAL(links[1]->ends[1].nexts[0].second, 0); + BOOST_REQUIRE_EQUAL(links[2]->ends[0].nexts.size(), 2); + BOOST_CHECK_EQUAL(links[2]->ends[0].nexts[0].first.lock().get(), links[1].get()); + BOOST_CHECK_EQUAL(links[2]->ends[0].nexts[0].second, 1); } BOOST_DATA_TEST_CASE(routeTo_nodeNotInNetwork, INVALID_NODES, dest) { - const auto & start = links.objects.front()->ends[1]; + const auto & start = links[0]->ends[1]; BOOST_CHECK_THROW((void)routeFromTo(start, dest), std::out_of_range); } BOOST_AUTO_TEST_CASE(routeTo_noSteps) { - const auto & start = links.objects.front()->ends[1]; + const auto & start = links[0]->ends[1]; auto r = this->routeFromTo(start, p100); BOOST_CHECK(r.empty()); } BOOST_AUTO_TEST_CASE(routeTo_upStream_to2) { - const auto & start = links.objects.front()->ends[1]; + const auto & start = links[0]->ends[1]; auto r = this->routeFromTo(start, p200); BOOST_REQUIRE_EQUAL(r.size(), 1); - BOOST_CHECK_EQUAL(r[0].first.lock().get(), links.objects[1].get()); + BOOST_CHECK_EQUAL(r[0].first.lock().get(), links[1].get()); } BOOST_AUTO_TEST_CASE(routeTo_upStream_to3) { - const auto & start = links.objects[0]->ends[1]; + const auto & start = links[0]->ends[1]; auto r = this->routeFromTo(start, p300); BOOST_REQUIRE_EQUAL(r.size(), 2); - BOOST_CHECK_EQUAL(r[0].first.lock().get(), links.objects[1].get()); - BOOST_CHECK_EQUAL(r[1].first.lock().get(), links.objects[2].get()); + BOOST_CHECK_EQUAL(r[0].first.lock().get(), links[1].get()); + BOOST_CHECK_EQUAL(r[1].first.lock().get(), links[2].get()); } BOOST_AUTO_TEST_CASE(routeTo_downStream_to0) { - const auto & start = links.objects[2]->ends[0]; + const auto & start = links[2]->ends[0]; auto r = this->routeFromTo(start, p000); BOOST_REQUIRE_EQUAL(r.size(), 2); - BOOST_CHECK_EQUAL(r[0].first.lock().get(), links.objects[1].get()); - BOOST_CHECK_EQUAL(r[1].first.lock().get(), links.objects[0].get()); + BOOST_CHECK_EQUAL(r[0].first.lock().get(), links[1].get()); + BOOST_CHECK_EQUAL(r[1].first.lock().get(), links[0].get()); } BOOST_AUTO_TEST_CASE(routeTo_upStream_3to300) { - const auto & start = links.objects[3]->ends[1]; + const auto & start = links[3]->ends[1]; auto r = this->routeFromTo(start, p300); BOOST_REQUIRE_EQUAL(r.size(), 2); - BOOST_CHECK_EQUAL(r[0].first.lock().get(), links.objects[4].get()); - BOOST_CHECK_EQUAL(r[1].first.lock().get(), links.objects[2].get()); + BOOST_CHECK_EQUAL(r[0].first.lock().get(), links[4].get()); + BOOST_CHECK_EQUAL(r[1].first.lock().get(), links[2].get()); } BOOST_AUTO_TEST_CASE(routeTo_downStream_3to300) { - const auto & start = links.objects[3]->ends[0]; + const auto & start = links[3]->ends[0]; auto r = this->routeFromTo(start, p300); BOOST_REQUIRE_EQUAL(r.size(), 3); - BOOST_CHECK_EQUAL(r[0].first.lock().get(), links.objects[0].get()); - BOOST_CHECK_EQUAL(r[1].first.lock().get(), links.objects[1].get()); - BOOST_CHECK_EQUAL(r[2].first.lock().get(), links.objects[2].get()); + BOOST_CHECK_EQUAL(r[0].first.lock().get(), links[0].get()); + BOOST_CHECK_EQUAL(r[1].first.lock().get(), links[1].get()); + BOOST_CHECK_EQUAL(r[2].first.lock().get(), links[2].get()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/ui/builders/freeExtend.cpp b/ui/builders/freeExtend.cpp index ab5a998..09e1c75 100644 --- a/ui/builders/freeExtend.cpp +++ b/ui/builders/freeExtend.cpp @@ -16,10 +16,10 @@ BuilderFreeExtend::move( { if (p1) { if (const auto p = network->intersectRayNodes(ray)) { - candidateLinks.objects = network->candidateJoins(*p1, p->pos); + candidateLinks = network->candidateJoins(*p1, p->pos); } else if (const auto p = geoData->intersectRay(ray)) { - candidateLinks.objects = network->candidateExtend(*p1, p->first); + candidateLinks = network->candidateExtend(*p1, p->first); } else { candidateLinks.removeAll(); diff --git a/ui/builders/join.cpp b/ui/builders/join.cpp index 6941e23..161b081 100644 --- a/ui/builders/join.cpp +++ b/ui/builders/join.cpp @@ -15,7 +15,7 @@ BuilderJoin::move(Network * network, const GeoData *, const SDL_MouseMotionEvent { if (p1) { if (const auto p = network->intersectRayNodes(ray)) { - candidateLinks.objects = network->candidateJoins(p1->pos, p->pos); + candidateLinks = network->candidateJoins(p1->pos, p->pos); } else { candidateLinks.removeAll(); diff --git a/ui/builders/straight.cpp b/ui/builders/straight.cpp index 338aa8a..6815689 100644 --- a/ui/builders/straight.cpp +++ b/ui/builders/straight.cpp @@ -17,7 +17,7 @@ BuilderStraight::move( { if (p1) { if (const auto p = geoData->intersectRay(ray)) { - candidateLinks.objects = network->candidateStraight(*p1, p->first); + candidateLinks = network->candidateStraight(*p1, p->first); } else { candidateLinks.removeAll(); -- cgit v1.2.3 From 035299f23a9207bb521b19e2f77154c276cf3033 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 23 Mar 2025 14:21:12 +0000 Subject: Other objects support in removeAll/clear removeAll requires a type that is one of Others, clear clears everything regardless of type. --- application/main.cpp | 4 ++-- lib/collection.h | 11 ++++++++++- test/test-collection.cpp | 24 ++++++++++++++++++++++++ ui/builders/freeExtend.cpp | 4 ++-- ui/builders/join.cpp | 4 ++-- ui/builders/straight.cpp | 6 +++--- 6 files changed, 43 insertions(+), 10 deletions(-) (limited to 'ui') diff --git a/application/main.cpp b/application/main.cpp index 1ca2192..9120376 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -90,7 +90,7 @@ public: for (int N = 0; N < 6; N++) { train->create(b47); } - train->orders.removeAll(); + train->orders.clear(); train->orders.create(&train->orders); train->currentActivity = train->orders.current()->createActivity(); @@ -113,7 +113,7 @@ public: mainLoop(); - world.removeAll(); + world.clear(); return 0; } }; diff --git a/lib/collection.h b/lib/collection.h index 329b681..98f043b 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -103,15 +103,24 @@ public: return applyOne_internal(objects.rbegin(), objects.rend(), m, std::forward(params)...); } - template + template + requires(std::is_convertible_v || ...) auto removeAll() { + std::get>(otherObjects).clear(); return std::erase_if(objects, [](auto && op) { return dynamic_cast(op.get()); }); } + void + clear() + { + ((std::get>(otherObjects).clear()), ...); + objects.clear(); + } + [[nodiscard]] auto begin() const { diff --git a/test/test-collection.cpp b/test/test-collection.cpp index 0cd08d5..13df95c 100644 --- a/test/test-collection.cpp +++ b/test/test-collection.cpp @@ -143,6 +143,30 @@ BOOST_AUTO_TEST_CASE(move_assign) BOOST_CHECK(other.empty()); } +BOOST_AUTO_TEST_CASE(clearAll) +{ + create(); + create(); + emplace(std::make_unique()); + emplace(std::make_unique()); + + clear(); + BOOST_CHECK(objects.empty()); + BOOST_CHECK(std::get>(otherObjects).empty()); +} + +BOOST_AUTO_TEST_CASE(removeAllOfSub) +{ + create(); + create(); + emplace(std::make_unique()); + emplace(std::make_unique()); + + removeAll(); + BOOST_CHECK_EQUAL(objects.size(), 2); + BOOST_CHECK(std::get>(otherObjects).empty()); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_FIXTURE_TEST_SUITE(btc, UniqueCollection) diff --git a/ui/builders/freeExtend.cpp b/ui/builders/freeExtend.cpp index 09e1c75..aff7cd7 100644 --- a/ui/builders/freeExtend.cpp +++ b/ui/builders/freeExtend.cpp @@ -22,11 +22,11 @@ BuilderFreeExtend::move( candidateLinks = network->candidateExtend(*p1, p->first); } else { - candidateLinks.removeAll(); + candidateLinks.clear(); } } else { - candidateLinks.removeAll(); + candidateLinks.clear(); } } diff --git a/ui/builders/join.cpp b/ui/builders/join.cpp index 161b081..f6cbce5 100644 --- a/ui/builders/join.cpp +++ b/ui/builders/join.cpp @@ -18,7 +18,7 @@ BuilderJoin::move(Network * network, const GeoData *, const SDL_MouseMotionEvent candidateLinks = network->candidateJoins(p1->pos, p->pos); } else { - candidateLinks.removeAll(); + candidateLinks.clear(); } } } @@ -33,7 +33,7 @@ BuilderJoin::click( if (p1) { create(network, geoData, p1, p); p1.reset(); - candidateLinks.removeAll(); + candidateLinks.clear(); } else { p1 = p; diff --git a/ui/builders/straight.cpp b/ui/builders/straight.cpp index 6815689..e7d83b5 100644 --- a/ui/builders/straight.cpp +++ b/ui/builders/straight.cpp @@ -20,7 +20,7 @@ BuilderStraight::move( candidateLinks = network->candidateStraight(*p1, p->first); } else { - candidateLinks.removeAll(); + candidateLinks.clear(); } } } @@ -34,7 +34,7 @@ BuilderStraight::click( if (const auto p = geoData->intersectRay(ray)) { if (p1) { create(network, geoData, *p1, p->first); - candidateLinks.removeAll(); + candidateLinks.clear(); p1.reset(); } else { @@ -44,7 +44,7 @@ BuilderStraight::click( return; case SDL_BUTTON_MIDDLE: p1.reset(); - candidateLinks.removeAll(); + candidateLinks.clear(); return; } } -- cgit v1.2.3 From ae99a2124da32e4d2474e6dc6cf54322b688b743 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 24 Mar 2025 18:10:30 +0000 Subject: Use is_base_of_v instead of is_convertible_v to choose OtherObjects --- lib/collection.h | 6 +++--- test/test-collection.cpp | 4 ++++ ui/gameMainWindow.cpp | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/lib/collection.h b/lib/collection.h index b786e2f..8e9cf1a 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -236,12 +236,12 @@ protected: } template - requires((std::is_convertible_v || ...)) + requires((std::is_base_of_v || ...)) [[nodiscard]] consteval static bool idx() { size_t typeIdx = 0; - return ((typeIdx++ && std::is_convertible_v) || ...); + return ((typeIdx++ && std::is_base_of_v) || ...); } template @@ -249,7 +249,7 @@ protected: constexpr const auto & containerFor() const { - if constexpr ((std::is_convertible_v || ...)) { + if constexpr ((std::is_base_of_v || ...)) { return std::get()>(otherObjects); } else { diff --git a/test/test-collection.cpp b/test/test-collection.cpp index a399845..90a3bd1 100644 --- a/test/test-collection.cpp +++ b/test/test-collection.cpp @@ -113,6 +113,10 @@ BOOST_AUTO_TEST_CASE(a_sub) BOOST_AUTO_TEST_CASE(filter) { + static_assert(TestCollection::idx() == 0); + static_assert(TestCollection::idx() == 0); + static_assert(TestCollection::idx() == 0); + static_assert(TestCollection::idx() == 0); create(); BOOST_CHECK_EQUAL(1, apply(&Base::yes)); BOOST_CHECK_EQUAL(0, apply(&Base::yes)); diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index 07901b3..f8c568b 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -80,7 +80,7 @@ GameMainWindow::content(const SceneShader & shader, const Frustum & frustum) con renderable->render(shader, frustum); } } - gameState->world.apply(&Renderable::render, shader, frustum); + gameState->world.apply(&Renderable::render, shader, frustum); uiComponents.apply(&WorldOverlay::render, shader, frustum); } @@ -93,7 +93,7 @@ GameMainWindow::environment(const SceneShader &, const SceneRenderer & r) const void GameMainWindow::lights(const SceneShader & shader) const { - gameState->world.apply(&Renderable::lights, shader); + gameState->world.apply(&Renderable::lights, shader); } void @@ -104,5 +104,5 @@ GameMainWindow::shadows(const ShadowMapper & shadowMapper, const Frustum & frust renderable->shadows(shadowMapper, frustum); } } - gameState->world.apply(&Renderable::shadows, shadowMapper, frustum); + gameState->world.apply(&Renderable::shadows, shadowMapper, frustum); } -- cgit v1.2.3