AIDEBUG: extracted code into own class

master
Martin Gerhardy 2020-10-13 22:19:30 +02:00
parent fcde5df93a
commit 9ca8fc1bd3
6 changed files with 143 additions and 37 deletions

View File

@ -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<float>()) {
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;

View File

@ -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();

View File

@ -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})

50
src/tools/aidebug/Map.cpp Normal file
View File

@ -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;
}

25
src/tools/aidebug/Map.h Normal file
View File

@ -0,0 +1,25 @@
/**
* @file
*/
#include <glm/vec2.hpp>
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;
};

View File

@ -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));
}