104 lines
3.6 KiB
C++
104 lines
3.6 KiB
C++
#include "game/editor/editor.hpp"
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#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<int>(CANVAS_PT.x) - tilemap.getOriginX();
|
|
const int CY = static_cast<int>(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
|