summaryrefslogtreecommitdiff
path: root/game/network/network.impl.h
blob: dda4974e7473ca74c544712f780be3baf85bf47e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "network.h"
#include <game/geoData.h>
#include <gfx/gl/sceneShader.h>
#include <gfx/models/texture.h>

template<typename T, typename... Links>
void
NetworkOf<T, Links...>::joinLinks(const Link::Ptr & link) const
{
	for (const auto & oldLink : links) {
		Network::joinLinks(link, oldLink);
	}
}

template<typename T, typename... Links>
Link::Ptr
NetworkOf<T, Links...>::intersectRayLinks(const Ray<GlobalPosition3D> & ray) const
{
	// Click link
	if (const auto link = std::find_if(links.begin(), links.end(),
				[&ray](const std::shared_ptr<T> & link) {
					return link->intersectRay(ray);
				});
			link != links.end()) {
		return *link;
	}
	return {};
}

template<typename T, typename... Links>
float
NetworkOf<T, Links...>::findNodeDirection(Node::AnyCPtr n) const
{
	for (const auto & link : links) {
		for (const auto & end : link->ends) {
			// cppcheck-suppress useStlAlgorithm
			if (end.node.get() == n.get()) {
				return end.dir;
			}
		}
	}
	throw std::runtime_error("Node exists but couldn't find it");
}

template<typename T, typename... Links>
Link::Ptr
NetworkOf<T, Links...>::create(const GenStraightDef & def)
{
	return std::make_shared<typename T::StraightLink>(
			*this, candidateNodeAt(std::get<0>(def)).first, candidateNodeAt(std::get<1>(def)).first);
}

template<typename T, typename... Links>
Link::Ptr
NetworkOf<T, Links...>::create(const GenCurveDef & def)
{
	return std::make_shared<typename T::CurveLink>(
			*this, candidateNodeAt(std::get<0>(def)).first, candidateNodeAt(std::get<1>(def)).first, std::get<2>(def));
}

template<typename T, typename... Links>
bool
NetworkOf<T, Links...>::anyLinks() const
{
	return !(static_cast<const NetworkLinkHolder<Links> *>(this)->vertices.empty() && ...);
}

template<typename T, typename... Links>
void
NetworkOf<T, Links...>::add(GeoData * geoData, const Link::Ptr & link)
{
	const auto addIf = [this](auto && lptr) {
		if (lptr) {
			links.emplace(lptr);
			return true;
		}
		return false;
	};
	for (auto & end : link->ends) {
		end.node = nodeAt(end.node->pos);
	}
	if (!(addIf(std::dynamic_pointer_cast<Links>(link)) || ...)) {
		throw std::logic_error("Unsupported link type for network");
	}
	joinLinks(link);
	if (geoData) {
		geoData->setHeights(link->getBase(getBaseWidth()), GeoData::SetHeightsOpts {.surface = getBaseSurface()});
	}
}