map_editor:

- tilepicker s'obri ara amb la T
- brush de varios tiles
- eyedropper amb botó dret (de uno o varios tiles)
This commit is contained in:
2026-04-10 21:33:57 +02:00
parent 342b46ca32
commit fadc3b03c9
5 changed files with 363 additions and 88 deletions

View File

@@ -14,7 +14,7 @@
static constexpr int BORDER_PAD = 3;
// Abre el picker con un tileset
void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_color, int source_color, int target_color, int tile_spacing_in, int tile_spacing_out) {
void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_color, int source_color, int target_color, int tile_spacing_in, int tile_spacing_out, bool allow_rect_selection) {
tileset_ = Resource::Cache::get()->getSurface(tileset_name);
if (!tileset_) {
open_ = false;
@@ -23,6 +23,10 @@ void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_
spacing_in_ = tile_spacing_in;
spacing_out_ = tile_spacing_out;
allow_rect_ = allow_rect_selection;
selecting_rect_ = false;
rect_start_tile_ = -1;
last_valid_hover_ = -1;
// Calcular dimensiones del tileset en tiles (teniendo en cuenta spacing de entrada)
int src_cell = Tile::SIZE + spacing_in_;
@@ -145,13 +149,37 @@ void TilePicker::render() {
float tileset_screen_y = frame_dst_.y + BORDER_PAD - static_cast<float>(scroll_y_);
constexpr auto TS = static_cast<float>(Tile::SIZE);
// Highlight del tile bajo el cursor (blanco)
if (hover_tile_ >= 0) {
// Si hay un drag rect activo, dibujar el rectángulo en progreso (blanco)
// y omitir el highlight de hover individual.
if (selecting_rect_ && rect_start_tile_ >= 0) {
int end_tile = (hover_tile_ >= 0) ? hover_tile_ : last_valid_hover_;
if (end_tile >= 0) {
int c1 = rect_start_tile_ % tileset_width_;
int r1 = rect_start_tile_ / tileset_width_;
int c2 = end_tile % tileset_width_;
int r2 = end_tile / tileset_width_;
int col_min = std::min(c1, c2);
int col_max = std::max(c1, c2);
int row_min = std::min(r1, r2);
int row_max = std::max(r1, r2);
int cells_w = col_max - col_min + 1;
int cells_h = row_max - row_min + 1;
float rx = tileset_screen_x + static_cast<float>(col_min * out_cell);
float ry = tileset_screen_y + static_cast<float>(row_min * out_cell);
float rw = static_cast<float>((cells_w * out_cell) - spacing_out_);
float rh = static_cast<float>((cells_h * out_cell) - spacing_out_);
if (ry + rh > 0 && ry < static_cast<float>(visible_height_)) {
SDL_FRect rect_box = {.x = rx, .y = ry, .w = rw, .h = rh};
game_surface->drawRectBorder(&rect_box, 15);
}
}
} else if (hover_tile_ >= 0) {
// Highlight del tile bajo el cursor (blanco)
int col = hover_tile_ % tileset_width_;
int row = hover_tile_ / tileset_width_;
float hx = tileset_screen_x + static_cast<float>(col * out_cell);
float hy = tileset_screen_y + static_cast<float>(row * out_cell);
if (hy >= 0 && hy + TS <= visible_height_) {
if (hy >= 0 && hy + TS <= static_cast<float>(visible_height_)) {
SDL_FRect highlight = {.x = hx, .y = hy, .w = TS, .h = TS};
game_surface->drawRectBorder(&highlight, 15);
}
@@ -163,7 +191,7 @@ void TilePicker::render() {
int row = current_tile_ / tileset_width_;
float cx = tileset_screen_x + static_cast<float>(col * out_cell);
float cy = tileset_screen_y + static_cast<float>(row * out_cell);
if (cy >= 0 && cy + TS <= visible_height_) {
if (cy >= 0 && cy + TS <= static_cast<float>(visible_height_)) {
SDL_FRect cur_rect = {.x = cx, .y = cy, .w = TS, .h = TS};
game_surface->drawRectBorder(&cur_rect, 9);
}
@@ -179,14 +207,44 @@ void TilePicker::handleEvent(const SDL_Event& event) {
}
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (event.button.button == SDL_BUTTON_LEFT && hover_tile_ >= 0) {
if (on_select) { on_select(hover_tile_); }
close();
if (event.button.button == SDL_BUTTON_LEFT) {
if (allow_rect_ && hover_tile_ >= 0) {
// Iniciar selección rectangular: el commit se hace al soltar
selecting_rect_ = true;
rect_start_tile_ = hover_tile_;
last_valid_hover_ = hover_tile_;
} else if (!allow_rect_ && hover_tile_ >= 0) {
// Modo single-tile: confirmar inmediatamente
int col = hover_tile_ % tileset_width_;
int row = hover_tile_ / tileset_width_;
if (on_select) { on_select(col, row, 1, 1); }
close();
}
} else if (event.button.button == SDL_BUTTON_RIGHT) {
close();
}
}
if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT && selecting_rect_) {
int end_tile = (hover_tile_ >= 0) ? hover_tile_ : last_valid_hover_;
if (end_tile >= 0 && rect_start_tile_ >= 0) {
int c1 = rect_start_tile_ % tileset_width_;
int r1 = rect_start_tile_ / tileset_width_;
int c2 = end_tile % tileset_width_;
int r2 = end_tile / tileset_width_;
int col_min = std::min(c1, c2);
int col_max = std::max(c1, c2);
int row_min = std::min(r1, r2);
int row_max = std::max(r1, r2);
int width = col_max - col_min + 1;
int height = row_max - row_min + 1;
if (on_select) { on_select(col_min, row_min, width, height); }
}
selecting_rect_ = false;
rect_start_tile_ = -1;
close();
}
if (event.type == SDL_EVENT_MOUSE_WHEEL) {
scroll_y_ -= static_cast<int>(event.wheel.y) * Tile::SIZE * 2;
int max_scroll = static_cast<int>(frame_dst_.h) - visible_height_;
@@ -231,7 +289,8 @@ void TilePicker::updateMousePosition() {
if (on_tile && rel_x >= 0 && rel_y >= 0 &&
tile_x >= 0 && tile_x < tileset_width_ &&
tile_y >= 0 && tile_y < tileset_height_) {
hover_tile_ = tile_y * tileset_width_ + tile_x;
hover_tile_ = (tile_y * tileset_width_) + tile_x;
last_valid_hover_ = hover_tile_;
} else {
hover_tile_ = -1;
}