feat(editor): màquina d'estats Mode {TILE,ENTITY,HAND} + Picker

This commit is contained in:
JailDesigner committed 2026-05-02 10:58:24 +02:00
1 parent ca03a1307e
commit 2ef5968e0d
2 files changed
+196 -84

No files matched your search

+68 -21
View File
@@ -2,6 +2,9 @@
#ifdef _DEBUG
#include <cstdint>
#include <string>
class Tilemap;
// Mode editor modal del GameScene. Només disponible en Debug — en Release
@@ -11,13 +14,21 @@ class Tilemap;
// L'editor NO gestiona la tecla de toggle pròpia (`editor_toggle`): això
// ho fa GameScene per poder decidir la coexistència amb la pausa F11
// (mútuament excloents). L'editor s'encarrega de:
// - Estat propi (actiu/no actiu, brush, picker obert).
// - Input del ratolí i tecles internes (`T`, `ESC`).
// - Estat propi (mode actiu, brush per mode, picker obert).
// - Input del ratolí i tecles internes (`T`, `E`, `H`, `Supr`, `ESC`).
// - Render del border blau + brush preview + picker.
// - Persistència del tilemap al YAML del repo en sortir.
// - Persistència del tilemap i de les entitats al YAML del repo en sortir.
//
// GameScene, quan `active()` és true, salta el tick de jugadors/entitats
// i no els pinta; el tilemap sí es pinta perquè és el que s'està editant.
// Modes del cursor (`Mode`):
// - TILE : el clic esquerre pinta el `brush_tile_` al tilemap.
// - ENTITY : el clic esquerre col·loca una instància de `brush_entity_`.
// - HAND : selecciona/mou/borra entitats existents.
//
// Pickers (`Picker`):
// - TILE_PICKER (`T`) : selecciona índex de tile.
// - ENTITY_PICKER (`E`) : selecciona tipus d'entitat (nom registrat al
// factory).
// Mútuament excloents: obrir un tanca l'altre.
class Editor {
public:
// Entra al mode editor: notifica i marca `active=true`. La congelació
@@ -37,29 +48,65 @@ class Editor {
// Processa input propi (brush, picker). No-op si no actiu.
void update(int delta_ms, Tilemap& tilemap);
// Pinta el border blau i, més endavant, brush preview + picker.
// No-op si no actiu.
// Pinta el border blau i, segons mode i picker, brush preview, marc
// d'entitat seleccionada o el picker. No-op si no actiu.
void render(const Tilemap& tilemap) const;
private:
// Les branques d'update / render segons el mode (picker obert o
// pintura al mapa) queden separades per claredat; no formen part
// de l'API pública perquè només té sentit cridar-les des d'`update`.
void updateMap(Tilemap& tilemap, int canvas_x, int canvas_y);
void updatePicker(const Tilemap& tilemap, int canvas_x, int canvas_y);
void renderPicker(const Tilemap& tilemap) const;
// Mode del cursor: determina què fa el clic esquerre sobre el mapa.
enum class Mode : std::uint8_t { TILE,
ENTITY,
HAND };
// Quin picker està obert (si n'hi ha). Mútuament excloents.
enum class Picker : std::uint8_t { NONE,
TILE,
ENTITY };
// Consum de hotkeys pròpies (T, E, H, ESC). Modifica `mode_` / `picker_`.
// Es crida al principi d'`update` perquè altres handlers no vegin
// tecles ja interpretades pel propi editor.
void handleHotkeys();
// Aplica una tecla i retorna true si l'editor l'ha consumit. Aïllat
// per mantenir baixa la complexitat cognitiva de `handleHotkeys` —
// l'iteració del buffer queda neta i la lògica de transició viu en
// un sol lloc.
auto applyHotkey(int scancode) -> bool;
// Branques d'update segons (mode, picker). Només té sentit cridar-les
// des d'`update`.
void updateTileBrush(Tilemap& tilemap, int canvas_x, int canvas_y);
void updateEntityBrush(int canvas_x, int canvas_y);
void updateHand(int canvas_x, int canvas_y);
void updateTilePicker(const Tilemap& tilemap, int canvas_x, int canvas_y);
void updateEntityPicker(int canvas_x, int canvas_y);
void renderTilePicker(const Tilemap& tilemap) const;
void renderEntityPicker(const Tilemap& tilemap) const;
bool active_{false};
Mode mode_{Mode::TILE};
Picker picker_{Picker::NONE};
// Estat de l'edició (brush + cursor + picker). Es poblen al pas
// següent; els declarem ara perquè `update()` pugui mutar-los i les
// signatures queden estables entre hitos.
int brush_{-1}; // Índex de tile al tileset; -1 = sense brush.
int cursor_col_{-1}; // Cel·la del mapa sota el cursor (-1 = fora).
// Cursor en cel·les del tilemap. -1/-1 = fora del mapa.
int cursor_col_{-1};
int cursor_row_{-1};
bool picker_open_{false};
int picker_scroll_{0}; // Fila superior visible del picker (linealitzat).
int picker_hover_{-1}; // Índex del tile sota el cursor dins del picker.
// Brush actiu per Mode::TILE (índex al tileset; -1 = sense brush).
int brush_tile_{-1};
// Estat del TilePicker.
int tile_picker_scroll_{0};
int tile_picker_hover_{-1};
// Brush actiu per Mode::ENTITY (nom registrat al factory; "" = cap).
std::string brush_entity_;
// Estat de l'EntityPicker.
int entity_picker_scroll_{0};
int entity_picker_hover_{-1}; // Índex a la llista de noms.
// Selecció en Mode::HAND (índex dins de l'EntityManager; -1 = cap).
int hand_selected_idx_{-1};
};
#endif // _DEBUG