#include "game/editor/editor.hpp" #ifdef _DEBUG #include #include "core/locale/locale.hpp" #include "core/rendering/notification_presets.hpp" #include "core/rendering/screen.hpp" #include "core/system/event_buffer.hpp" #include "game/map/tilemap.hpp" #include "utils/defaults.hpp" #include "utils/defines.hpp" void Editor::enter() { if (active_) { return; } active_ = true; Notification::notify(Locale::get().text("input.editor_on")); } // cppcheck-suppress constParameterReference // Tilemap& mutable per simetria amb `toggle()` i per futures // invalidacions de caches d'edició, encara que `save()` sigui const. void Editor::exit(Tilemap& tilemap) { if (!active_) { return; } active_ = false; const bool SAVED = tilemap.save(Defaults::Editor::SAVE_PATH); Notification::notify(Locale::get().text(SAVED ? "input.editor_off" : "input.editor_save_error")); } void Editor::toggle(Tilemap& tilemap) { if (active_) { exit(tilemap); } else { enter(); } } void Editor::update(int /*delta_ms*/, Tilemap& tilemap) { if (!active_) { return; } // 1. Cursor → cel·la. Convertim la posició del ratolí (espai finestra) // a coordenades del canvas amb Screen::windowToCanvas, i d'allí al // sistema de cel·les del tilemap restant l'origin i dividint pel // tile_size. Fora del mapa → cursor_col/row = -1. float mouse_x = 0.0F; float mouse_y = 0.0F; SDL_GetMouseState(&mouse_x, &mouse_y); const auto CANVAS_PT = Screen::get().windowToCanvas(mouse_x, mouse_y); const int CX = static_cast(CANVAS_PT.x) - tilemap.getOriginX(); const int CY = static_cast(CANVAS_PT.y) - tilemap.getOriginY(); const int TS = tilemap.getTileSize(); int col = -1; int row = -1; if (TS > 0 && CX >= 0 && CY >= 0) { const int C = CX / TS; const int R = CY / TS; if (C < tilemap.getCols() && R < tilemap.getRows()) { col = C; row = R; } } cursor_col_ = col; cursor_row_ = row; // 2. Clicks: només per-esdeveniment (no per estat). Un clic = un // tile col·locat o brush netejat. El picker encara no existeix, així // que el right-click no obre res: només neteja el brush. for (const auto& ev : EventBuffer::events) { if (ev.type != SDL_EVENT_MOUSE_BUTTON_DOWN) { continue; } if (ev.button.button == SDL_BUTTON_LEFT) { if (brush_ >= 0 && cursor_col_ >= 0 && cursor_row_ >= 0) { tilemap.setTileAt(cursor_col_, cursor_row_, brush_); } } else if (ev.button.button == SDL_BUTTON_RIGHT) { brush_ = -1; } } } void Editor::render(const Tilemap& tilemap) const { if (!active_) { return; } auto& screen = Screen::get(); constexpr int W = GameCanvas::WIDTH; constexpr int H = GameCanvas::HEIGHT; constexpr auto BORDER = Defaults::Editor::BORDER_ARGB; // Preview del brush: blitejem el tile seleccionat a la cel·la sota // el cursor, abans del border, així el border no el talla si caiguera // al perímetre. Cap efecte si no hi ha brush o el cursor està fora. if (brush_ >= 0 && cursor_col_ >= 0 && cursor_row_ >= 0) { const int PX = tilemap.getOriginX() + (cursor_col_ * tilemap.getTileSize()); const int PY = tilemap.getOriginY() + (cursor_row_ * tilemap.getTileSize()); tilemap.renderTilePreview(PX, PY, brush_); } screen.fillRect(0, 0, W, 1, BORDER); // top screen.fillRect(0, H - 1, W, 1, BORDER); // bottom screen.fillRect(0, 0, 1, H, BORDER); // left screen.fillRect(W - 1, 0, 1, H, BORDER); // right } #endif // _DEBUG