summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--editor/app.hpp5
-rw-r--r--editor/tests-private.hpp69
-rw-r--r--editor/tests.cpp102
-rw-r--r--editor/tests.hpp4
-rw-r--r--editor/tests/path-test.cpp118
-rw-r--r--src/dijkstra.cpp2
-rw-r--r--src/path-search-result.cpp2
7 files changed, 188 insertions, 114 deletions
diff --git a/editor/app.hpp b/editor/app.hpp
index 14a0fcd6..6f21a456 100644
--- a/editor/app.hpp
+++ b/editor/app.hpp
@@ -25,6 +25,8 @@ GL::Texture2D make_constant_texture();
struct meshes;
} // namespace floormat::wireframe
+namespace floormat::tests { struct tests_data; }
+
namespace floormat {
struct fm_settings;
@@ -37,7 +39,6 @@ struct critter;
struct point;
class editor;
template<typename T> struct shared_ptr_wrapper;
-struct tests_data;
struct tests_data_;
struct cursor_state final
@@ -171,7 +172,7 @@ private:
void draw_tests_pane(float width);
void draw_tests_overlay();
void tests_reset_mode();
- tests_data& tests();
+ tests::tests_data& tests();
void reserve_inspector_array();
void add_inspector(popup_target p);
diff --git a/editor/tests-private.hpp b/editor/tests-private.hpp
index d7854ac4..7967256e 100644
--- a/editor/tests-private.hpp
+++ b/editor/tests-private.hpp
@@ -5,16 +5,13 @@
#include "src/object-id.hpp"
#include "floormat/events.hpp"
#include <Corrade/Containers/StringView.h>
+#include <memory>
#include <vector>
-#include <variant>
namespace floormat { struct app; }
namespace floormat::tests {
-template<typename... Ts> struct overloaded : Ts... { using Ts::operator()...; };
-template<typename... Ts> overloaded(Ts...) -> overloaded<Ts...>;
-
struct base_test
{
fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(base_test);
@@ -34,61 +31,35 @@ protected:
base_test();
};
-struct path_test : base_test
-{
- bool handle_key(app& a, const key_event& e, bool is_down) override;
- bool handle_mouse_click(app& a, const mouse_button_event& e, bool is_down) override;
- bool handle_mouse_move(app& a, const mouse_move_event& e) override;
- void draw_overlay(app& a) override;
- void draw_ui(app& a, float width) override;
- void update_pre(app& a) override;
- void update_post(app& a) override;
-
- struct pending_s
- {
- point from, to;
- object_id own_id;
- uint32_t max_dist;
- Vector2ub own_size;
- } pending = {};
-
- struct result_s
- {
- point from;
- std::vector<point> path;
- } result;
+void label_left(StringView label, float width);
- bool has_result : 1 = false, has_pending : 1 = false;
+enum class Test : uint32_t {
+ none, path, COUNT,
};
-void label_left(StringView label, float width);
-
-using variant = std::variant<std::monostate, tests::path_test>;
+struct tests_data final : tests_data_
+{
+ ~tests_data() noexcept override;
-} // namespace floormat::tests
+ void switch_to(Test i);
-namespace floormat {
+ static std::unique_ptr<base_test> make_test_none();
+ static std::unique_ptr<base_test> make_test_path();
-struct tests_data final : tests_data_, tests::variant
-{
- fm_DECLARE_DELETED_COPY_ASSIGNMENT(tests_data);
- tests_data();
- ~tests_data() noexcept override;
- using tests::variant::operator=;
+ std::unique_ptr<base_test> current_test;
+ Test current_index = Test::none;
- struct pair
+ struct test_tuple
{
- StringView str;
- size_t index;
- tests::variant(*ctor)();
+ StringView name;
+ Test t;
+ std::unique_ptr<base_test>(*ctor)();
};
- static constexpr inline pair fields[] = {
- { "None"_s, 0, [] -> tests::variant { return std::monostate{}; } },
- { "Path"_s, 1, [] -> tests::variant { return tests::path_test{}; } },
+ static constexpr test_tuple fields[] = {
+ { "None"_s, Test::none, &tests_data::make_test_none, },
+ { "Path"_s, Test::path, &tests_data::make_test_path, },
};
-
- void switch_to(size_t i);
};
-} // namespace floormat
+} // namespace floormat::tests
diff --git a/editor/tests.cpp b/editor/tests.cpp
index 8d0d72c5..1521fff7 100644
--- a/editor/tests.cpp
+++ b/editor/tests.cpp
@@ -18,6 +18,8 @@ void label_left(StringView label, float width)
ImGui::SetNextItemWidth(-1);
}
+std::unique_ptr<base_test> tests_data::make_test_none() { return {}; }
+
} // namespace floormat::tests
namespace floormat {
@@ -28,18 +30,25 @@ tests_data_::~tests_data_() noexcept = default;
tests_data_::tests_data_() = default;
tests_data::~tests_data() noexcept = default;
-tests_data::tests_data() = default;
base_test::~base_test() noexcept = default;
base_test::base_test() = default;
using namespace floormat::imgui;
-void tests_data::switch_to(size_t i)
+void tests_data::switch_to(Test i)
{
- fm_assert(i < std::size(fields));
- const auto& [str, index, ctor] = fields[i];
- *this = ctor();
+ fm_assert((size_t)i < std::size(fields));
+ current_index = Test::none;
+ current_test = make_test_none();
+ switch (i)
+ {
+ default: break;
+ case Test::none: current_test = make_test_none(); break;
+ case Test::path: current_test = make_test_path(); break;
+ }
+ if (current_test)
+ current_index = i;
}
safe_ptr<tests_data_> tests_data_::make()
@@ -49,51 +58,40 @@ safe_ptr<tests_data_> tests_data_::make()
void app::tests_pre_update()
{
- std::visit(overloaded {
- [](std::monostate) {},
- [&](base_test& x) { return x.update_pre(*this); }
- }, tests());
+ if (const auto& x = tests().current_test)
+ x->update_pre(*this);
}
void app::tests_post_update()
{
- std::visit(overloaded {
- [](std::monostate) {},
- [&](base_test& x) { return x.update_post(*this); }
- }, tests());
+ if (const auto& x = tests().current_test)
+ x->update_post(*this);
}
bool app::tests_handle_mouse_click(const mouse_button_event& e, bool is_down)
{
update_cursor_tile(cursor.pixel);
- return std::visit(overloaded {
- [](std::monostate) { return false; },
- [&](base_test& x) { return x.handle_mouse_click(*this, e, is_down); }
- }, tests());
+ if (const auto& x = tests().current_test)
+ return x->handle_mouse_click(*this, e, is_down);
+ else
+ return false;
}
bool app::tests_handle_key(const key_event& e, bool is_down)
{
- switch (e.key)
- {
- case SDLK_ESCAPE:
- tests().switch_to(0);
- return true;
- default:
- return std::visit(overloaded {
- [](std::monostate) { return false; },
- [&](base_test& x) { return x.handle_key(*this, e, is_down); }
- }, tests());
- }
+ if (const auto& x = tests().current_test)
+ return x->handle_key(*this, e, is_down);
+ else
+ return false;
}
bool app::tests_handle_mouse_move(const mouse_move_event& e)
{
- return std::visit(overloaded {
- [](std::monostate) { return false; },
- [&](base_test& x) { return x.handle_mouse_move(*this, e); }
- }, tests());
+ if (const auto& x = tests().current_test)
+ return x->handle_mouse_move(*this, e);
+ else
+ return false;
}
tests_data& app::tests()
@@ -103,39 +101,35 @@ tests_data& app::tests()
void app::tests_reset_mode()
{
- if (!std::holds_alternative<std::monostate>(tests()))
- tests() = std::monostate{};
+ tests().switch_to(Test::none);
}
void app::draw_tests_pane(float width)
{
ImGui::SeparatorText("Functional tests");
+ auto& t = tests();
constexpr int selectable_flags = ImGuiSelectableFlags_SpanAvailWidth;
- for (auto [str, i, ctor] : tests_data::fields)
- if (ImGui::Selectable(str.data(), i == tests().index(), selectable_flags))
- tests().switch_to(i);
-
- std::visit(overloaded {
- [](std::monostate) {},
- [&](base_test& x) {
- auto dpi = M->dpi_scale();
- ImGui::NewLine();
- ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, 2*dpi.y());
- auto b = push_id("###test-data");
- return x.draw_ui(*this, width);
- }
- }, tests());
+
+ for (auto [str, id, ctor] : tests_data::fields)
+ if (ImGui::Selectable(str.data(), id == t.current_index, selectable_flags))
+ if (t.current_index != id)
+ t.switch_to(id);
+
+ if (t.current_test)
+ {
+ auto dpi = M->dpi_scale();
+ ImGui::NewLine();
+ ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, 2*dpi.y());
+ auto b = push_id("###test-data");
+ t.current_test->draw_ui(*this, width);
+ }
}
void app::draw_tests_overlay()
{
- std::visit(overloaded {
- [](std::monostate) {},
- [&](base_test& x) {
- return x.draw_overlay(*this);
- }
- }, tests());
+ if (const auto& x = tests().current_test)
+ x->draw_overlay(*this);
}
} // namespace floormat
diff --git a/editor/tests.hpp b/editor/tests.hpp
index b4ee5289..51e81a3c 100644
--- a/editor/tests.hpp
+++ b/editor/tests.hpp
@@ -1,12 +1,12 @@
#pragma once
#include "compat/defs.hpp"
+namespace floormat::tests { struct base_test; struct tests_data; }
+
namespace floormat {
template<typename T> class safe_ptr;
-struct tests_data;
-
struct tests_data_
{
fm_DECLARE_DELETED_COPY_ASSIGNMENT(tests_data_);
diff --git a/editor/tests/path-test.cpp b/editor/tests/path-test.cpp
index ca976a38..baeeb11f 100644
--- a/editor/tests/path-test.cpp
+++ b/editor/tests/path-test.cpp
@@ -8,9 +8,43 @@
#include "../imgui-raii.hpp"
#include "src/camera-offset.hpp"
#include <Magnum/Math/Functions.h>
+#include <magnum/Math/Color.h>
namespace floormat::tests {
+using namespace floormat::imgui;
+
+struct path_test : base_test
+{
+ bool handle_key(app& a, const key_event& e, bool is_down) override;
+ bool handle_mouse_click(app& a, const mouse_button_event& e, bool is_down) override;
+ bool handle_mouse_move(app& a, const mouse_move_event& e) override;
+ void draw_overlay(app& a) override;
+ void draw_ui(app& a, float width) override;
+ void update_pre(app& a) override;
+ void update_post(app& a) override;
+
+ struct pending_s
+ {
+ point from, to;
+ object_id own_id;
+ uint32_t max_dist;
+ Vector2ub own_size;
+ } pending = {};
+
+ struct result_s
+ {
+ point from, to;
+ std::vector<point> path;
+ float time;
+ uint32_t cost, distance;
+ bool found : 1;
+ } result;
+
+ bool has_result : 1 = false, has_pending : 1 = false;
+};
+
+
bool path_test::handle_key(app& a, const key_event& e, bool is_down)
{
(void)a; (void)e; (void)is_down;
@@ -116,8 +150,15 @@ void path_test::update_pre(app& a)
if (res)
{
has_result = true;
- result.from = pending.from;
- result.path = res.path();
+ result = {
+ .from = pending.from,
+ .to = pending.to,
+ .path = std::move(res.path()),
+ .time = res.time(),
+ .cost = res.cost(),
+ .distance = res.distance(),
+ .found = res.is_found(),
+ };
}
}
@@ -128,9 +169,76 @@ void path_test::update_post(app& a)
void path_test::draw_ui(app& a, float width)
{
- static uint32_t val;
- label_left("foo", 100);
- ImGui::InputScalar("##foo", ImGuiDataType_U32, &val);
+ constexpr ImGuiTableFlags table_flags = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY;
+ constexpr auto colflags_1 = ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoReorder | ImGuiTableColumnFlags_NoSort;
+ constexpr auto colflags_0 = colflags_1 | ImGuiTableColumnFlags_WidthFixed;
+
+ char buf[128];
+ const auto& res = result;
+
+ if (!has_result)
+ return;
+
+ auto from_c = Vector3i(res.from.chunk3()), to_c = Vector3i(res.to.chunk3());
+ auto from_l = Vector2i(res.from.local()), to_l = Vector2i(res.to.local());
+ auto from_p = Vector2i(res.from.offset()), to_p = Vector2i(res.to.offset());
+
+ constexpr auto print_coord = [](auto&& buf, Vector3i c, Vector2i l, Vector2i p)
+ {
+ std::snprintf(buf, std::size(buf), "(%dx%d) <%dx%d> {%dx%d}", c.x(), c.y(), l.x(), l.y(), p.x(), p.y());
+ };
+
+ constexpr auto do_column = [](StringView name)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ text(name);
+ ImGui::TableNextColumn();
+ };
+
+ if (auto b1 = begin_table("##search_results", 2, table_flags))
+ {
+ ImGui::TableSetupColumn("##name", colflags_0);
+ ImGui::TableSetupColumn("##value", colflags_1 | ImGuiTableColumnFlags_WidthStretch);
+
+ do_column("from");
+ print_coord(buf, from_c, from_l, from_p);
+ text(buf);
+
+ do_column("to");
+ print_coord(buf, to_c, to_l, to_p);
+ text(buf);
+
+ do_column("found?");
+ if (res.found)
+ {
+ auto b = push_style_color(ImGuiCol_Text, 0x00ff00ff_rgbaf);
+ text("yes");
+ }
+ else
+ {
+ {
+ auto b = push_style_color(ImGuiCol_Text, 0xff0000ff_rgbaf);
+ text("no");
+ }
+ {
+ auto b = push_style_color(ImGuiCol_Text, 0xffff00ff_rgbaf);
+ do_column("dist");
+ std::snprintf(buf, std::size(buf), "%d", (int)res.distance);
+ text(buf);
+ }
+ }
+
+ do_column("cost");
+ std::snprintf(buf, std::size(buf), "%d", (int)res.cost);
+ text(buf);
+
+ do_column("length");
+ std::snprintf(buf, std::size(buf), "%d", (int)res.path.size());
+ text(buf);
+ }
}
+std::unique_ptr<base_test> tests_data::make_test_path() { return std::make_unique<path_test>(); }
+
} // namespace floormat::tests
diff --git a/src/dijkstra.cpp b/src/dijkstra.cpp
index ef980ee6..69711453 100644
--- a/src/dijkstra.cpp
+++ b/src/dijkstra.cpp
@@ -108,7 +108,7 @@ void set_result_from_idx(path_search_result& result, const std::vector<visited>&
path.clear();
const auto& to_node = nodes[idx];
- if (to != to_node.pt)
+ if (result.is_found() && to != to_node.pt)
path.push_back(to);
result.set_cost(to_node.dist);
diff --git a/src/path-search-result.cpp b/src/path-search-result.cpp
index fe420475..50e9173a 100644
--- a/src/path-search-result.cpp
+++ b/src/path-search-result.cpp
@@ -34,7 +34,7 @@ path_search_result::path_search_result()
path_search_result::~path_search_result() noexcept
{
- if (_node) [[likely]]
+ if (_node && _node->vec.capacity() > 0) [[likely]]
{
_node->vec.clear();
_node->_next = std::move(_pool);