diff --git a/source/game/editor/editor.cpp b/source/game/editor/editor.cpp index 183b67d..5ced037 100644 --- a/source/game/editor/editor.cpp +++ b/source/game/editor/editor.cpp @@ -9,12 +9,15 @@ #include "core/input/key_config.hpp" #include "core/locale/locale.hpp" +#include "core/rendering/hud_constants.hpp" #include "core/rendering/notification_presets.hpp" #include "core/rendering/screen.hpp" #include "core/rendering/surface.hpp" +#include "core/rendering/text.hpp" #include "core/resources/resource_cache.hpp" #include "core/resources/resource_helper.hpp" #include "core/system/event_buffer.hpp" +#include "core/ui/ui_config.hpp" #include "external/fkyaml_node.hpp" #include "game/editor/editor_config.hpp" #include "game/entities/entity.hpp" @@ -185,9 +188,19 @@ void Editor::enter() { brush_entity_.clear(); hand_selected_idx_ = -1; ensureEditableEntities(); + ensureHudFont(); Notification::notify(Locale::get().text("input.editor_on")); } +void Editor::ensureHudFont() { + if (hud_font_ != nullptr) { return; } + const auto KEY = UiConfig::get().hudFont().name + ".gif"; + auto surface = Resource::Cache::get().getSurface(KEY); + if (surface == nullptr) { return; } + hud_font_ = std::make_shared(surface, UiConfig::get().hudFont().fnt); + hud_font_->setDefaultKerning(UiConfig::get().hudFont().kerning); +} + void Editor::ensureEditableEntities() { if (!editable_entities_.empty()) { return; } // Recorrem tots els noms registrats al factory i ens quedem amb els @@ -623,6 +636,67 @@ void Editor::deleteSelected(EntityManager& entities) { if (entities.removeEntity(target)) { hand_selected_idx_ = -1; } } +void Editor::renderEditorHud(const EntityManager& entities) const { + if (hud_font_ == nullptr || Map::hud_h <= 0) { return; } + auto& screen = Screen::get(); + const auto& pal = Resource::Cache::get().getPalette("ui"); + screen.fillRect(0, 0, GameCanvas::WIDTH, Map::hud_h, pal[UiConfig::get().hudBg()]); + + std::string mode_str; + switch (mode_) { + case Mode::TILE: + mode_str = "TILE"; + break; + case Mode::ENTITY: + mode_str = "ENTITY"; + break; + case Mode::HAND: + mode_str = "HAND"; + break; + } + + std::string brush_label; + std::string brush_value; + if (mode_ == Mode::TILE) { + brush_label = "BRUSH:"; + brush_value = (brush_tile_ >= 0) ? std::to_string(brush_tile_) : "-"; + } else if (mode_ == Mode::ENTITY) { + brush_label = "BRUSH:"; + brush_value = brush_entity_.empty() ? "-" : brush_entity_; + } else { + const auto LIST = entities.getEntities(); + brush_label = "SEL:"; + brush_value = (hand_selected_idx_ >= 0 && hand_selected_idx_ < static_cast(LIST.size())) + ? LIST[hand_selected_idx_]->getName() + : "-"; + } + + const std::string COORD = (cursor_col_ >= 0) + ? "(" + std::to_string(cursor_col_) + "," + std::to_string(cursor_row_) + ")" + : "(--,--)"; + + const auto LBL = UiConfig::get().hudLabel(); + const auto VAL = UiConfig::get().hudValue(); + const int KERN = UiConfig::get().hudFont().kerning; + const int Y = (Map::hud_h - Rendering::Hud::FONT_SIZE_PX) / 2; + int x = 2; + + auto draw = [&](const std::string& s, std::uint8_t color) { + hud_font_->writeColored(x, Y, s, color, KERN); + x += hud_font_->length(s, KERN); + }; + + draw("MODE:", LBL); + draw(" " + mode_str, VAL); + draw(" " + brush_label, LBL); + draw(" " + brush_value, VAL); + draw(" " + COORD, VAL); + draw(" DOOR:", LBL); + draw(" " + std::to_string(countByName(entities, "door")), VAL); + draw(" SARCS:", LBL); + draw(" " + std::to_string(countByName(entities, "sarcophagus")), VAL); +} + void Editor::renderEntityFrame(const Entity& e, std::uint32_t argb) { const auto R = e.getPixelRect(); auto& screen = Screen::get(); @@ -793,6 +867,13 @@ void Editor::render(const Tilemap& tilemap, const EntityManager& entities) const } } + // HUD d'edició: només quan no hi ha picker obert (no té sentit + // tapar el picker amb la franja). Es pinta abans del border per + // que la línia de vora quedi visible per damunt. + if (picker_ == Picker::NONE) { + renderEditorHud(entities); + } + const auto BORDER = EditorConfig::get().borderArgb(); screen.fillRect(0, 0, W, 1, BORDER); screen.fillRect(0, H - 1, W, 1, BORDER); diff --git a/source/game/editor/editor.hpp b/source/game/editor/editor.hpp index 90e7637..500db4f 100644 --- a/source/game/editor/editor.hpp +++ b/source/game/editor/editor.hpp @@ -10,6 +10,7 @@ class Entity; class EntityManager; class Surface; +class Text; class Tilemap; // Mode editor modal del GameScene. Només disponible en Debug — en Release @@ -117,6 +118,13 @@ class Editor { // Render del marc d'una entitat: 1 px sobre el seu pixel_rect. static void renderEntityFrame(const Entity& e, std::uint32_t argb); + // HUD d'edició: franja superior amb mode, brush, cursor i comptadors + // de constraints. Substitueix el HUD del joc mentre l'editor és actiu. + void renderEditorHud(const EntityManager& entities) const; + + // Carrega la font 8bithud del cache. Lazy: al primer enter(). + void ensureHudFont(); + void renderTilePicker(const Tilemap& tilemap) const; void renderEntityPicker(const Tilemap& tilemap) const; @@ -159,6 +167,11 @@ class Editor { std::vector editable_entities_; + // Font compartida amb el Notifier/HUD: el surface el carrega Director + // a l'arrencada, ací només prenem la referència del cache. shared_ptr + // perquè `Text` accepta el surface per shared_ptr i així no copiem. + std::shared_ptr hud_font_; + // Selecció en Mode::HAND. Treballem amb índexs sobre el snapshot de // `EntityManager::getEntities()` perquè és el que ens dóna l'API // pública. Després de cada mutació (move/delete) ho recalculem; com