- afegides opcions persistents al editor

- afegida rejilla
This commit is contained in:
2026-04-02 17:38:03 +02:00
parent 44b6f6830d
commit 3c3e012386
7 changed files with 144 additions and 5 deletions

View File

@@ -139,6 +139,7 @@ class Surface {
// Paleta
void setPalette(const std::array<Uint32, 256>& palette) { palette_ = palette; }
[[nodiscard]] auto getPaletteColor(Uint8 index) const -> Uint32 { return palette_[index]; }
// Inicializa la sub paleta
static void initializeSubPalette(SubPalette& palette) { std::iota(palette.begin(), palette.end(), 0); }

View File

@@ -5,9 +5,11 @@
#include <SDL3/SDL.h>
#include <cmath> // Para std::round
#include <fstream> // Para ifstream, ofstream
#include <iostream> // Para cout
#include "core/input/mouse.hpp" // Para Mouse
#include "core/rendering/render_info.hpp" // Para RenderInfo
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface.hpp" // Para Surface
#include "core/resources/resource_cache.hpp" // Para Resource::Cache
@@ -40,11 +42,64 @@ auto MapEditor::get() -> MapEditor* {
}
// Constructor
MapEditor::MapEditor() = default;
MapEditor::MapEditor() {
loadSettings();
}
// Destructor
MapEditor::~MapEditor() = default;
// Carga las opciones del editor desde editor.yaml
void MapEditor::loadSettings() {
std::string path = Resource::List::get()->get("editor.yaml");
if (path.empty()) { return; }
std::ifstream file(path);
if (!file.is_open()) { return; }
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
try {
auto yaml = fkyaml::node::deserialize(content);
if (yaml.contains("grid")) { settings_.grid = yaml["grid"].get_value<bool>(); }
if (yaml.contains("show_render_info")) { settings_.show_render_info = yaml["show_render_info"].get_value<bool>(); }
} catch (...) {
// Fichero corrupto o vacío, usar defaults
}
}
// Guarda las opciones del editor a editor.yaml
void MapEditor::saveSettings() {
std::string path = Resource::List::get()->get("editor.yaml");
if (path.empty()) { return; }
std::ofstream file(path);
if (!file.is_open()) { return; }
file << "# Map Editor Settings\n";
file << "grid: " << (settings_.grid ? "true" : "false") << "\n";
file << "show_render_info: " << (settings_.show_render_info ? "true" : "false") << "\n";
file.close();
}
// Muestra/oculta render info (persistente)
auto MapEditor::showInfo(bool show) -> std::string {
settings_.show_render_info = show;
if (RenderInfo::get()->isActive() != show) {
RenderInfo::get()->toggle();
}
saveSettings();
return show ? "Info ON" : "Info OFF";
}
// Muestra/oculta grid (persistente)
auto MapEditor::showGrid(bool show) -> std::string {
settings_.grid = show;
saveSettings();
return show ? "Grid ON" : "Grid OFF";
}
// Entra en modo editor
void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player, const std::string& room_path, std::shared_ptr<Scoreboard::Data> scoreboard_data) {
if (active_) { return; }
@@ -72,6 +127,12 @@ void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player
Options::cheats.invincible = Options::Cheat::State::ENABLED;
player_->setColor();
// Guardar estado de render_info y aplicar el setting del editor
render_info_before_editor_ = RenderInfo::get()->isActive();
if (settings_.show_render_info != render_info_before_editor_) {
RenderInfo::get()->toggle();
}
// Resetear enemigos a su posición inicial (pueden haberse movido durante el gameplay)
room_->resetEnemyPositions(room_data_.enemies);
@@ -99,6 +160,11 @@ void MapEditor::exit() {
Options::cheats.invincible = invincible_before_editor_;
player_->setColor();
// Restaurar render_info
if (RenderInfo::get()->isActive() != render_info_before_editor_) {
RenderInfo::get()->toggle();
}
// Restaurar prompt de la consola y limpiar estado
selected_enemy_ = -1;
Console::get()->setPrompt("> ");
@@ -203,6 +269,11 @@ void MapEditor::update(float delta_time) {
void MapEditor::render() {
// El tilemap ya ha sido renderizado por Game::renderPlaying() antes de llamar aquí
// Grid (debajo de todo)
if (settings_.grid) {
renderGrid();
}
// Renderizar los marcadores de boundaries y líneas de ruta (debajo de los sprites)
renderEnemyBoundaries();
@@ -1136,4 +1207,40 @@ auto MapEditor::duplicateItem() -> std::string {
return "Duplicated as item " + std::to_string(selected_item_);
}
// Elige un color de grid que contraste con el fondo
// Empieza con bright_black (1), si coincide con el bg en la paleta activa, sube índices
static auto pickGridColor(Uint8 bg, const std::shared_ptr<Surface>& surface) -> Uint8 {
Uint8 grid = static_cast<Uint8>(PaletteColor::BRIGHT_BLACK);
Uint32 bg_argb = surface->getPaletteColor(bg);
// Si bright_black es igual al bg, buscar el siguiente color distinto
while (grid < 15 && surface->getPaletteColor(grid) == bg_argb) {
grid += 2; // Saltar de 2 en 2 para mantenerse en tonos discretos
}
return grid;
}
// Dibuja la cuadrícula de tiles (líneas de puntos, 1 pixel sí / 1 no)
void MapEditor::renderGrid() {
auto game_surface = Screen::get()->getRendererSurface();
if (!game_surface) { return; }
const Uint8 COLOR = pickGridColor(stringToColor(room_data_.bg_color), game_surface);
// Líneas verticales (cada 8 pixels)
for (int x = Tile::SIZE; x < PlayArea::WIDTH; x += Tile::SIZE) {
for (int y = 0; y < PlayArea::HEIGHT; y += 2) {
game_surface->putPixel(x, y, COLOR);
}
}
// Líneas horizontales (cada 8 pixels)
for (int y = Tile::SIZE; y < PlayArea::HEIGHT; y += Tile::SIZE) {
for (int x = 0; x < PlayArea::WIDTH; x += 2) {
game_surface->putPixel(x, y, COLOR);
}
}
}
#endif // _DEBUG

View File

@@ -43,6 +43,11 @@ class MapEditor {
// Comandos para propiedades de la habitación
auto setRoomProperty(const std::string& property, const std::string& value) -> std::string;
// Opciones del editor (llamados desde console_commands / teclas)
auto showInfo(bool show) -> std::string;
auto showGrid(bool show) -> std::string;
[[nodiscard]] auto isGridEnabled() const -> bool { return settings_.grid; }
// Comandos para items
auto setItemProperty(const std::string& property, const std::string& value) -> std::string;
auto addItem() -> std::string;
@@ -57,6 +62,15 @@ class MapEditor {
MapEditor(); // Constructor
~MapEditor(); // Destructor
// Opciones persistentes del editor
struct Settings {
bool grid{false};
bool show_render_info{false};
};
Settings settings_;
void loadSettings();
void saveSettings();
// Tipos para drag & drop y selección
enum class DragTarget { NONE,
PLAYER,
@@ -80,6 +94,7 @@ class MapEditor {
void renderEnemyBoundaries();
void renderBoundaryMarker(float x, float y, Uint8 color);
void renderSelectionHighlight();
void renderGrid();
void handleMouseDown(float game_x, float game_y);
void handleMouseUp();
void updateDrag();
@@ -124,8 +139,9 @@ class MapEditor {
int mouse_tile_x_{0};
int mouse_tile_y_{0};
// Estado previo de invencibilidad
// Estado previo (para restaurar al salir)
Options::Cheat::State invincible_before_editor_{Options::Cheat::State::DISABLED};
bool render_info_before_editor_{false};
};
#endif // _DEBUG

View File

@@ -191,6 +191,8 @@ void Game::handleEvents() {
GameControl::enter_editor();
Notifier::get()->show({Locale::get()->get("game.editor_enabled")}); // NOLINT(readability-static-accessed-through-instance)
}
} else if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_8 && static_cast<int>(event.key.repeat) == 0 && MapEditor::get()->isActive()) {
MapEditor::get()->showGrid(!MapEditor::get()->isGridEnabled());
} else if (MapEditor::get()->isActive()) {
MapEditor::get()->handleEvent(event);
} else {

View File

@@ -702,7 +702,14 @@ static auto cmd_edit(const std::vector<std::string>& args) -> std::string {
}
return "Editor not active";
}
return "usage: edit [on|off|revert]";
// EDIT SHOW/HIDE INFO/GRID
if ((args[0] == "SHOW" || args[0] == "HIDE") && args.size() >= 2) {
if (!MapEditor::get() || !MapEditor::get()->isActive()) { return "Editor not active"; }
bool show = (args[0] == "SHOW");
if (args[1] == "INFO") { return MapEditor::get()->showInfo(show); }
if (args[1] == "GRID") { return MapEditor::get()->showGrid(show); }
}
return "usage: edit [on|off|revert|show|hide] [info|grid]";
}
// SET <property> <value> — modifica propiedad del enemigo seleccionado o de la habitación