mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-18 19:03:28 +00:00
added events
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "omath/linear_algebra/vector3.hpp"
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -29,10 +30,20 @@ namespace omath::pathfinding
|
||||
[[nodiscard]]
|
||||
bool empty() const;
|
||||
|
||||
// Events -- per-vertex optional tag (e.g. "jump", "teleport")
|
||||
void set_event(const Vector3<float>& vertex, std::string event_id);
|
||||
void clear_event(const Vector3<float>& vertex);
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<std::string> get_event(const Vector3<float>& vertex) const noexcept;
|
||||
|
||||
[[nodiscard]] std::string serialize() const noexcept;
|
||||
|
||||
void deserialize(const std::string& raw);
|
||||
|
||||
std::unordered_map<Vector3<float>, std::vector<Vector3<float>>> m_vertex_map;
|
||||
|
||||
private:
|
||||
std::unordered_map<Vector3<float>, std::string> m_vertex_events;
|
||||
};
|
||||
} // namespace omath::pathfinding
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace omath::pathfinding
|
||||
{
|
||||
std::expected<Vector3<float>, std::string>
|
||||
@@ -29,13 +30,40 @@ namespace omath::pathfinding
|
||||
return m_vertex_map.empty();
|
||||
}
|
||||
|
||||
void NavigationMesh::set_event(const Vector3<float>& vertex, std::string event_id)
|
||||
{
|
||||
m_vertex_events[vertex] = std::move(event_id);
|
||||
}
|
||||
|
||||
void NavigationMesh::clear_event(const Vector3<float>& vertex)
|
||||
{
|
||||
m_vertex_events.erase(vertex);
|
||||
}
|
||||
|
||||
std::optional<std::string> NavigationMesh::get_event(const Vector3<float>& vertex) const noexcept
|
||||
{
|
||||
const auto it = m_vertex_events.find(vertex);
|
||||
if (it == m_vertex_events.end())
|
||||
return std::nullopt;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Serialization format per vertex line:
|
||||
// x y z neighbor_count event_id
|
||||
// where event_id is "-" when no event is set.
|
||||
// Neighbor lines follow: nx ny nz
|
||||
|
||||
std::string NavigationMesh::serialize() const noexcept
|
||||
{
|
||||
std::ostringstream oss;
|
||||
for (const auto& [vertex, neighbors] : m_vertex_map)
|
||||
{
|
||||
const auto event_it = m_vertex_events.find(vertex);
|
||||
const std::string& event = (event_it != m_vertex_events.end()) ? event_it->second : "-";
|
||||
|
||||
oss << vertex.x << ' ' << vertex.y << ' ' << vertex.z
|
||||
<< ' ' << neighbors.size() << '\n';
|
||||
<< ' ' << neighbors.size() << ' ' << event << '\n';
|
||||
|
||||
for (const auto& n : neighbors)
|
||||
oss << n.x << ' ' << n.y << ' ' << n.z << '\n';
|
||||
}
|
||||
@@ -45,11 +73,13 @@ namespace omath::pathfinding
|
||||
void NavigationMesh::deserialize(const std::string& raw)
|
||||
{
|
||||
m_vertex_map.clear();
|
||||
m_vertex_events.clear();
|
||||
std::istringstream iss(raw);
|
||||
|
||||
Vector3<float> vertex;
|
||||
std::size_t neighbors_count;
|
||||
while (iss >> vertex.x >> vertex.y >> vertex.z >> neighbors_count)
|
||||
std::string event;
|
||||
while (iss >> vertex.x >> vertex.y >> vertex.z >> neighbors_count >> event)
|
||||
{
|
||||
std::vector<Vector3<float>> neighbors;
|
||||
neighbors.reserve(neighbors_count);
|
||||
@@ -61,6 +91,9 @@ namespace omath::pathfinding
|
||||
neighbors.push_back(n);
|
||||
}
|
||||
m_vertex_map.emplace(vertex, std::move(neighbors));
|
||||
|
||||
if (event != "-")
|
||||
m_vertex_events.emplace(vertex, std::move(event));
|
||||
}
|
||||
}
|
||||
} // namespace omath::pathfinding
|
||||
|
||||
@@ -140,3 +140,102 @@ TEST(NavigationMeshTests, VertexWithNoNeighborsRoundTrip)
|
||||
ASSERT_EQ(nav2.m_vertex_map.count(v), 1u);
|
||||
EXPECT_TRUE(nav2.get_neighbors(v).empty());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vertex events
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST(NavigationMeshTests, EventNotSetByDefault)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> v{0.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
|
||||
EXPECT_FALSE(nav.get_event(v).has_value());
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, SetAndGetEvent)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> v{1.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
nav.set_event(v, "jump");
|
||||
|
||||
const auto event = nav.get_event(v);
|
||||
ASSERT_TRUE(event.has_value());
|
||||
EXPECT_EQ(event.value(), "jump");
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, OverwriteEvent)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> v{1.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
nav.set_event(v, "jump");
|
||||
nav.set_event(v, "teleport");
|
||||
|
||||
EXPECT_EQ(nav.get_event(v).value(), "teleport");
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, ClearEvent)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> v{1.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
nav.set_event(v, "jump");
|
||||
nav.clear_event(v);
|
||||
|
||||
EXPECT_FALSE(nav.get_event(v).has_value());
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, EventRoundTripSerialization)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> a{0.f, 0.f, 0.f};
|
||||
const Vector3<float> b{1.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(a, std::vector<Vector3<float>>{b});
|
||||
nav.m_vertex_map.emplace(b, std::vector<Vector3<float>>{});
|
||||
nav.set_event(b, "jump");
|
||||
|
||||
NavigationMesh nav2;
|
||||
nav2.deserialize(nav.serialize());
|
||||
|
||||
ASSERT_FALSE(nav2.get_event(a).has_value());
|
||||
ASSERT_TRUE(nav2.get_event(b).has_value());
|
||||
EXPECT_EQ(nav2.get_event(b).value(), "jump");
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, MultipleEventsRoundTrip)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> a{0.f, 0.f, 0.f};
|
||||
const Vector3<float> b{1.f, 0.f, 0.f};
|
||||
const Vector3<float> c{2.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(a, std::vector<Vector3<float>>{});
|
||||
nav.m_vertex_map.emplace(b, std::vector<Vector3<float>>{});
|
||||
nav.m_vertex_map.emplace(c, std::vector<Vector3<float>>{});
|
||||
nav.set_event(a, "spawn");
|
||||
nav.set_event(c, "teleport");
|
||||
|
||||
NavigationMesh nav2;
|
||||
nav2.deserialize(nav.serialize());
|
||||
|
||||
EXPECT_EQ(nav2.get_event(a).value(), "spawn");
|
||||
EXPECT_FALSE(nav2.get_event(b).has_value());
|
||||
EXPECT_EQ(nav2.get_event(c).value(), "teleport");
|
||||
}
|
||||
|
||||
TEST(NavigationMeshTests, DeserializeClearsOldEvents)
|
||||
{
|
||||
NavigationMesh nav;
|
||||
const Vector3<float> v{0.f, 0.f, 0.f};
|
||||
nav.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
nav.set_event(v, "jump");
|
||||
|
||||
// Deserialize a mesh that has no events
|
||||
NavigationMesh empty_events;
|
||||
empty_events.m_vertex_map.emplace(v, std::vector<Vector3<float>>{});
|
||||
|
||||
nav.deserialize(empty_events.serialize());
|
||||
EXPECT_FALSE(nav.get_event(v).has_value());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user