feat: F7/F8 redimensionan campo lógico, F1/F2 muestran notificación de zoom
- F7/F8: nuevo setFieldScale() cambia resolución lógica en pasos del 10% (mín 50%, máx limitado por pantalla), reinicia escena como F4 - F1/F2: muestran notificación "Zoom X%" al cambiar escala de ventana - Ventana física = lógico × zoom en todo momento; resizeWindowCentered() unifica el cálculo de posición leyendo el tamaño real con SDL_GetWindowSize - PostFXUniforms::time renombrado a screen_height; scanlines usan la altura lógica actual en lugar del 720 hardcodeado — F1/F2 escalan las scanlines visualmente, F7/F8 las mantienen a 1 franja por píxel lógico - Eliminados logs de debug de calculateMaxWindowScale y setWindowScale Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -84,8 +84,8 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
|
||||
window_zoom = 1;
|
||||
}
|
||||
|
||||
// Guardar zoom calculado ANTES de crear la ventana (para F1/F2/F3/F4)
|
||||
current_window_zoom_ = window_zoom;
|
||||
// Guardar escala inicial (siempre 1.0 salvo que CLI haya pedido zoom > 1)
|
||||
current_window_scale_ = static_cast<float>(window_zoom);
|
||||
|
||||
// Calcular tamaño de ventana
|
||||
int window_width = logical_width * window_zoom;
|
||||
@@ -427,7 +427,7 @@ void Engine::calculateDeltaTime() {
|
||||
|
||||
void Engine::update() {
|
||||
// Accumulate time for PostFX uniforms
|
||||
postfx_uniforms_.time += delta_time_;
|
||||
postfx_uniforms_.screen_height = static_cast<float>(current_screen_height_);
|
||||
|
||||
// Actualizar visibilidad del cursor (auto-ocultar tras inactividad)
|
||||
Mouse::updateCursorVisibility();
|
||||
@@ -953,7 +953,9 @@ void Engine::toggleFullscreen() {
|
||||
|
||||
// Si acabamos de salir de fullscreen, restaurar tamaño de ventana
|
||||
if (!fullscreen_enabled_) {
|
||||
SDL_SetWindowSize(window_, base_screen_width_ * current_window_zoom_, base_screen_height_ * current_window_zoom_);
|
||||
int restore_w = static_cast<int>(std::round(base_screen_width_ * current_window_scale_));
|
||||
int restore_h = static_cast<int>(std::round(base_screen_height_ * current_window_scale_));
|
||||
SDL_SetWindowSize(window_, restore_w, restore_h);
|
||||
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
@@ -1018,10 +1020,13 @@ void Engine::toggleRealFullscreen() {
|
||||
// Volver a resolución base (configurada por CLI o default)
|
||||
current_screen_width_ = base_screen_width_;
|
||||
current_screen_height_ = base_screen_height_;
|
||||
current_field_scale_ = 1.0f; // Resetear escala de campo al salir de fullscreen real
|
||||
|
||||
// Restaurar ventana normal con el zoom actual (no hardcoded)
|
||||
// Restaurar ventana normal con la escala actual
|
||||
SDL_SetWindowFullscreen(window_, false);
|
||||
SDL_SetWindowSize(window_, base_screen_width_ * current_window_zoom_, base_screen_height_ * current_window_zoom_);
|
||||
int restore_w = static_cast<int>(std::round(base_screen_width_ * current_window_scale_));
|
||||
int restore_h = static_cast<int>(std::round(base_screen_height_ * current_window_scale_));
|
||||
SDL_SetWindowSize(window_, restore_w, restore_h);
|
||||
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
|
||||
// Recrear render target offscreen con resolución base
|
||||
@@ -1148,85 +1153,112 @@ void Engine::addSpriteToBatch(float x, float y, float w, float h, int r, int g,
|
||||
static_cast<float>(current_screen_height_));
|
||||
}
|
||||
|
||||
// Sistema de zoom dinámico
|
||||
int Engine::calculateMaxWindowZoom() const {
|
||||
// Obtener información del display usando el método de Coffee Crisis
|
||||
int num_displays = 0;
|
||||
SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
|
||||
if (displays == nullptr || num_displays == 0) {
|
||||
return WINDOW_ZOOM_MIN; // Fallback si no se puede obtener
|
||||
// Sistema de escala de ventana (pasos del 10%)
|
||||
float Engine::calculateMaxWindowScale() const {
|
||||
SDL_Rect bounds;
|
||||
if (!SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &bounds)) { // bool: false = error
|
||||
return WINDOW_SCALE_MIN; // Fallback solo si falla de verdad
|
||||
}
|
||||
|
||||
// Obtener el modo de display actual
|
||||
const auto* dm = SDL_GetCurrentDisplayMode(displays[0]);
|
||||
if (dm == nullptr) {
|
||||
SDL_free(displays);
|
||||
return WINDOW_ZOOM_MIN;
|
||||
}
|
||||
|
||||
// Calcular zoom máximo usando la fórmula de Coffee Crisis
|
||||
const int MAX_ZOOM = std::min(dm->w / base_screen_width_, (dm->h - WINDOW_DECORATION_HEIGHT) / base_screen_height_);
|
||||
|
||||
SDL_free(displays);
|
||||
|
||||
// Aplicar límites
|
||||
return std::max(WINDOW_ZOOM_MIN, std::min(MAX_ZOOM, WINDOW_ZOOM_MAX));
|
||||
float max_by_w = static_cast<float>(bounds.w - 2 * WINDOW_DESKTOP_MARGIN) / base_screen_width_;
|
||||
float max_by_h = static_cast<float>(bounds.h - 2 * WINDOW_DESKTOP_MARGIN - WINDOW_DECORATION_HEIGHT) / base_screen_height_;
|
||||
float result = std::max(WINDOW_SCALE_MIN, std::min(max_by_w, max_by_h));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Engine::setWindowZoom(int new_zoom) {
|
||||
// Validar zoom
|
||||
int max_zoom = calculateMaxWindowZoom();
|
||||
new_zoom = std::max(WINDOW_ZOOM_MIN, std::min(new_zoom, max_zoom));
|
||||
// Redimensiona la ventana física manteniéndo su centro, con clamping a pantalla.
|
||||
static void resizeWindowCentered(SDL_Window* window, int new_w, int new_h) {
|
||||
int cur_x, cur_y, cur_w, cur_h;
|
||||
SDL_GetWindowPosition(window, &cur_x, &cur_y);
|
||||
SDL_GetWindowSize(window, &cur_w, &cur_h);
|
||||
|
||||
if (new_zoom == current_window_zoom_) {
|
||||
return; // No hay cambio
|
||||
int new_x = cur_x + (cur_w - new_w) / 2;
|
||||
int new_y = cur_y + (cur_h - new_h) / 2;
|
||||
|
||||
SDL_Rect bounds;
|
||||
if (SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &bounds)) {
|
||||
new_x = std::max(WINDOW_DESKTOP_MARGIN,
|
||||
std::min(new_x, bounds.w - new_w - WINDOW_DESKTOP_MARGIN));
|
||||
new_y = std::max(WINDOW_DESKTOP_MARGIN,
|
||||
std::min(new_y, bounds.h - new_h - WINDOW_DESKTOP_MARGIN - WINDOW_DECORATION_HEIGHT));
|
||||
}
|
||||
|
||||
// Obtener posición actual del centro de la ventana
|
||||
int current_x, current_y;
|
||||
SDL_GetWindowPosition(window_, ¤t_x, ¤t_y);
|
||||
int current_center_x = current_x + (base_screen_width_ * current_window_zoom_) / 2;
|
||||
int current_center_y = current_y + (base_screen_height_ * current_window_zoom_) / 2;
|
||||
SDL_SetWindowSize(window, new_w, new_h);
|
||||
SDL_SetWindowPosition(window, new_x, new_y);
|
||||
}
|
||||
|
||||
// Calcular nuevo tamaño
|
||||
int new_width = base_screen_width_ * new_zoom;
|
||||
int new_height = base_screen_height_ * new_zoom;
|
||||
void Engine::setWindowScale(float new_scale) {
|
||||
float max_scale = calculateMaxWindowScale();
|
||||
new_scale = std::max(WINDOW_SCALE_MIN, std::min(new_scale, max_scale));
|
||||
new_scale = std::round(new_scale * 10.0f) / 10.0f;
|
||||
|
||||
// Calcular nueva posición (centrada en el punto actual)
|
||||
int new_x = current_center_x - new_width / 2;
|
||||
int new_y = current_center_y - new_height / 2;
|
||||
if (new_scale == current_window_scale_) return;
|
||||
|
||||
// Obtener límites del escritorio para no salirse
|
||||
SDL_Rect display_bounds;
|
||||
if (SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &display_bounds) == 0) {
|
||||
// Aplicar márgenes
|
||||
int min_x = WINDOW_DESKTOP_MARGIN;
|
||||
int min_y = WINDOW_DESKTOP_MARGIN;
|
||||
int max_x = display_bounds.w - new_width - WINDOW_DESKTOP_MARGIN;
|
||||
int max_y = display_bounds.h - new_height - WINDOW_DESKTOP_MARGIN - WINDOW_DECORATION_HEIGHT;
|
||||
int new_width = static_cast<int>(std::round(current_screen_width_ * new_scale));
|
||||
int new_height = static_cast<int>(std::round(current_screen_height_ * new_scale));
|
||||
|
||||
// Limitar posición
|
||||
new_x = std::max(min_x, std::min(new_x, max_x));
|
||||
new_y = std::max(min_y, std::min(new_y, max_y));
|
||||
}
|
||||
resizeWindowCentered(window_, new_width, new_height);
|
||||
current_window_scale_ = new_scale;
|
||||
|
||||
// Aplicar cambios
|
||||
SDL_SetWindowSize(window_, new_width, new_height);
|
||||
SDL_SetWindowPosition(window_, new_x, new_y);
|
||||
current_window_zoom_ = new_zoom;
|
||||
|
||||
// Actualizar tamaño físico de ventana y fuentes
|
||||
updatePhysicalWindowSize();
|
||||
}
|
||||
|
||||
void Engine::zoomIn() {
|
||||
setWindowZoom(current_window_zoom_ + 1);
|
||||
float prev = current_window_scale_;
|
||||
setWindowScale(current_window_scale_ + WINDOW_SCALE_STEP);
|
||||
if (current_window_scale_ != prev) {
|
||||
char buf[32];
|
||||
std::snprintf(buf, sizeof(buf), "Zoom %.0f%%", current_window_scale_ * 100.0f);
|
||||
showNotificationForAction(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::zoomOut() {
|
||||
setWindowZoom(current_window_zoom_ - 1);
|
||||
float prev = current_window_scale_;
|
||||
setWindowScale(current_window_scale_ - WINDOW_SCALE_STEP);
|
||||
if (current_window_scale_ != prev) {
|
||||
char buf[32];
|
||||
std::snprintf(buf, sizeof(buf), "Zoom %.0f%%", current_window_scale_ * 100.0f);
|
||||
showNotificationForAction(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::setFieldScale(float new_scale) {
|
||||
float max_scale = calculateMaxWindowScale();
|
||||
new_scale = std::max(WINDOW_SCALE_MIN, std::min(new_scale, max_scale));
|
||||
new_scale = std::round(new_scale * 10.0f) / 10.0f;
|
||||
if (new_scale == current_field_scale_) return;
|
||||
|
||||
current_field_scale_ = new_scale;
|
||||
current_screen_width_ = static_cast<int>(std::round(base_screen_width_ * new_scale));
|
||||
current_screen_height_ = static_cast<int>(std::round(base_screen_height_ * new_scale));
|
||||
|
||||
// Ajustar ventana física: campo lógico × zoom actual, manteniendo centro
|
||||
int phys_w = static_cast<int>(std::round(current_screen_width_ * current_window_scale_));
|
||||
int phys_h = static_cast<int>(std::round(current_screen_height_ * current_window_scale_));
|
||||
resizeWindowCentered(window_, phys_w, phys_h);
|
||||
|
||||
// Recrear render target con nueva resolución lógica
|
||||
recreateOffscreenTexture();
|
||||
updatePhysicalWindowSize();
|
||||
|
||||
// Reiniciar escena (igual que F4)
|
||||
scene_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||
scene_manager_->changeScenario(scene_manager_->getCurrentScenario(), current_mode_);
|
||||
boid_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||
shape_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||
if (app_logo_) app_logo_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||
if (current_mode_ == SimulationMode::SHAPE) {
|
||||
generateShape();
|
||||
scene_manager_->enableShapeAttractionAll(true);
|
||||
}
|
||||
|
||||
showNotificationForAction("Campo " + std::to_string(current_screen_width_) +
|
||||
" x " + std::to_string(current_screen_height_));
|
||||
}
|
||||
|
||||
void Engine::fieldSizeUp() { setFieldScale(current_field_scale_ + WINDOW_SCALE_STEP); }
|
||||
void Engine::fieldSizeDown() { setFieldScale(current_field_scale_ - WINDOW_SCALE_STEP); }
|
||||
|
||||
void Engine::updatePhysicalWindowSize() {
|
||||
if (real_fullscreen_enabled_) {
|
||||
// En fullscreen real (F4), usar resolución del display
|
||||
@@ -1254,6 +1286,7 @@ void Engine::updatePhysicalWindowSize() {
|
||||
|
||||
// Notificar a UIManager del cambio de tamaño (delegado)
|
||||
ui_manager_->updatePhysicalWindowSize(physical_window_width_, physical_window_height_);
|
||||
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user