- afegides opcions persistents al editor
- afegida rejilla
This commit is contained in:
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user