tile_picker ara gasta spacing_in i spacing_out
This commit is contained in:
@@ -14,48 +14,77 @@
|
|||||||
static constexpr int BORDER_PAD = 3;
|
static constexpr int BORDER_PAD = 3;
|
||||||
|
|
||||||
// Abre el picker con un tileset
|
// 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) {
|
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) {
|
||||||
tileset_ = Resource::Cache::get()->getSurface(tileset_name);
|
tileset_ = Resource::Cache::get()->getSurface(tileset_name);
|
||||||
if (!tileset_) {
|
if (!tileset_) {
|
||||||
open_ = false;
|
open_ = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tileset_width_ = static_cast<int>(tileset_->getWidth()) / Tile::SIZE;
|
spacing_in_ = tile_spacing_in;
|
||||||
tileset_height_ = static_cast<int>(tileset_->getHeight()) / Tile::SIZE;
|
spacing_out_ = tile_spacing_out;
|
||||||
|
|
||||||
|
// Calcular dimensiones del tileset en tiles (teniendo en cuenta spacing de entrada)
|
||||||
|
int src_cell = Tile::SIZE + spacing_in_;
|
||||||
|
tileset_width_ = static_cast<int>(tileset_->getWidth()) / src_cell;
|
||||||
|
tileset_height_ = static_cast<int>(tileset_->getHeight()) / src_cell;
|
||||||
|
// Corregir si el último tile cabe sin spacing
|
||||||
|
if (tileset_width_ == 0 && tileset_->getWidth() >= Tile::SIZE) { tileset_width_ = 1; }
|
||||||
|
if (tileset_height_ == 0 && tileset_->getHeight() >= Tile::SIZE) { tileset_height_ = 1; }
|
||||||
|
|
||||||
current_tile_ = current_tile;
|
current_tile_ = current_tile;
|
||||||
hover_tile_ = -1;
|
hover_tile_ = -1;
|
||||||
scroll_y_ = 0;
|
scroll_y_ = 0;
|
||||||
|
|
||||||
int tileset_px_w = tileset_width_ * Tile::SIZE;
|
// Dimensiones de salida (con spacing visual entre tiles)
|
||||||
int tileset_px_h = tileset_height_ * Tile::SIZE;
|
int out_cell = Tile::SIZE + spacing_out_;
|
||||||
|
int display_w = tileset_width_ * out_cell - spacing_out_; // Sin trailing
|
||||||
|
int display_h = tileset_height_ * out_cell - spacing_out_;
|
||||||
|
|
||||||
// Crear surface con borde: tileset + BORDER_PAD pixels a cada lado
|
// Frame: display + borde
|
||||||
int frame_w = tileset_px_w + BORDER_PAD * 2;
|
int frame_w = display_w + BORDER_PAD * 2;
|
||||||
int frame_h = tileset_px_h + BORDER_PAD * 2;
|
int frame_h = display_h + BORDER_PAD * 2;
|
||||||
frame_surface_ = std::make_shared<Surface>(frame_w, frame_h);
|
frame_surface_ = std::make_shared<Surface>(frame_w, frame_h);
|
||||||
|
|
||||||
// Componer: fondo + borde + tileset (con sustitución de color opcional)
|
// Componer: fondo + borde + tiles uno a uno
|
||||||
{
|
{
|
||||||
auto prev = Screen::get()->getRendererSurface();
|
auto prev = Screen::get()->getRendererSurface();
|
||||||
Screen::get()->setRendererSurface(frame_surface_);
|
Screen::get()->setRendererSurface(frame_surface_);
|
||||||
|
|
||||||
// Fondo: color personalizado o negro por defecto
|
|
||||||
Uint8 fill_color = (bg_color >= 0) ? static_cast<Uint8>(bg_color) : stringToColor("black");
|
Uint8 fill_color = (bg_color >= 0) ? static_cast<Uint8>(bg_color) : stringToColor("black");
|
||||||
frame_surface_->clear(fill_color);
|
frame_surface_->clear(fill_color);
|
||||||
|
|
||||||
// Borde doble (bright_white + white)
|
// Borde doble
|
||||||
SDL_FRect outer = {.x = 0, .y = 0, .w = static_cast<float>(frame_w), .h = static_cast<float>(frame_h)};
|
SDL_FRect outer = {.x = 0, .y = 0, .w = static_cast<float>(frame_w), .h = static_cast<float>(frame_h)};
|
||||||
frame_surface_->drawRectBorder(&outer, stringToColor("bright_white"));
|
frame_surface_->drawRectBorder(&outer, stringToColor("bright_white"));
|
||||||
SDL_FRect inner = {.x = 1, .y = 1, .w = static_cast<float>(frame_w - 2), .h = static_cast<float>(frame_h - 2)};
|
SDL_FRect inner = {.x = 1, .y = 1, .w = static_cast<float>(frame_w - 2), .h = static_cast<float>(frame_h - 2)};
|
||||||
frame_surface_->drawRectBorder(&inner, stringToColor("white"));
|
frame_surface_->drawRectBorder(&inner, stringToColor("white"));
|
||||||
|
|
||||||
// Tileset dentro del borde (con o sin sustitución de color)
|
// Renderizar cada tile individualmente
|
||||||
|
constexpr float TS = static_cast<float>(Tile::SIZE);
|
||||||
|
for (int row = 0; row < tileset_height_; ++row) {
|
||||||
|
for (int col = 0; col < tileset_width_; ++col) {
|
||||||
|
// Fuente: posición en el tileset original
|
||||||
|
SDL_FRect src = {
|
||||||
|
.x = static_cast<float>(col * src_cell),
|
||||||
|
.y = static_cast<float>(row * src_cell),
|
||||||
|
.w = TS, .h = TS};
|
||||||
|
|
||||||
|
// Destino: posición en el frame con spacing de salida
|
||||||
|
int dst_x = BORDER_PAD + col * out_cell;
|
||||||
|
int dst_y = BORDER_PAD + row * out_cell;
|
||||||
|
|
||||||
if (source_color >= 0 && target_color >= 0) {
|
if (source_color >= 0 && target_color >= 0) {
|
||||||
tileset_->renderWithColorReplace(BORDER_PAD, BORDER_PAD, static_cast<Uint8>(source_color), static_cast<Uint8>(target_color));
|
tileset_->renderWithColorReplace(dst_x, dst_y,
|
||||||
|
static_cast<Uint8>(source_color),
|
||||||
|
static_cast<Uint8>(target_color), &src);
|
||||||
} else {
|
} else {
|
||||||
SDL_FRect dst_rect = {.x = static_cast<float>(BORDER_PAD), .y = static_cast<float>(BORDER_PAD), .w = static_cast<float>(tileset_px_w), .h = static_cast<float>(tileset_px_h)};
|
SDL_FRect dst = {.x = static_cast<float>(dst_x), .y = static_cast<float>(dst_y), .w = TS, .h = TS};
|
||||||
tileset_->render(nullptr, &dst_rect);
|
tileset_->render(&src, &dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen::get()->setRendererSurface(prev);
|
Screen::get()->setRendererSurface(prev);
|
||||||
@@ -66,19 +95,17 @@ void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_
|
|||||||
int offset_y = (PlayArea::HEIGHT - frame_h) / 2;
|
int offset_y = (PlayArea::HEIGHT - frame_h) / 2;
|
||||||
if (offset_y < 0) { offset_y = 0; }
|
if (offset_y < 0) { offset_y = 0; }
|
||||||
|
|
||||||
// Área visible
|
|
||||||
visible_height_ = PlayArea::HEIGHT;
|
visible_height_ = PlayArea::HEIGHT;
|
||||||
|
|
||||||
// Posición de destino del frame
|
frame_dst_ = {.x = static_cast<float>(offset_x_), .y = static_cast<float>(offset_y),
|
||||||
frame_dst_ = {.x = static_cast<float>(offset_x_), .y = static_cast<float>(offset_y), .w = static_cast<float>(frame_w), .h = static_cast<float>(frame_h)};
|
.w = static_cast<float>(frame_w), .h = static_cast<float>(frame_h)};
|
||||||
|
|
||||||
// Si el frame es más alto que el play area, necesitará scroll
|
// Si el frame es más alto que el play area, necesitará scroll
|
||||||
if (frame_h > visible_height_) {
|
if (frame_h > visible_height_) {
|
||||||
frame_dst_.y = 0;
|
frame_dst_.y = 0;
|
||||||
// Scroll hasta el tile actual si está fuera de vista
|
|
||||||
if (current_tile_ >= 0) {
|
if (current_tile_ >= 0) {
|
||||||
int tile_row = current_tile_ / tileset_width_;
|
int tile_row = current_tile_ / tileset_width_;
|
||||||
int tile_y_px = tile_row * Tile::SIZE;
|
int tile_y_px = tile_row * out_cell;
|
||||||
if (tile_y_px > visible_height_ / 2) {
|
if (tile_y_px > visible_height_ / 2) {
|
||||||
scroll_y_ = tile_y_px - visible_height_ / 2;
|
scroll_y_ = tile_y_px - visible_height_ / 2;
|
||||||
}
|
}
|
||||||
@@ -105,30 +132,31 @@ void TilePicker::render() {
|
|||||||
int frame_h = static_cast<int>(frame_dst_.h);
|
int frame_h = static_cast<int>(frame_dst_.h);
|
||||||
|
|
||||||
if (frame_h <= visible_height_) {
|
if (frame_h <= visible_height_) {
|
||||||
// El frame cabe entero: renderizar tal cual (flotando sobre el mapa)
|
|
||||||
frame_surface_->render(nullptr, &frame_dst_);
|
frame_surface_->render(nullptr, &frame_dst_);
|
||||||
} else {
|
} else {
|
||||||
// El frame no cabe: renderizar porción visible con scroll
|
|
||||||
int max_scroll = frame_h - visible_height_;
|
int max_scroll = frame_h - visible_height_;
|
||||||
scroll_y_ = std::clamp(scroll_y_, 0, max_scroll);
|
scroll_y_ = std::clamp(scroll_y_, 0, max_scroll);
|
||||||
|
|
||||||
SDL_FRect src = {.x = 0, .y = static_cast<float>(scroll_y_), .w = frame_dst_.w, .h = static_cast<float>(visible_height_)};
|
SDL_FRect src = {.x = 0, .y = static_cast<float>(scroll_y_),
|
||||||
|
.w = frame_dst_.w, .h = static_cast<float>(visible_height_)};
|
||||||
SDL_FRect dst = {.x = frame_dst_.x, .y = 0, .w = frame_dst_.w, .h = static_cast<float>(visible_height_)};
|
SDL_FRect dst = {.x = frame_dst_.x, .y = 0, .w = frame_dst_.w, .h = static_cast<float>(visible_height_)};
|
||||||
frame_surface_->render(&src, &dst);
|
frame_surface_->render(&src, &dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Los highlights se dibujan directamente en game_surface (encima del frame)
|
// Highlights (en game_surface, encima del frame)
|
||||||
|
int out_cell = Tile::SIZE + spacing_out_;
|
||||||
float tileset_screen_x = frame_dst_.x + BORDER_PAD;
|
float tileset_screen_x = frame_dst_.x + BORDER_PAD;
|
||||||
float tileset_screen_y = frame_dst_.y + BORDER_PAD - static_cast<float>(scroll_y_);
|
float tileset_screen_y = frame_dst_.y + BORDER_PAD - static_cast<float>(scroll_y_);
|
||||||
|
constexpr float TS = static_cast<float>(Tile::SIZE);
|
||||||
|
|
||||||
// Highlight del tile bajo el cursor (blanco)
|
// Highlight del tile bajo el cursor (blanco)
|
||||||
if (hover_tile_ >= 0) {
|
if (hover_tile_ >= 0) {
|
||||||
int col = hover_tile_ % tileset_width_;
|
int col = hover_tile_ % tileset_width_;
|
||||||
int row = hover_tile_ / tileset_width_;
|
int row = hover_tile_ / tileset_width_;
|
||||||
float hx = tileset_screen_x + static_cast<float>(col * Tile::SIZE);
|
float hx = tileset_screen_x + static_cast<float>(col * out_cell);
|
||||||
float hy = tileset_screen_y + static_cast<float>(row * Tile::SIZE);
|
float hy = tileset_screen_y + static_cast<float>(row * out_cell);
|
||||||
if (hy >= 0 && hy + Tile::SIZE <= visible_height_) {
|
if (hy >= 0 && hy + TS <= visible_height_) {
|
||||||
SDL_FRect highlight = {.x = hx, .y = hy, .w = static_cast<float>(Tile::SIZE), .h = static_cast<float>(Tile::SIZE)};
|
SDL_FRect highlight = {.x = hx, .y = hy, .w = TS, .h = TS};
|
||||||
game_surface->drawRectBorder(&highlight, stringToColor("bright_white"));
|
game_surface->drawRectBorder(&highlight, stringToColor("bright_white"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,10 +165,10 @@ void TilePicker::render() {
|
|||||||
if (current_tile_ >= 0) {
|
if (current_tile_ >= 0) {
|
||||||
int col = current_tile_ % tileset_width_;
|
int col = current_tile_ % tileset_width_;
|
||||||
int row = current_tile_ / tileset_width_;
|
int row = current_tile_ / tileset_width_;
|
||||||
float cx = tileset_screen_x + static_cast<float>(col * Tile::SIZE);
|
float cx = tileset_screen_x + static_cast<float>(col * out_cell);
|
||||||
float cy = tileset_screen_y + static_cast<float>(row * Tile::SIZE);
|
float cy = tileset_screen_y + static_cast<float>(row * out_cell);
|
||||||
if (cy >= 0 && cy + Tile::SIZE <= visible_height_) {
|
if (cy >= 0 && cy + TS <= visible_height_) {
|
||||||
SDL_FRect cur_rect = {.x = cx, .y = cy, .w = static_cast<float>(Tile::SIZE), .h = static_cast<float>(Tile::SIZE)};
|
SDL_FRect cur_rect = {.x = cx, .y = cy, .w = TS, .h = TS};
|
||||||
game_surface->drawRectBorder(&cur_rect, stringToColor("bright_green"));
|
game_surface->drawRectBorder(&cur_rect, stringToColor("bright_green"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,15 +218,23 @@ void TilePicker::updateMousePosition() {
|
|||||||
float game_x = render_x - dst_rect.x;
|
float game_x = render_x - dst_rect.x;
|
||||||
float game_y = render_y - dst_rect.y;
|
float game_y = render_y - dst_rect.y;
|
||||||
|
|
||||||
// Coordenada relativa al tileset (dentro del frame, con scroll)
|
// Coordenada relativa al contenido del frame (con scroll)
|
||||||
float tileset_x = game_x - frame_dst_.x - BORDER_PAD;
|
float rel_x = game_x - frame_dst_.x - BORDER_PAD;
|
||||||
float tileset_y = game_y - frame_dst_.y - BORDER_PAD + static_cast<float>(scroll_y_);
|
float rel_y = game_y - frame_dst_.y - BORDER_PAD + static_cast<float>(scroll_y_);
|
||||||
|
|
||||||
int tile_x = static_cast<int>(tileset_x) / Tile::SIZE;
|
// Convertir a tile teniendo en cuenta el spacing de salida
|
||||||
int tile_y = static_cast<int>(tileset_y) / Tile::SIZE;
|
int out_cell = Tile::SIZE + spacing_out_;
|
||||||
|
int tile_x = static_cast<int>(rel_x) / out_cell;
|
||||||
|
int tile_y = static_cast<int>(rel_y) / out_cell;
|
||||||
|
|
||||||
if (tileset_x >= 0 && tile_x >= 0 && tile_x < tileset_width_ &&
|
// Verificar que estamos sobre un tile y no sobre el spacing
|
||||||
tileset_y >= 0 && tile_y >= 0 && tile_y < tileset_height_) {
|
int local_x = static_cast<int>(rel_x) % out_cell;
|
||||||
|
int local_y = static_cast<int>(rel_y) % out_cell;
|
||||||
|
bool on_tile = (local_x < Tile::SIZE && local_y < Tile::SIZE);
|
||||||
|
|
||||||
|
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;
|
||||||
} else {
|
} else {
|
||||||
hover_tile_ = -1;
|
hover_tile_ = -1;
|
||||||
|
|||||||
@@ -26,8 +26,12 @@ class TilePicker {
|
|||||||
|
|
||||||
// Abre el picker con un tileset
|
// Abre el picker con un tileset
|
||||||
// bg_color: color de fondo del panel (-1 = negro)
|
// bg_color: color de fondo del panel (-1 = negro)
|
||||||
// source_color/target_color: sustitución de color al renderizar el tileset (-1 = sin sustitución)
|
// source_color/target_color: sustitución de color (-1 = sin sustitución)
|
||||||
void open(const std::string& tileset_name, int current_tile = -1, int bg_color = -1, int source_color = -1, int target_color = -1);
|
// tile_spacing_in: pixels de separación entre tiles en el fichero fuente
|
||||||
|
// tile_spacing_out: pixels de separación visual entre tiles al mostrar
|
||||||
|
void open(const std::string& tileset_name, int current_tile = -1,
|
||||||
|
int bg_color = -1, int source_color = -1, int target_color = -1,
|
||||||
|
int tile_spacing_in = 0, int tile_spacing_out = 1);
|
||||||
void close();
|
void close();
|
||||||
[[nodiscard]] auto isOpen() const -> bool { return open_; }
|
[[nodiscard]] auto isOpen() const -> bool { return open_; }
|
||||||
|
|
||||||
@@ -49,6 +53,10 @@ class TilePicker {
|
|||||||
int current_tile_{-1}; // Tile actualmente seleccionado (highlight)
|
int current_tile_{-1}; // Tile actualmente seleccionado (highlight)
|
||||||
int hover_tile_{-1}; // Tile bajo el cursor
|
int hover_tile_{-1}; // Tile bajo el cursor
|
||||||
|
|
||||||
|
// Spacing
|
||||||
|
int spacing_in_{0}; // Spacing en el fichero fuente
|
||||||
|
int spacing_out_{1}; // Spacing visual al mostrar
|
||||||
|
|
||||||
// Scroll y posicionamiento
|
// Scroll y posicionamiento
|
||||||
int scroll_y_{0}; // Scroll vertical en pixels
|
int scroll_y_{0}; // Scroll vertical en pixels
|
||||||
int offset_x_{0}; // Offset X para centrar en pantalla
|
int offset_x_{0}; // Offset X para centrar en pantalla
|
||||||
|
|||||||
Reference in New Issue
Block a user