From 91f87fa12636ea67d004704805ad35f0b9256d8a Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 1 Jul 2023 23:02:25 -0300 Subject: [PATCH] Add level debugger screen The level debugger is toggleable in playtesting mode by pressing Y. You can toggle whether or not the game is paused inside of the debugger by pressing TAB. The debugger screen allows you to see entity and block properties, and allows you to move them around. --- desktop_version/CMakeLists.txt | 1 + desktop_version/src/Game.cpp | 3 +- desktop_version/src/Input.cpp | 7 + desktop_version/src/LevelDebugger.cpp | 306 ++++++++++++++++++++++++++ desktop_version/src/LevelDebugger.h | 14 ++ desktop_version/src/Render.cpp | 2 + 6 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 desktop_version/src/LevelDebugger.cpp create mode 100644 desktop_version/src/LevelDebugger.h diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt index b2dfbf8d..41ec3396 100644 --- a/desktop_version/CMakeLists.txt +++ b/desktop_version/CMakeLists.txt @@ -84,6 +84,7 @@ set(VVV_SRC src/Input.cpp src/KeyPoll.cpp src/Labclass.cpp + src/LevelDebugger.cpp src/Localization.cpp src/LocalizationMaint.cpp src/LocalizationStorage.cpp diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 552cb059..df506186 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -17,6 +17,7 @@ #include "Font.h" #include "GlitchrunnerMode.h" #include "Graphics.h" +#include "LevelDebugger.h" #include "Localization.h" #include "LocalizationStorage.h" #include "KeyPoll.h" @@ -7491,7 +7492,7 @@ int Game::get_timestep(void) bool Game::physics_frozen(void) { - return roomname_translator::is_pausing(); + return roomname_translator::is_pausing() || level_debugger::is_pausing(); } bool Game::incompetitive(void) diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index 55c8064e..dcb29828 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -13,6 +13,7 @@ #include "Graphics.h" #include "GraphicsUtil.h" #include "KeyPoll.h" +#include "LevelDebugger.h" #include "Localization.h" #include "LocalizationMaint.h" #include "LocalizationStorage.h" @@ -2436,6 +2437,12 @@ void gameinput(void) } } + level_debugger::input(); + if (level_debugger::is_pausing()) + { + return; + } + game.press_map = false; if (key.isDown(KEYBOARD_ENTER) || key.isDown(SDLK_KP_ENTER) || key.isDown(game.controllerButton_map) ) { diff --git a/desktop_version/src/LevelDebugger.cpp b/desktop_version/src/LevelDebugger.cpp new file mode 100644 index 00000000..b8f902b8 --- /dev/null +++ b/desktop_version/src/LevelDebugger.cpp @@ -0,0 +1,306 @@ +#include "LevelDebugger.h" + +#include "Constants.h" +#include "Entity.h" +#include "Font.h" +#include "Graphics.h" +#include "KeyPoll.h" +#include "Localization.h" +#include "Map.h" +#include "UtilityClass.h" +#include "VFormat.h" + +namespace level_debugger +{ + bool active = false; + bool should_pause = true; + bool tab_held = false; + bool debug_held = false; + + // Moving entities/blocks + bool mouse_held = false; + int held_entity = -1; + int held_block = -1; + int grabber_offset_x = 0; + int grabber_offset_y = 0; + + bool is_pausing(void) + { + return active && should_pause; + } + + bool is_active(void) + { + return active; + } + + void toggle_active(void) + { + active = !active; + } + + bool mouse_within(SDL_Rect* rect) + { + return key.mx >= rect->x && key.mx < rect->x + rect->w && + key.my >= rect->y && key.my < rect->y + rect->h; + } + + void input(void) + { + if (!map.custommode || map.custommodeforreal) + { + active = false; + return; + } + + if (key.isDown(SDLK_y)) + { + if (!debug_held) + { + debug_held = true; + active = !active; + } + } + else + { + debug_held = false; + } + + if (!active) + { + return; + } + + if (key.isDown(SDLK_TAB)) + { + if (!tab_held) + { + tab_held = true; + should_pause = !should_pause; + } + } + else + { + tab_held = false; + } + + for (int i = 0; i < obj.entities.size(); i++) + { + SDL_Rect bounding_box = { + obj.entities[i].xp + obj.entities[i].cx, + obj.entities[i].yp + obj.entities[i].cy, + obj.entities[i].w, + obj.entities[i].h + }; + + if (key.leftbutton) + { + if (mouse_within(&bounding_box)) + { + if (!mouse_held) + { + mouse_held = true; + held_entity = i; + grabber_offset_x = key.mx - obj.entities[i].xp; + grabber_offset_y = key.my - obj.entities[i].yp; + + if (!key.keymap[SDLK_LSHIFT] && !key.keymap[SDLK_RSHIFT]) + { + for (int j = 0; j < obj.blocks.size(); j++) + { + if (obj.entities[i].xp == obj.blocks[j].rect.x && obj.entities[i].yp == obj.blocks[j].rect.y) + { + held_block = j; + } + } + } + } + break; + } + } + else + { + mouse_held = false; + held_entity = -1; + held_block = -1; + } + } + + if (held_entity == -1) + { + for (int i = 0; i < obj.blocks.size(); i++) + { + SDL_Rect bounding_box = { + obj.blocks[i].rect.x, + obj.blocks[i].rect.y, + obj.blocks[i].rect.w, + obj.blocks[i].rect.h + }; + + if (key.leftbutton) + { + if (mouse_within(&bounding_box)) + { + if (!mouse_held) + { + mouse_held = true; + held_block = i; + grabber_offset_x = key.mx - obj.blocks[i].rect.x; + grabber_offset_y = key.my - obj.blocks[i].rect.y; + } + break; + } + } + else + { + held_entity = -1; + mouse_held = false; + held_block = -1; + } + } + } + + if (INBOUNDS_VEC(held_entity, obj.entities)) + { + obj.entities[held_entity].xp = key.mx - grabber_offset_x; + obj.entities[held_entity].yp = key.my - grabber_offset_y; + + if (key.isDown(SDLK_LSHIFT) || key.isDown(SDLK_RSHIFT)) + { + obj.entities[held_entity].xp -= obj.entities[held_entity].xp % 8; + obj.entities[held_entity].yp -= obj.entities[held_entity].yp % 8; + } + } + + if (INBOUNDS_VEC(held_block, obj.blocks)) + { + int new_xp = key.mx - grabber_offset_x; + int new_yp = key.my - grabber_offset_y; + + if (key.isDown(SDLK_LSHIFT) || key.isDown(SDLK_RSHIFT)) + { + new_xp -= new_xp % 8; + new_yp -= new_yp % 8; + } + + obj.blocks[held_block].xp = new_xp; + obj.blocks[held_block].yp = new_yp; + obj.blocks[held_block].rect.x = new_xp; + obj.blocks[held_block].rect.y = new_yp; + } + } + + void render_info(int y, const char* text, const char* value) + { + char buffer[SCREEN_WIDTH_CHARS + 1]; + vformat_buf(buffer, sizeof(buffer), text, "value:str", value); + font::print(PR_BOR | PR_FONT_8X8, 5, 32 + (10 * y), buffer, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2)); + } + + void render(void) + { + if (!active) + { + return; + } + + int hovered = -1; + bool hovered_entity = true; + SDL_Rect hover_box; + + for (int i = 0; i < obj.entities.size(); i++) + { + SDL_Rect bounding_box = { + obj.entities[i].xp + obj.entities[i].cx, + obj.entities[i].yp + obj.entities[i].cy, + obj.entities[i].w, + obj.entities[i].h + }; + + bool hovering = false; + + if (hovered == -1 && mouse_within(&bounding_box)) + { + hovering = true; + hovered = i; + hovered_entity = true; + hover_box = bounding_box; + } + + graphics.draw_rect(bounding_box.x, bounding_box.y, bounding_box.w, bounding_box.h, graphics.getRGB(15, 90, 90)); + } + + for (int i = 0; i < obj.blocks.size(); i++) + { + SDL_Rect bounding_box = { + obj.blocks[i].rect.x, + obj.blocks[i].rect.y, + obj.blocks[i].rect.w, + obj.blocks[i].rect.h + }; + + bool hovering = false; + + if (hovered == -1 && mouse_within(&bounding_box)) + { + hovering = true; + hovered = i; + hovered_entity = false; + hover_box = bounding_box; + } + + graphics.draw_rect(bounding_box.x, bounding_box.y, bounding_box.w, bounding_box.h, graphics.getRGB(90, 15, 15)); + } + + font::print(PR_BOR | PR_FONT_8X8, 5, 14, loc::gettext("[Press TAB to toggle movement]"), 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2)); + + if (hovered != -1) + { + int line = 0; + if (hovered_entity) + { + entclass* entity = &obj.entities[hovered]; + render_info(line++, "Index: {value}", help.String(hovered).c_str()); + render_info(line++, "X: {value}", help.String(entity->xp).c_str()); + render_info(line++, "Y: {value}", help.String(entity->yp).c_str()); + render_info(line++, "Width: {value}", help.String(entity->w).c_str()); + render_info(line++, "Height: {value}", help.String(entity->h).c_str()); + line++; + render_info(line++, "Rule: {value}", help.String(entity->rule).c_str()); + render_info(line++, "Type: {value}", help.String(entity->type).c_str()); + render_info(line++, "Behave: {value}", help.String(entity->behave).c_str()); + render_info(line++, "Para: {value}", help.String(entity->para).c_str()); + line++; + render_info(line++, "Tile: {value}", help.String(entity->tile).c_str()); + render_info(line++, "Draw Frame: {value}", help.String(entity->drawframe).c_str()); + render_info(line++, "Size: {value}", help.String(entity->size).c_str()); + render_info(line++, "Direction: {value}", help.String(entity->dir).c_str()); + + graphics.draw_rect(hover_box.x, hover_box.y, hover_box.w, hover_box.h, graphics.getRGB(32, 255 - help.glow, 255 - help.glow)); + } + else + { + blockclass* block = &obj.blocks[hovered]; + render_info(line++, "Index: {value}", help.String(hovered).c_str()); + render_info(line++, "X: {value}", help.String(block->rect.x).c_str()); + render_info(line++, "Y: {value}", help.String(block->rect.y).c_str()); + render_info(line++, "Width: {value}", help.String(block->rect.w).c_str()); + render_info(line++, "Height: {value}", help.String(block->rect.h).c_str()); + + line++; + + if (block->type == TRIGGER || block->type == ACTIVITY) + { + render_info(line++, "Script: {value}", block->script.c_str()); + render_info(line++, "State: {value}", help.String(block->trigger).c_str()); + } + else if (block->type == DIRECTIONAL) + { + render_info(line++, "Direction: {value}", help.String(block->trigger).c_str()); + } + + graphics.draw_rect(hover_box.x, hover_box.y, hover_box.w, hover_box.h, graphics.getRGB(255 - help.glow, 32, 32)); + } + } + } +}; diff --git a/desktop_version/src/LevelDebugger.h b/desktop_version/src/LevelDebugger.h new file mode 100644 index 00000000..8f8b988a --- /dev/null +++ b/desktop_version/src/LevelDebugger.h @@ -0,0 +1,14 @@ +#ifndef LEVELDEBUGGER_H +#define LEVELDEBUGGER_H + +#include + +namespace level_debugger +{ + bool is_pausing(void); + bool is_active(void); + void input(void); + void render(void); +} + +#endif /* LEVELDEBUGGER_H */ diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 7c6ca1ce..dc064642 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -14,6 +14,7 @@ #include "GraphicsUtil.h" #include "InterimVersion.h" #include "KeyPoll.h" +#include "LevelDebugger.h" #include "Localization.h" #include "LocalizationStorage.h" #include "MakeAndPlay.h" @@ -2472,6 +2473,7 @@ void gamerender(void) graphics.drawtrophytext(); } + level_debugger::render(); graphics.renderwithscreeneffects(); }