From 9fd25e8b10b1291525a18c8b3e34256ca6151dd6 Mon Sep 17 00:00:00 2001
From: Dan Goodliffe <dan@randomdan.homeip.net>
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.
---
 application/main.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'application')

diff --git a/application/main.cpp b/application/main.cpp
index 723f3d2..514fab6 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -86,7 +86,7 @@ public:
 			}
 
 			const std::shared_ptr<Train> train = world.create<Train>(l3, 800000);
-			auto b47 = std::dynamic_pointer_cast<RailVehicleClass>(assets.at("brush-47"));
+			auto b47 = assets.at("brush-47").dynamicCast<RailVehicleClass>();
 			for (int N = 0; N < 6; N++) {
 				train->create<RailVehicle>(b47);
 			}
@@ -101,8 +101,9 @@ public:
 			std::uniform_int_distribution<int> treeVariantDistribution {1, 4};
 			for (auto x = 311000000; x < 311830000; x += 5000) {
 				for (auto y = 491100000; y < 491130000; y += 5000) {
-					world.create<Plant>(std::dynamic_pointer_cast<Foliage>(assets.at(std::format("Tree-{:#02}-{}",
-												treeDistribution(randomdev), treeVariantDistribution(randomdev)))),
+					world.create<Plant>(assets.at(std::format("Tree-{:#02}-{}", treeDistribution(randomdev),
+														  treeVariantDistribution(randomdev)))
+												.dynamicCast<Foliage>(),
 							Location {terrain->positionAt({{x + positionOffsetDistribution(randomdev),
 											  y + positionOffsetDistribution(randomdev)}}),
 									{0, rotationDistribution(randomdev), 0}});
-- 
cgit v1.2.3


From 163c8f75265054a168cc1e2750a0adb40fb08d83 Mon Sep 17 00:00:00 2001
From: Dan Goodliffe <dan@randomdan.homeip.net>
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 'application')

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<typename T, typename... Links>
 void
 NetworkOf<T, Links...>::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<T, Links...>::intersectRayLinks(const Ray<GlobalPosition3D> & 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<T> & link) {
 					return link->intersectRay(ray);
 				});
-			link != links.objects.end()) {
+			link != links.end()) {
 		return *link;
 	}
 	return {};
@@ -32,7 +32,7 @@ template<typename T, typename... Links>
 float
 NetworkOf<T, Links...>::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<Ptr>;
-	Objects objects;
+
+	Collection &
+	operator=(Objects && other)
+	{
+		objects = std::move(other);
+		return *this;
+	}
+
+	const Ptr &
+	operator[](size_t idx) const
+	{
+		return objects[idx];
+	}
 
 	template<typename T = Object, typename... Params>
 	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<typename T = Object, typename... Params>
 	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<RailVehicle>(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<Plant>(tree_01_1_f, Location {{3000, -4000, 0}, {0, 1, 0}});
 	auto plant3 = std::make_shared<Plant>(tree_01_1_f, Location {{-2000, -4000, 0}, {0, 2, 0}});
 	auto plant4 = std::make_shared<Plant>(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<Light>(rlight_f, Location {{-4000, 0, 0}, {0, 2, 0}});
 	auto light3 = std::make_shared<Light>(rlight_f, Location {{-4000, -4000, 0}, {0, 1, 0}});
 	auto light4 = std::make_shared<Light>(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<Foliage>();
 	auto floor = std::make_shared<Plant>(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 <dan@randomdan.homeip.net>
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 'application')

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<RailVehicle>(b47);
 			}
-			train->orders.removeAll();
+			train->orders.clear();
 			train->orders.create<FreeRoam>(&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<T>(objects.rbegin(), objects.rend(), m, std::forward<Params>(params)...);
 	}
 
-	template<typename T = Object>
+	template<typename T>
+		requires(std::is_convertible_v<T *, Others *> || ...)
 	auto
 	removeAll()
 	{
+		std::get<OtherObjects<T>>(otherObjects).clear();
 		return std::erase_if(objects, [](auto && op) {
 			return dynamic_cast<T *>(op.get());
 		});
 	}
 
+	void
+	clear()
+	{
+		((std::get<OtherObjects<Others>>(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<Base>();
+	create<Sub>();
+	emplace(std::make_unique<Base>());
+	emplace(std::make_unique<Sub>());
+
+	clear();
+	BOOST_CHECK(objects.empty());
+	BOOST_CHECK(std::get<OtherObjects<Sub>>(otherObjects).empty());
+}
+
+BOOST_AUTO_TEST_CASE(removeAllOfSub)
+{
+	create<Base>();
+	create<Sub>();
+	emplace(std::make_unique<Base>());
+	emplace(std::make_unique<Sub>());
+
+	removeAll<Sub>();
+	BOOST_CHECK_EQUAL(objects.size(), 2);
+	BOOST_CHECK(std::get<OtherObjects<Sub>>(otherObjects).empty());
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 BOOST_FIXTURE_TEST_SUITE(btc, UniqueCollection<Base>)
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