diff options
-rw-r--r-- | editor/tests-private.hpp | 4 | ||||
-rw-r--r-- | editor/tests/pathfinding.cpp | 140 |
2 files changed, 143 insertions, 1 deletions
diff --git a/editor/tests-private.hpp b/editor/tests-private.hpp index cd254e85..a6f20e92 100644 --- a/editor/tests-private.hpp +++ b/editor/tests-private.hpp @@ -31,7 +31,7 @@ protected: }; enum class Test : uint32_t { - none, path, raycast, region, COUNT, + none, path, raycast, region, pathfinding, COUNT, }; struct tests_data final : tests_data_ @@ -44,6 +44,7 @@ struct tests_data final : tests_data_ static Pointer<base_test> make_test_path(); static Pointer<base_test> make_test_raycast(); static Pointer<base_test> make_test_region(); + static Pointer<base_test> make_test_pathfinding(); Pointer<base_test> current_test; Test current_index = Test::none; @@ -60,6 +61,7 @@ struct tests_data final : tests_data_ { "Path"_s, Test::path, make_test_path, }, { "Raycasting"_s, Test::raycast, make_test_raycast }, { "Region extraction"_s, Test::region, make_test_region }, + { "Pathfinding"_s, Test::pathfinding, make_test_pathfinding }, }; }; diff --git a/editor/tests/pathfinding.cpp b/editor/tests/pathfinding.cpp new file mode 100644 index 00000000..0fde9143 --- /dev/null +++ b/editor/tests/pathfinding.cpp @@ -0,0 +1,140 @@ +#include "../tests-private.hpp" +#include "compat/shared-ptr-wrapper.hpp" +#include "editor/app.hpp" +#include "src/world.hpp" +#include "floormat/main.hpp" +#include "../imgui-raii.hpp" +#include <mg/Functions.h> + +namespace floormat::tests { + +using namespace floormat::imgui; + +namespace { + +struct step_s +{ + uint32_t count; + Vector2b direction; + + explicit constexpr operator bool() const { return count != 0 && count != -1u; } +}; + +constexpr inline auto empty_step = step_s{0, {}}, invalid_step = step_s{-1u, {}}; + +constexpr step_s next_step(Vector2i vec_in) +{ + const auto vec = Vector2ui(Math::abs(vec_in)); + const auto signs = Vector2b(Math::sign(vec_in)); + fm_debug_assert(!vec.isZero()); + + if (vec.y() == 0) + return { vec.x(), Vector2b{1, 0} * signs }; + else if (vec.x() == 0) + return { vec.y(), Vector2b{0, 1} * signs }; + else if (vec.x() == vec.y()) + return { vec.x(), Vector2b{1} * signs }; + else + { + uint32_t major_idx, minor_idx; + if (vec.x() > vec.y()) + { + major_idx = 0; + minor_idx = 1; + } + else + { + major_idx = 1; + minor_idx = 0; + } + const auto major = vec[major_idx], minor = vec[minor_idx]; + const auto num_axis_aligned = (uint32_t)Math::abs((int)major - (int)minor); + fm_debug_assert(num_axis_aligned > 0); + auto axis_aligned = Vector2b{}; + axis_aligned[major] = 1; + return { num_axis_aligned, axis_aligned * signs }; + // moving on the minor axis first looks more natural + + } +} + +struct result_s +{ + bool has_value : 1 = false; +}; + +struct pending_s +{ + bool has_value : 1 = false; +}; + +struct pf_test final : base_test +{ + result_s result; + pending_s pending; + + ~pf_test() noexcept override = default; + + step_s get_next_step(point from, point to); + + 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&) override { return {}; } + void draw_overlay(app& a) override; + void draw_ui(app& a, float menu_bar_height) override; + void update_pre(app& a) override; + void update_post(app& a) override; +}; + +step_s pf_test::get_next_step(point from, point to) +{ + if (from.chunk3().z != to.chunk3().z) + return invalid_step; + + if (from == to) + return empty_step; + + const auto vec = to.coord() - from.coord(); + + fm_debug_assert(!vec.isZero()); + + return next_step(vec); +} + +bool pf_test::handle_key(app& a, const key_event& e, bool is_down) +{ + return false; +} + +bool pf_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_down) +{ + return false; +} + +void pf_test::draw_overlay(app& a) +{ +} + +void pf_test::draw_ui(app& a, float menu_bar_height) +{ +} + +void pf_test::update_pre(app& a) +{ + if (!pending.has_value) + return; + pending.has_value = false; + + auto& m = a.main(); + auto& c = *a.ensure_player_character(m.world()).ptr; +} + +void pf_test::update_post(app& a) +{ +} + +} // namespace + +Pointer<base_test> tests_data::make_test_pathfinding() { return Pointer<pf_test>{InPlaceInit}; } + +} // namespace floormat::tests |