Acaba la migració dels std::cout/cerr a Log::*:
- core/locale, core/ui/ui_config, core/rendering/{screen,text,gif,
surface, sprite/animated_sprite, sdl3gpu/*}.
- game/{options, debug_config, editor/editor_config, levels/level_manager,
map/{map,tilemap,paint_layer}, entities/entity_manager_loadlevel}.
Severitats coherents: warns per a configs absents amb fallback,
errors per a YAML malformat o E/S fallida, infos per a estats.
Resultat:
- 0 occurrences de std::cout/std::cerr a source/.
- Cap #include <iostream> orfà (eliminat de surface.cpp).
- Output funcional idèntic al històric; AEE_LOG filtra (ex.
`AEE_LOG=warn` només mostra warnings, `AEE_LOG=*:warn,Tag:info`
combina globals i overrides).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
L'estat mutable d'Options (window, video, audio, locale, presets, paths)
es mou a un anonymous namespace dins options.cpp. L'API pública del
namespace passa a ser:
- Getters const-ref: window(), video(), audio(), locale(),
configVersion(), postfxPresets(), crtpiPresets().
- Setters específics que muten i persisteixen via saveToFile():
setWindowZoom, setWindowFullscreen, setVideoVSync,
setVideoScalingMode, setVideoRenderInfoPosition,
setVideoRenderInfoShowTime, setShaderEnabled, setActiveShaderName,
setPostFXPreset, setCrtPiPreset.
Els setters NO notifiquen els subsistemes: el caller (global_inputs.cpp)
crida explícitament Screen::setWindowZoom, reapplyShader, etc. La part
"observers" del audit es deixa WONTFIX justificat — notificar des
d'Options invertiria la direcció Director→Screen/Audio i Options
aprenria del layout dels subsistemes.
CONV-02 tanca al pas: la part Options dels "globals sense observers"
queda resolta amb la nova encapsulació. Map::* (l'altra meitat de
CONV-02) ja s'havia tancat amb PATCH-07.
Smoke tests 13/13 OK; log Game start → Bye! sota xvfb-run +
SDL_VIDEODRIVER=dummy + SIGINT idèntic al baseline de main.
clang-tidy i cppcheck nets sobre els fitxers modificats.
Refs: docs/audit-game.md (COUP-03, CONV-02, INCONS-01).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- INCONS-05: `buildScreenConfig` passa a return amb designated
initializers, consistent amb `buildAudioConfig`.
- INCONS-01: marcat DONE (parcial) — queden 3 estils intencionals
(namespace per estat compartit, classes per entitats, constexpr per
alias), ja no barreja fortuïta.
- INCONS-03/04, PATCH-03, COUP-04, CONV-04: WONTFIX amb raó
documentada (contractes diferents, linter ho dicta, o sobre-abstracció
per a un únic caller).
- COUP-02/03, CONV-02 (parcial): DEFERRED a `refactor/options-class`
(equivalent a COUP-01 de l'audit d'àudio).
- CONV-01: DONE per HC-01/02/03/04/05/06.
Les 7 funcions parse* i els dos parse*Preset repetien el patró
`if (node.contains("x")) { x = node["x"].get_value<T>(); }`. Centralitzat
en `readField(node, key, dst)` a l'anonymous namespace.
Tres parelles de `*ToString`/`*FromString` substituïdes per tres taules
`constexpr std::array<pair<Enum, string_view>, N>` i dos helpers plantilla
(`enumToString`, `enumFromString`). La primera entrada de cada taula és
el fallback quan l'enum és desconegut o el text no casa: així els valors
"letterbox"/"nearest"/"off" només apareixen una vegada. Resol també HC-07.
Les 10 ocurrències de std::cerr a options.cpp (incloent les de PATCH-04)
passen a std::cout per complir la convenció del projecte ("std::cout
only, no SDL_Log"). Prova manual: amb config.yaml trencat, els missatges
de backup i reescriptura es veuen per stdout.
Helper `backupFile(path)` que copia el YAML a `<path>.bak` si existeix.
Es crida a `loadFromFile` (versió mismatch i catch) i a
`loadPresetsFromFile<T>` (manca `presets:`, llista buida, catch).
La primera execució no genera .bak. Cada reescriptura forçada registra el
motiu per stderr (INCONS-02 migrarà a std::cout).
Prova manual: config.yaml amb contingut \"===broken===\" genera
config.yaml.bak amb el contingut previ i un nou config.yaml amb defaults.
Afegits `loadPresetsFromFile<T>` i `savePresetsToFile<T>` a l'anonymous
namespace; els quatre entry-points passen a ser one-liners que injecten
parse/write/defaults per tipus. Abans eren dues còpies del mateix codi
diferenciades només pel tipus concret de preset. Els YAML regenerats són
byte-a-byte idèntics als anteriors (el formatter i els comentaris es
preserven).
core/rendering/render_info ja no inclou game/options.hpp ni
game/ui/ui_palette.hpp. S'introdueix RenderInfo::Frame amb tot l'estat
extern (posició, show_time, shader_enabled, shader_name, shader_preset,
colors) que el caller injecta a cada init()/update(). La lògica de
persistència (cyclePosition/toggleShowTime) surt de RenderInfo i passa
a global_inputs.cpp, que muta Options i crida saveToFile() directament.
Options::buildRenderInfoFrame(text_color, shadow_color) centralitza la
construcció del Frame seguint el mateix patró que buildScreenConfig /
buildPostFXParams. Director i GameScene criden aquest builder quan
necessiten un Frame (amb UiColor::RENDER_INFO_{TEXT,SHADOW} com a
colors actius).
Amb aquest canvi queda tancada COUP-01: core/rendering/ no té cap
include de game/*.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>