From 9ca8fc1bd3259e8f389652190a216c69ba55d3eb Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Tue, 13 Oct 2020 22:19:30 +0200 Subject: [PATCH] AIDEBUG: extracted code into own class --- src/tools/aidebug/AIDebug.cpp | 48 ++++++++++----------------- src/tools/aidebug/AIDebug.h | 8 ++--- src/tools/aidebug/CMakeLists.txt | 15 +++++++++ src/tools/aidebug/Map.cpp | 50 +++++++++++++++++++++++++++++ src/tools/aidebug/Map.h | 25 +++++++++++++++ src/tools/aidebug/tests/MapTest.cpp | 34 ++++++++++++++++++++ 6 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 src/tools/aidebug/Map.cpp create mode 100644 src/tools/aidebug/Map.h create mode 100644 src/tools/aidebug/tests/MapTest.cpp diff --git a/src/tools/aidebug/AIDebug.cpp b/src/tools/aidebug/AIDebug.cpp index 30cb2e635..e4e6aead6 100644 --- a/src/tools/aidebug/AIDebug.cpp +++ b/src/tools/aidebug/AIDebug.cpp @@ -577,22 +577,6 @@ void AIDebug::dbgTree() { ImGui::End(); } -bool AIDebug::dbgMapIsVisible(const ImVec2& pos, const ImVec2& mapMins, const ImVec2& mapMaxs) const { - return pos.x > mapMins.x && pos.y > mapMins.y && pos.x < mapMaxs.x && pos.y < mapMaxs.y; -} - -float AIDebug::dbgMapZoom() const { - return _zoom; -} - -ImVec2 AIDebug::dbgMapCalculateOffsetPos(float x, float y) const { - return ImVec2(-x * dbgMapZoom() + _frameBufferDimension.x / 2.0f, -y * dbgMapZoom() + _frameBufferDimension.y / 2.0f); -} - -ImVec2 AIDebug::dbgMapConvertEntPos(float x, float y) const { - return ImVec2(dbgMapZoom() * (_dbgMapOffset.x + x), dbgMapZoom() * (_dbgMapOffset.y + y)); -} - void AIDebug::dbgMap() { if (_stateWorldMsg == nullptr || _stateWorldMsg->states() == nullptr) { return; @@ -601,7 +585,7 @@ void AIDebug::dbgMap() { for (const auto &e : *_stateWorldMsg->states()) { const bool selected = isSelected(e->character_id()); if (selected) { - _dbgMapOffset = dbgMapCalculateOffsetPos(e->position()->x(), e->position()->z()); + _map.centerAtEntPos(e->position()->x(), e->position()->z()); break; } } @@ -621,15 +605,15 @@ void AIDebug::dbgMap() { ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); const ImVec2 mapMins(0.0f, 0.0f); const ImVec2 mapMaxs(_frameBufferDimension.x, _frameBufferDimension.y); + _map.setMinsMaxs(mapMins, mapMaxs); if (ImGui::Begin("##map", nullptr, ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings)) { dbgBar(); if (ImGui::IsMouseDragging(ImGuiMouseButton_Right, 0)) { - _dbgMapOffset.x += _mouseRelativePos.x; - _dbgMapOffset.y += _mouseRelativePos.y; + _map.scroll(_mouseRelativePos); } - const float radius = 10.0f * dbgMapZoom(); + const float radius = 10.0f * _map.zoom(); const ImVec2 entSize(radius * 2.0f); ImDrawList *draw = ImGui::GetWindowDrawList(); const ImVec2& clipRectMins = ImGui::GetCursorPos(); @@ -638,8 +622,8 @@ void AIDebug::dbgMap() { clipRectMaxs.y += clipRectMins.y; draw->PushClipRect(clipRectMins, clipRectMaxs, true); for (const auto &e : *_stateWorldMsg->states()) { - const ImVec2& entPos = dbgMapConvertEntPos(e->position()->x(), e->position()->z()); - if (!dbgMapIsVisible(entPos, mapMins, mapMaxs)) { + const ImVec2& entPos = _map.entPosToMap(e->position()->x(), e->position()->z()); + if (!_map.isVisible(entPos, mapMins, mapMaxs)) { continue; } const float orientation = e->orientation(); @@ -684,18 +668,18 @@ void AIDebug::dbgMap() { draw->AddCircle(entPos, radius, col, 12, 1.0f); draw->AddLine(entPos, {entPos.x + dir.x * radius * 2.0f, entPos.y + dir.y * radius * 2.0f}, col, 1.0f); if (selected) { - const ImVec2& homePos = dbgMapConvertEntPos(e->home_position()->x(), e->home_position()->z()); - const ImVec2& targetPos = dbgMapConvertEntPos(e->target_position()->x(), e->target_position()->z()); + const ImVec2& homePos = _map.entPosToMap(e->home_position()->x(), e->home_position()->z()); + const ImVec2& targetPos = _map.entPosToMap(e->target_position()->x(), e->target_position()->z()); draw->AddLine(entPos, homePos, homecol, 1.0f); draw->AddLine(entPos, targetPos, targetcol, 1.0f); } - const float viewRadius = (float)attribCurrent[core::enumVal(attrib::Type::VIEWDISTANCE)] * dbgMapZoom(); + const float viewRadius = (float)attribCurrent[core::enumVal(attrib::Type::VIEWDISTANCE)] * _map.zoom(); if (viewRadius > radius) { draw->AddCircle(entPos, (float)viewRadius, viewRadiusColor, 18, 1.0f); } - const float attackRadius = (float)attribCurrent[core::enumVal(attrib::Type::ATTACKRANGE)] * dbgMapZoom(); + const float attackRadius = (float)attribCurrent[core::enumVal(attrib::Type::ATTACKRANGE)] * _map.zoom(); if (attackRadius > 0.0) { draw->AddCircle(entPos, (float)attackRadius, attackRadiusColor, 12, 1.0f); } @@ -720,9 +704,12 @@ void AIDebug::dbgMap() { draw->PopClipRect(); } if (ImGui::IsWindowHovered()) { - _zoom = core_max(0.01f, dbgMapZoom() + ImGui::GetIO().MouseWheel * 0.1f); - // TODO: don't center on selection - but on the relative position in the map view - //_centerOnSelection = true; + const float deltaZoom = ImGui::GetIO().MouseWheel * 0.1f; + if (glm::abs(deltaZoom) > glm::epsilon()) { + const ImVec2 mousePos = ImGui::GetMousePos(); + const ImVec2 mouseMapPos(mousePos.x - mapMins.x, mousePos.y - mapMins.y); + _map.zoomAtMapPos(mouseMapPos.x, mouseMapPos.y, deltaZoom); + } } ImGui::End(); } @@ -809,11 +796,10 @@ void AIDebug::onEvent(const network::DisconnectEvent &event) { _chrStaticMsg = nullptr; _stateWorldMsg = nullptr; _namesMsg = nullptr; - _dbgMapOffset = { 0.0f, 0.0f }; + _map.reset(); _pause = false; _centerOnSelection = false; _zoneId = ""; - _zoom = 1.0f; _entityListFilter[0] = '\0'; _stateWorldSize = 0u; _characterDetailsSize = 0u; diff --git a/src/tools/aidebug/AIDebug.h b/src/tools/aidebug/AIDebug.h index 16820e577..49deb61ca 100644 --- a/src/tools/aidebug/AIDebug.h +++ b/src/tools/aidebug/AIDebug.h @@ -12,6 +12,7 @@ #include "network/MessageSender.h" #include "network/NetworkEvents.h" #include "ui/imgui/IMGUIApp.h" +#include "Map.h" /** * @ingroup Tools @@ -25,7 +26,6 @@ private: using Super = ui::imgui::IMGUIApp; char _aiServer[1024] = "127.0.0.1"; int _port = _defaultPort; - ImVec2 _dbgMapOffset { 0.0f, 0.0f }; int _dbgTreeIdAdd = -1; int _dbgTreeIdEdit = -1; @@ -36,10 +36,10 @@ private: Max }; + Map _map; State _state = State::Connect; bool _pause = false; bool _centerOnSelection = false; - float _zoom = 1.0f; char _entityListFilter[64] = ""; size_t _stateWorldSize = 0u; size_t _characterDetailsSize = 0u; @@ -95,10 +95,6 @@ private: bool dbgConnect(); void dbgBar(); - float dbgMapZoom() const; - ImVec2 dbgMapConvertEntPos(float x, float y) const; - ImVec2 dbgMapCalculateOffsetPos(float x, float y) const; - bool dbgMapIsVisible(const ImVec2& pos, const ImVec2& mapMins, const ImVec2& mapMaxs) const; void dbgMap(); void dbgStats(); void dbgEntities(); diff --git a/src/tools/aidebug/CMakeLists.txt b/src/tools/aidebug/CMakeLists.txt index f1b20bb79..168c1965f 100644 --- a/src/tools/aidebug/CMakeLists.txt +++ b/src/tools/aidebug/CMakeLists.txt @@ -4,7 +4,22 @@ set(SRCS network/MessageSender.h network/MessageSender.cpp AIDebug.h AIDebug.cpp + Map.h Map.cpp ) engine_add_executable(TARGET ${PROJECT_NAME} SRCS ${SRCS} WINDOWED) engine_target_link_libraries(TARGET ${PROJECT_NAME} DEPENDENCIES imgui ai-shared network attrib) + +set(TEST_SRCS + tests/MapTest.cpp + Map.h Map.cpp +) + +gtest_suite_sources(tests + ${TEST_SRCS} +) + +gtest_suite_begin(tests-${PROJECT_NAME} TEMPLATE ${ROOT_DIR}/src/modules/core/tests/main.cpp.in) +gtest_suite_sources(tests-${PROJECT_NAME} ${TEST_SRCS}) +gtest_suite_deps(tests-${PROJECT_NAME} test-app) +gtest_suite_end(tests-${PROJECT_NAME}) diff --git a/src/tools/aidebug/Map.cpp b/src/tools/aidebug/Map.cpp new file mode 100644 index 000000000..6bae5574d --- /dev/null +++ b/src/tools/aidebug/Map.cpp @@ -0,0 +1,50 @@ +/** + * @file + */ + +#include "Map.h" +#include "core/Common.h" + +void Map::setMinsMaxs(const glm::ivec2& mins, const glm::ivec2& maxs) { + _mins = mins; + _maxs = maxs; +} + +void Map::reset() { + _dbgMapOffset = { 0.0f, 0.0f }; + _zoom = 1.0f; +} + +void Map::centerAtEntPos(float x, float y) { + _dbgMapOffset = calculateOffsetPos(x, y, (_maxs - _mins) / 2); +} + +void Map::zoomAtMapPos(float x, float y, float deltaZoom) { + const glm::ivec2 entPos = mapToEntPos(x, y); + _zoom = core_max(0.01f, zoom() + deltaZoom); + _dbgMapOffset = calculateOffsetPos(entPos.x, entPos.y, glm::ivec2(x, y)); +} + +void Map::scroll(const glm::ivec2& amount) { + _dbgMapOffset += amount; +} + +float Map::zoom() const { + return _zoom; +} + +glm::ivec2 Map::calculateOffsetPos(float x, float y, const glm::ivec2& center) const { + return glm::ivec2(-x * zoom() + (float)center.x, -y * zoom() + (float)center.y); +} + +glm::ivec2 Map::entPosToMap(float x, float y) const { + return glm::ivec2(zoom() * (_dbgMapOffset.x + x), zoom() * (_dbgMapOffset.y + y)); +} + +glm::ivec2 Map::mapToEntPos(float x, float y) const { + return glm::ivec2((x - _dbgMapOffset.x) / zoom(), (y - _dbgMapOffset.y) / zoom()); +} + +bool Map::isVisible(const glm::ivec2& pos, const glm::ivec2& mapMins, const glm::ivec2& mapMaxs) const { + return pos.x > mapMins.x && pos.y > mapMins.y && pos.x < mapMaxs.x && pos.y < mapMaxs.y; +} diff --git a/src/tools/aidebug/Map.h b/src/tools/aidebug/Map.h new file mode 100644 index 000000000..1bccd9dd1 --- /dev/null +++ b/src/tools/aidebug/Map.h @@ -0,0 +1,25 @@ +/** + * @file + */ + +#include + +class Map { +private: + float _zoom = 1.0f; + glm::vec2 _dbgMapOffset { 0.0f, 0.0f }; + glm::ivec2 _mins {0}; + glm::ivec2 _maxs {0}; + glm::ivec2 calculateOffsetPos(float x, float y, const glm::ivec2& center) const; + +public: + void scroll(const glm::ivec2& amount); + void setMinsMaxs(const glm::ivec2& mins, const glm::ivec2& maxs); + void reset(); + void centerAtEntPos(float x, float y); + void zoomAtMapPos(float x, float y, float deltaZoom); + float zoom() const; + glm::ivec2 entPosToMap(float x, float y) const; + glm::ivec2 mapToEntPos(float x, float y) const; + bool isVisible(const glm::ivec2& pos, const glm::ivec2& mapMins, const glm::ivec2& mapMaxs) const; +}; diff --git a/src/tools/aidebug/tests/MapTest.cpp b/src/tools/aidebug/tests/MapTest.cpp new file mode 100644 index 000000000..1f08b13a6 --- /dev/null +++ b/src/tools/aidebug/tests/MapTest.cpp @@ -0,0 +1,34 @@ +/** + * @file + */ + +#include "app/tests/AbstractTest.h" +#include "../Map.h" + +class MapTest: public app::AbstractTest { +private: + using Super = app::AbstractTest; +public: + Map _map; + + void SetUp() override { + Super::SetUp(); + _map = Map(); + _map.setMinsMaxs(glm::ivec2(0), glm::ivec2(200, 100)); + } +}; + +TEST_F(MapTest, testConvertCoordinatesNoScroll) { + EXPECT_EQ(glm::ivec2(0), _map.entPosToMap(0.0f, 0.0f)); + EXPECT_EQ(glm::ivec2(500), _map.entPosToMap(500.0f, 500.0f)); +} + +TEST_F(MapTest, testConvertCoordinatesNoScrollNeeded) { + _map.centerAtEntPos(100.0f, 50.0f); + EXPECT_EQ(glm::ivec2(0), _map.entPosToMap(0.0f, 0.0f)); +} + +TEST_F(MapTest, testConvertCoordinatesScrolled) { + _map.centerAtEntPos(200.0f, 100.0f); + EXPECT_EQ(glm::ivec2(-100, -50), _map.entPosToMap(0.0f, 0.0f)); +}