Refactor: Sistema de modos y notificaciones mejorado
Cambios principales: - Renombrado AppMode::MANUAL → AppMode::SANDBOX (nomenclatura más clara) - Notificaciones ahora funcionan en TODAS las transiciones de modo - Lógica de teclas D/L/K simplificada: toggle exclusivo modo ↔ SANDBOX - Mensajes simplificados: "MODO DEMO", "MODO SANDBOX", etc. (sin ON/OFF) - Eliminado check restrictivo en showNotificationForAction() Comportamiento nuevo: - Tecla D: Toggle DEMO ↔ SANDBOX - Tecla L: Toggle DEMO_LITE ↔ SANDBOX - Tecla K: Toggle LOGO ↔ SANDBOX - Cada tecla activa su modo o vuelve a SANDBOX si ya está activo - Notificaciones visibles tanto al activar como desactivar modos 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -329,8 +329,12 @@ void Engine::handleEvents() {
|
|||||||
// Si estamos en modo figura, salir a modo física SIN GRAVEDAD
|
// Si estamos en modo figura, salir a modo física SIN GRAVEDAD
|
||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
toggleShapeMode(false); // Desactivar figura sin forzar gravedad ON
|
toggleShapeMode(false); // Desactivar figura sin forzar gravedad ON
|
||||||
|
showNotificationForAction("Gravity Off");
|
||||||
} else {
|
} else {
|
||||||
switchBallsGravity(); // Toggle normal en modo física
|
switchBallsGravity(); // Toggle normal en modo física
|
||||||
|
// Determinar estado actual de gravedad (gravity_force_ != 0.0f significa ON)
|
||||||
|
bool gravity_on = balls_.empty() ? true : (balls_[0]->getGravityForce() != 0.0f);
|
||||||
|
showNotificationForAction(gravity_on ? "Gravity On" : "Gravity Off");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -343,6 +347,7 @@ void Engine::handleEvents() {
|
|||||||
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
||||||
}
|
}
|
||||||
changeGravityDirection(GravityDirection::UP);
|
changeGravityDirection(GravityDirection::UP);
|
||||||
|
showNotificationForAction("Gravity Up");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_DOWN:
|
case SDLK_DOWN:
|
||||||
@@ -353,6 +358,7 @@ void Engine::handleEvents() {
|
|||||||
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
||||||
}
|
}
|
||||||
changeGravityDirection(GravityDirection::DOWN);
|
changeGravityDirection(GravityDirection::DOWN);
|
||||||
|
showNotificationForAction("Gravity Down");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
@@ -363,6 +369,7 @@ void Engine::handleEvents() {
|
|||||||
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
||||||
}
|
}
|
||||||
changeGravityDirection(GravityDirection::LEFT);
|
changeGravityDirection(GravityDirection::LEFT);
|
||||||
|
showNotificationForAction("Gravity Left");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
@@ -373,6 +380,7 @@ void Engine::handleEvents() {
|
|||||||
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
|
||||||
}
|
}
|
||||||
changeGravityDirection(GravityDirection::RIGHT);
|
changeGravityDirection(GravityDirection::RIGHT);
|
||||||
|
showNotificationForAction("Gravity Right");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_V:
|
case SDLK_V:
|
||||||
@@ -386,43 +394,60 @@ void Engine::handleEvents() {
|
|||||||
// Toggle Física ↔ Última Figura (antes era C)
|
// Toggle Física ↔ Última Figura (antes era C)
|
||||||
case SDLK_F:
|
case SDLK_F:
|
||||||
toggleShapeMode();
|
toggleShapeMode();
|
||||||
|
// Mostrar notificación según el modo actual después del toggle
|
||||||
|
if (current_mode_ == SimulationMode::PHYSICS) {
|
||||||
|
showNotificationForAction("Physics Mode");
|
||||||
|
} else {
|
||||||
|
// Mostrar nombre de la figura actual
|
||||||
|
const char* shape_names[] = {"Sphere", "Lissajous", "Helix", "Torus", "Cube", "Cylinder", "Icosahedron", "Atom", "PNG Shape"};
|
||||||
|
showNotificationForAction(shape_names[static_cast<int>(current_shape_type_)]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Selección directa de figuras 3D
|
// Selección directa de figuras 3D
|
||||||
case SDLK_Q:
|
case SDLK_Q:
|
||||||
activateShape(ShapeType::SPHERE);
|
activateShape(ShapeType::SPHERE);
|
||||||
|
showNotificationForAction("Sphere");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_W:
|
case SDLK_W:
|
||||||
activateShape(ShapeType::LISSAJOUS);
|
activateShape(ShapeType::LISSAJOUS);
|
||||||
|
showNotificationForAction("Lissajous");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_E:
|
case SDLK_E:
|
||||||
activateShape(ShapeType::HELIX);
|
activateShape(ShapeType::HELIX);
|
||||||
|
showNotificationForAction("Helix");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_R:
|
case SDLK_R:
|
||||||
activateShape(ShapeType::TORUS);
|
activateShape(ShapeType::TORUS);
|
||||||
|
showNotificationForAction("Torus");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_T:
|
case SDLK_T:
|
||||||
activateShape(ShapeType::CUBE);
|
activateShape(ShapeType::CUBE);
|
||||||
|
showNotificationForAction("Cube");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_Y:
|
case SDLK_Y:
|
||||||
activateShape(ShapeType::CYLINDER);
|
activateShape(ShapeType::CYLINDER);
|
||||||
|
showNotificationForAction("Cylinder");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_U:
|
case SDLK_U:
|
||||||
activateShape(ShapeType::ICOSAHEDRON);
|
activateShape(ShapeType::ICOSAHEDRON);
|
||||||
|
showNotificationForAction("Icosahedron");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_I:
|
case SDLK_I:
|
||||||
activateShape(ShapeType::ATOM);
|
activateShape(ShapeType::ATOM);
|
||||||
|
showNotificationForAction("Atom");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_O:
|
case SDLK_O:
|
||||||
activateShape(ShapeType::PNG_SHAPE);
|
activateShape(ShapeType::PNG_SHAPE);
|
||||||
|
showNotificationForAction("PNG Shape");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Ciclar temas de color (movido de T a B)
|
// Ciclar temas de color (movido de T a B)
|
||||||
@@ -438,13 +463,8 @@ void Engine::handleEvents() {
|
|||||||
theme_manager_->cycleTheme();
|
theme_manager_->cycleTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mostrar nombre del tema (solo si NO estamos en modo demo)
|
// Mostrar notificación con el nombre del tema
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -454,12 +474,7 @@ void Engine::handleEvents() {
|
|||||||
{
|
{
|
||||||
int theme_index = (theme_page_ == 0) ? 0 : 10;
|
int theme_index = (theme_page_ == 0) ? 0 : 10;
|
||||||
theme_manager_->switchToTheme(theme_index);
|
theme_manager_->switchToTheme(theme_index);
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -468,12 +483,7 @@ void Engine::handleEvents() {
|
|||||||
{
|
{
|
||||||
int theme_index = (theme_page_ == 0) ? 1 : 11;
|
int theme_index = (theme_page_ == 0) ? 1 : 11;
|
||||||
theme_manager_->switchToTheme(theme_index);
|
theme_manager_->switchToTheme(theme_index);
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -482,12 +492,7 @@ void Engine::handleEvents() {
|
|||||||
{
|
{
|
||||||
int theme_index = (theme_page_ == 0) ? 2 : 12;
|
int theme_index = (theme_page_ == 0) ? 2 : 12;
|
||||||
theme_manager_->switchToTheme(theme_index);
|
theme_manager_->switchToTheme(theme_index);
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -496,12 +501,7 @@ void Engine::handleEvents() {
|
|||||||
{
|
{
|
||||||
int theme_index = (theme_page_ == 0) ? 3 : 13;
|
int theme_index = (theme_page_ == 0) ? 3 : 13;
|
||||||
theme_manager_->switchToTheme(theme_index);
|
theme_manager_->switchToTheme(theme_index);
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -510,12 +510,7 @@ void Engine::handleEvents() {
|
|||||||
{
|
{
|
||||||
int theme_index = (theme_page_ == 0) ? 4 : 14;
|
int theme_index = (theme_page_ == 0) ? 4 : 14;
|
||||||
theme_manager_->switchToTheme(theme_index);
|
theme_manager_->switchToTheme(theme_index);
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -523,12 +518,7 @@ void Engine::handleEvents() {
|
|||||||
// Solo página 0: MONOCHROME (5)
|
// Solo página 0: MONOCHROME (5)
|
||||||
if (theme_page_ == 0) {
|
if (theme_page_ == 0) {
|
||||||
theme_manager_->switchToTheme(5); // MONOCHROME
|
theme_manager_->switchToTheme(5); // MONOCHROME
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -536,12 +526,7 @@ void Engine::handleEvents() {
|
|||||||
// Solo página 0: LAVENDER (6)
|
// Solo página 0: LAVENDER (6)
|
||||||
if (theme_page_ == 0) {
|
if (theme_page_ == 0) {
|
||||||
theme_manager_->switchToTheme(6); // LAVENDER
|
theme_manager_->switchToTheme(6); // LAVENDER
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -549,12 +534,7 @@ void Engine::handleEvents() {
|
|||||||
// Solo página 0: CRIMSON (7)
|
// Solo página 0: CRIMSON (7)
|
||||||
if (theme_page_ == 0) {
|
if (theme_page_ == 0) {
|
||||||
theme_manager_->switchToTheme(7); // CRIMSON
|
theme_manager_->switchToTheme(7); // CRIMSON
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -562,12 +542,7 @@ void Engine::handleEvents() {
|
|||||||
// Solo página 0: EMERALD (8)
|
// Solo página 0: EMERALD (8)
|
||||||
if (theme_page_ == 0) {
|
if (theme_page_ == 0) {
|
||||||
theme_manager_->switchToTheme(8); // EMERALD
|
theme_manager_->switchToTheme(8); // EMERALD
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -575,12 +550,7 @@ void Engine::handleEvents() {
|
|||||||
// Solo página 0: SUNRISE (9)
|
// Solo página 0: SUNRISE (9)
|
||||||
if (theme_page_ == 0) {
|
if (theme_page_ == 0) {
|
||||||
theme_manager_->switchToTheme(9); // SUNRISE
|
theme_manager_->switchToTheme(9); // SUNRISE
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
showNotificationForAction(theme_manager_->getCurrentThemeNameES());
|
||||||
text_ = theme_manager_->getCurrentThemeNameES();
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -588,14 +558,7 @@ void Engine::handleEvents() {
|
|||||||
case SDLK_KP_ENTER:
|
case SDLK_KP_ENTER:
|
||||||
// Alternar entre página 0 y página 1
|
// Alternar entre página 0 y página 1
|
||||||
theme_page_ = (theme_page_ == 0) ? 1 : 0;
|
theme_page_ = (theme_page_ == 0) ? 1 : 0;
|
||||||
|
showNotificationForAction((theme_page_ == 0) ? "Página 1" : "Página 2");
|
||||||
// Mostrar feedback visual (solo si NO estamos en modo demo)
|
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
|
||||||
text_ = (theme_page_ == 0) ? "Página 1" : "Página 2";
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cambio de sprite/textura dinámico
|
// Cambio de sprite/textura dinámico
|
||||||
@@ -608,11 +571,7 @@ void Engine::handleEvents() {
|
|||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
shape_scale_factor_ += SHAPE_SCALE_STEP;
|
shape_scale_factor_ += SHAPE_SCALE_STEP;
|
||||||
clampShapeScale();
|
clampShapeScale();
|
||||||
text_ = "Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
|
showNotificationForAction("Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%");
|
||||||
int text_width = static_cast<int>(text_.length() * 8);
|
|
||||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
show_text_ = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -620,74 +579,70 @@ void Engine::handleEvents() {
|
|||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
shape_scale_factor_ -= SHAPE_SCALE_STEP;
|
shape_scale_factor_ -= SHAPE_SCALE_STEP;
|
||||||
clampShapeScale();
|
clampShapeScale();
|
||||||
text_ = "Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
|
showNotificationForAction("Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%");
|
||||||
int text_width = static_cast<int>(text_.length() * 8);
|
|
||||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
show_text_ = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_MULTIPLY:
|
case SDLK_KP_MULTIPLY:
|
||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
shape_scale_factor_ = SHAPE_SCALE_DEFAULT;
|
shape_scale_factor_ = SHAPE_SCALE_DEFAULT;
|
||||||
text_ = "Escala reiniciada (100%)";
|
showNotificationForAction("Escala 100%");
|
||||||
int text_width = static_cast<int>(text_.length() * 8);
|
|
||||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
show_text_ = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_DIVIDE:
|
case SDLK_KP_DIVIDE:
|
||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
depth_zoom_enabled_ = !depth_zoom_enabled_;
|
depth_zoom_enabled_ = !depth_zoom_enabled_;
|
||||||
text_ = depth_zoom_enabled_ ? "Zoom profundidad: On" : "Zoom profundidad: Off";
|
showNotificationForAction(depth_zoom_enabled_ ? "Depth Zoom On" : "Depth Zoom Off");
|
||||||
int text_width = static_cast<int>(text_.length() * 8);
|
|
||||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
show_text_ = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_1:
|
case SDLK_1:
|
||||||
scenario_ = 0;
|
scenario_ = 0;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("10 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_2:
|
case SDLK_2:
|
||||||
scenario_ = 1;
|
scenario_ = 1;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("50 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_3:
|
case SDLK_3:
|
||||||
scenario_ = 2;
|
scenario_ = 2;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("100 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_4:
|
case SDLK_4:
|
||||||
scenario_ = 3;
|
scenario_ = 3;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("500 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_5:
|
case SDLK_5:
|
||||||
scenario_ = 4;
|
scenario_ = 4;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("1,000 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_6:
|
case SDLK_6:
|
||||||
scenario_ = 5;
|
scenario_ = 5;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("5,000 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_7:
|
case SDLK_7:
|
||||||
scenario_ = 6;
|
scenario_ = 6;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("10,000 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_8:
|
case SDLK_8:
|
||||||
scenario_ = 7;
|
scenario_ = 7;
|
||||||
initBalls(scenario_);
|
initBalls(scenario_);
|
||||||
|
showNotificationForAction("50,000 Pelotas");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Controles de zoom dinámico (solo si no estamos en fullscreen)
|
// Controles de zoom dinámico (solo si no estamos en fullscreen)
|
||||||
@@ -724,22 +679,16 @@ void Engine::handleEvents() {
|
|||||||
if (event.key.mod & SDL_KMOD_SHIFT) {
|
if (event.key.mod & SDL_KMOD_SHIFT) {
|
||||||
theme_manager_->pauseDynamic();
|
theme_manager_->pauseDynamic();
|
||||||
} else {
|
} else {
|
||||||
// D sin Shift = Toggle modo DEMO
|
// D sin Shift = Toggle DEMO ↔ SANDBOX
|
||||||
if (current_app_mode_ == AppMode::DEMO) {
|
if (current_app_mode_ == AppMode::DEMO) {
|
||||||
// Desactivar DEMO → MANUAL
|
// Ya estamos en DEMO → volver a SANDBOX
|
||||||
setState(AppMode::MANUAL);
|
setState(AppMode::SANDBOX);
|
||||||
text_ = "Modo Demo: Off";
|
showNotificationForAction("MODO SANDBOX");
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
} else {
|
} else {
|
||||||
// Activar DEMO (desde cualquier otro modo)
|
// Estamos en otro modo → ir a DEMO
|
||||||
setState(AppMode::DEMO);
|
setState(AppMode::DEMO);
|
||||||
randomizeOnDemoStart(false);
|
randomizeOnDemoStart(false);
|
||||||
text_ = "Modo Demo: On";
|
showNotificationForAction("MODO DEMO");
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -747,35 +696,28 @@ void Engine::handleEvents() {
|
|||||||
// Toggle Modo DEMO LITE (solo física/figuras)
|
// Toggle Modo DEMO LITE (solo física/figuras)
|
||||||
case SDLK_L:
|
case SDLK_L:
|
||||||
if (current_app_mode_ == AppMode::DEMO_LITE) {
|
if (current_app_mode_ == AppMode::DEMO_LITE) {
|
||||||
// Desactivar DEMO_LITE → MANUAL
|
// Ya estamos en DEMO_LITE → volver a SANDBOX
|
||||||
setState(AppMode::MANUAL);
|
setState(AppMode::SANDBOX);
|
||||||
text_ = "Modo Demo Lite: Off";
|
showNotificationForAction("MODO SANDBOX");
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
} else {
|
} else {
|
||||||
// Activar DEMO_LITE (desde cualquier otro modo)
|
// Estamos en otro modo → ir a DEMO_LITE
|
||||||
setState(AppMode::DEMO_LITE);
|
setState(AppMode::DEMO_LITE);
|
||||||
randomizeOnDemoStart(true);
|
randomizeOnDemoStart(true);
|
||||||
text_ = "Modo Demo Lite: On";
|
showNotificationForAction("MODO DEMO LITE");
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Toggle Modo LOGO (easter egg - marca de agua)
|
// Toggle Modo LOGO (easter egg - marca de agua)
|
||||||
case SDLK_K:
|
case SDLK_K:
|
||||||
toggleLogoMode();
|
|
||||||
// Mostrar texto informativo
|
|
||||||
if (current_app_mode_ == AppMode::LOGO) {
|
if (current_app_mode_ == AppMode::LOGO) {
|
||||||
text_ = "Modo Logo: On";
|
// Ya estamos en LOGO → volver a SANDBOX
|
||||||
|
exitLogoMode(false);
|
||||||
|
showNotificationForAction("MODO SANDBOX");
|
||||||
} else {
|
} else {
|
||||||
text_ = "Modo Logo: Off";
|
// Estamos en otro modo → ir a LOGO
|
||||||
|
enterLogoMode(false);
|
||||||
|
showNotificationForAction("MODO LOGO");
|
||||||
}
|
}
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1039,12 +981,12 @@ void Engine::initBalls(int value) {
|
|||||||
float mass_factor = GRAVITY_MASS_MIN + (rand() % 1000) / 1000.0f * (GRAVITY_MASS_MAX - GRAVITY_MASS_MIN);
|
float mass_factor = GRAVITY_MASS_MIN + (rand() % 1000) / 1000.0f * (GRAVITY_MASS_MAX - GRAVITY_MASS_MIN);
|
||||||
balls_.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture_, current_screen_width_, current_screen_height_, current_ball_size_, current_gravity_, mass_factor));
|
balls_.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture_, current_screen_width_, current_screen_height_, current_ball_size_, current_gravity_, mass_factor));
|
||||||
}
|
}
|
||||||
setText(); // Actualiza el texto
|
// NOTA: setText() removido - las notificaciones ahora se llaman manualmente desde cada tecla
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setText() {
|
void Engine::setText() {
|
||||||
// Suprimir textos durante modos demo
|
// Suprimir textos durante modos demo
|
||||||
if (current_app_mode_ != AppMode::MANUAL) return;
|
if (current_app_mode_ != AppMode::SANDBOX) return;
|
||||||
|
|
||||||
// Generar texto de número de pelotas
|
// Generar texto de número de pelotas
|
||||||
int num_balls = BALL_COUNT_SCENARIOS[scenario_];
|
int num_balls = BALL_COUNT_SCENARIOS[scenario_];
|
||||||
@@ -1091,6 +1033,34 @@ void Engine::setText() {
|
|||||||
text_init_time_ = SDL_GetTicks();
|
text_init_time_ = SDL_GetTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::showNotificationForAction(const std::string& text) {
|
||||||
|
// IMPORTANTE: Esta función solo se llama desde handlers de teclado (acciones manuales)
|
||||||
|
// NUNCA se llama desde código automático (DEMO/LOGO), por lo tanto siempre mostramos notificación
|
||||||
|
|
||||||
|
// Obtener color del tema actual para el texto
|
||||||
|
int text_r, text_g, text_b;
|
||||||
|
theme_manager_->getCurrentThemeTextColor(text_r, text_g, text_b);
|
||||||
|
SDL_Color notification_color = {
|
||||||
|
static_cast<Uint8>(text_r),
|
||||||
|
static_cast<Uint8>(text_g),
|
||||||
|
static_cast<Uint8>(text_b),
|
||||||
|
255
|
||||||
|
};
|
||||||
|
|
||||||
|
// Obtener color de fondo de la notificación desde el tema
|
||||||
|
int bg_r, bg_g, bg_b;
|
||||||
|
theme_manager_->getCurrentNotificationBackgroundColor(bg_r, bg_g, bg_b);
|
||||||
|
SDL_Color notification_bg_color = {
|
||||||
|
static_cast<Uint8>(bg_r),
|
||||||
|
static_cast<Uint8>(bg_g),
|
||||||
|
static_cast<Uint8>(bg_b),
|
||||||
|
255
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mostrar notificación
|
||||||
|
notifier_.show(text, NOTIFICATION_DURATION, notification_color, notification_bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::pushBallsAwayFromGravity() {
|
void Engine::pushBallsAwayFromGravity() {
|
||||||
for (auto& ball : balls_) {
|
for (auto& ball : balls_) {
|
||||||
const int SIGNO = ((rand() % 2) * 2) - 1;
|
const int SIGNO = ((rand() % 2) * 2) - 1;
|
||||||
@@ -1552,7 +1522,7 @@ void Engine::setState(AppMode new_mode) {
|
|||||||
|
|
||||||
void Engine::updateDemoMode() {
|
void Engine::updateDemoMode() {
|
||||||
// Verificar si algún modo demo está activo (DEMO, DEMO_LITE o LOGO)
|
// Verificar si algún modo demo está activo (DEMO, DEMO_LITE o LOGO)
|
||||||
if (current_app_mode_ == AppMode::MANUAL) return;
|
if (current_app_mode_ == AppMode::SANDBOX) return;
|
||||||
|
|
||||||
// Actualizar timer
|
// Actualizar timer
|
||||||
demo_timer_ += delta_time_;
|
demo_timer_ += delta_time_;
|
||||||
@@ -1692,7 +1662,7 @@ void Engine::updateDemoMode() {
|
|||||||
|
|
||||||
// Solo salir automáticamente si NO llegamos desde MANUAL
|
// Solo salir automáticamente si NO llegamos desde MANUAL
|
||||||
// Probabilidad de salir: 60% en cada acción → sale rápido (relación DEMO:LOGO = 6:1)
|
// Probabilidad de salir: 60% en cada acción → sale rápido (relación DEMO:LOGO = 6:1)
|
||||||
if (previous_app_mode_ != AppMode::MANUAL && rand() % 100 < 60) {
|
if (previous_app_mode_ != AppMode::SANDBOX && rand() % 100 < 60) {
|
||||||
exitLogoMode(true); // Volver a DEMO/DEMO_LITE
|
exitLogoMode(true); // Volver a DEMO/DEMO_LITE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1891,7 +1861,7 @@ void Engine::performDemoAction(bool is_lite) {
|
|||||||
// Cambiar sprite (2%)
|
// Cambiar sprite (2%)
|
||||||
accumulated_weight += DEMO_WEIGHT_SPRITE;
|
accumulated_weight += DEMO_WEIGHT_SPRITE;
|
||||||
if (random_value < accumulated_weight) {
|
if (random_value < accumulated_weight) {
|
||||||
switchTexture();
|
switchTexture(false); // Suprimir notificación en modo automático
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1934,7 +1904,7 @@ void Engine::randomizeOnDemoStart(bool is_lite) {
|
|||||||
|
|
||||||
// 3. Sprite
|
// 3. Sprite
|
||||||
if (rand() % 2 == 0) {
|
if (rand() % 2 == 0) {
|
||||||
switchTexture();
|
switchTexture(false); // Suprimir notificación al activar modo DEMO
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Física o Figura
|
// 4. Física o Figura
|
||||||
@@ -2087,7 +2057,7 @@ void Engine::exitLogoMode(bool return_to_demo) {
|
|||||||
|
|
||||||
if (!return_to_demo) {
|
if (!return_to_demo) {
|
||||||
// Salida manual (tecla K): volver a MANUAL
|
// Salida manual (tecla K): volver a MANUAL
|
||||||
setState(AppMode::MANUAL);
|
setState(AppMode::SANDBOX);
|
||||||
} else {
|
} else {
|
||||||
// Volver al modo previo (DEMO o DEMO_LITE)
|
// Volver al modo previo (DEMO o DEMO_LITE)
|
||||||
setState(previous_app_mode_);
|
setState(previous_app_mode_);
|
||||||
@@ -2147,7 +2117,7 @@ void Engine::updateBallSizes(int old_size, int new_size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::switchTexture() {
|
void Engine::switchTexture(bool show_notification) {
|
||||||
if (textures_.empty()) return;
|
if (textures_.empty()) return;
|
||||||
|
|
||||||
// Guardar tamaño antiguo
|
// Guardar tamaño antiguo
|
||||||
@@ -2169,16 +2139,11 @@ void Engine::switchTexture() {
|
|||||||
// Ajustar posiciones según el cambio de tamaño
|
// Ajustar posiciones según el cambio de tamaño
|
||||||
updateBallSizes(old_size, new_size);
|
updateBallSizes(old_size, new_size);
|
||||||
|
|
||||||
// Mostrar texto informativo (solo si NO estamos en modo demo)
|
// Mostrar notificación con el nombre de la textura (solo si se solicita)
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
if (show_notification) {
|
||||||
// Obtener nombre de textura (uppercase)
|
|
||||||
std::string texture_name = texture_names_[current_texture_index_];
|
std::string texture_name = texture_names_[current_texture_index_];
|
||||||
std::transform(texture_name.begin(), texture_name.end(), texture_name.begin(), ::toupper);
|
std::transform(texture_name.begin(), texture_name.end(), texture_name.begin(), ::toupper);
|
||||||
|
showNotificationForAction("Sprite: " + texture_name);
|
||||||
text_ = "Sprite: " + texture_name;
|
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
|
||||||
show_text_ = true;
|
|
||||||
text_init_time_ = SDL_GetTicks();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2220,7 +2185,7 @@ void Engine::toggleShapeMode(bool force_gravity_on_exit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mostrar texto informativo (solo si NO estamos en modo demo o logo)
|
// Mostrar texto informativo (solo si NO estamos en modo demo o logo)
|
||||||
if (current_app_mode_ == AppMode::MANUAL) {
|
if (current_app_mode_ == AppMode::SANDBOX) {
|
||||||
text_ = "Modo Física";
|
text_ = "Modo Física";
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
||||||
text_init_time_ = SDL_GetTicks();
|
text_init_time_ = SDL_GetTicks();
|
||||||
@@ -2284,7 +2249,7 @@ void Engine::activateShape(ShapeType type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo o logo)
|
// Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo o logo)
|
||||||
if (active_shape_ && current_app_mode_ == AppMode::MANUAL) {
|
if (active_shape_ && current_app_mode_ == AppMode::SANDBOX) {
|
||||||
text_ = std::string("Modo ") + active_shape_->getName();
|
text_ = std::string("Modo ") + active_shape_->getName();
|
||||||
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
|
||||||
text_init_time_ = SDL_GetTicks();
|
text_init_time_ = SDL_GetTicks();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
// Modos de aplicación mutuamente excluyentes
|
// Modos de aplicación mutuamente excluyentes
|
||||||
enum class AppMode {
|
enum class AppMode {
|
||||||
MANUAL, // Control manual del usuario
|
SANDBOX, // Control manual del usuario (modo sandbox)
|
||||||
DEMO, // Modo demo completo (auto-play)
|
DEMO, // Modo demo completo (auto-play)
|
||||||
DEMO_LITE, // Modo demo lite (solo física/figuras)
|
DEMO_LITE, // Modo demo lite (solo física/figuras)
|
||||||
LOGO // Modo logo (easter egg)
|
LOGO // Modo logo (easter egg)
|
||||||
@@ -103,8 +103,8 @@ class Engine {
|
|||||||
bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado
|
bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado
|
||||||
|
|
||||||
// Sistema de Modo DEMO (auto-play)
|
// Sistema de Modo DEMO (auto-play)
|
||||||
AppMode current_app_mode_ = AppMode::MANUAL; // Modo actual (mutuamente excluyente)
|
AppMode current_app_mode_ = AppMode::SANDBOX; // Modo actual (mutuamente excluyente)
|
||||||
AppMode previous_app_mode_ = AppMode::MANUAL; // Modo previo antes de entrar a LOGO
|
AppMode previous_app_mode_ = AppMode::SANDBOX; // Modo previo antes de entrar a LOGO
|
||||||
float demo_timer_ = 0.0f; // Contador de tiempo para próxima acción
|
float demo_timer_ = 0.0f; // Contador de tiempo para próxima acción
|
||||||
float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos)
|
float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos)
|
||||||
|
|
||||||
@@ -142,7 +142,8 @@ class Engine {
|
|||||||
|
|
||||||
// Métodos auxiliares
|
// Métodos auxiliares
|
||||||
void initBalls(int value);
|
void initBalls(int value);
|
||||||
void setText();
|
void setText(); // DEPRECATED - usar showNotificationForAction() en su lugar
|
||||||
|
void showNotificationForAction(const std::string& text); // Mostrar notificación solo en modo MANUAL
|
||||||
void pushBallsAwayFromGravity();
|
void pushBallsAwayFromGravity();
|
||||||
void switchBallsGravity();
|
void switchBallsGravity();
|
||||||
void enableBallsGravityIfDisabled();
|
void enableBallsGravityIfDisabled();
|
||||||
@@ -170,8 +171,8 @@ class Engine {
|
|||||||
void exitLogoMode(bool return_to_demo = false); // Salir del modo logo
|
void exitLogoMode(bool return_to_demo = false); // Salir del modo logo
|
||||||
|
|
||||||
// Sistema de cambio de sprites dinámico
|
// Sistema de cambio de sprites dinámico
|
||||||
void switchTexture(); // Cambia a siguiente textura disponible
|
void switchTexture(bool show_notification = true); // Cambia a siguiente textura disponible
|
||||||
void updateBallSizes(int old_size, int new_size); // Ajusta posiciones al cambiar tamaño
|
void updateBallSizes(int old_size, int new_size); // Ajusta posiciones al cambiar tamaño
|
||||||
|
|
||||||
// Sistema de zoom dinámico
|
// Sistema de zoom dinámico
|
||||||
int calculateMaxWindowZoom() const;
|
int calculateMaxWindowZoom() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user