feat(lighting): mode additive amb color per emissor

This commit is contained in:
JailDesigner committed 2026-05-13 14:11:51 +02:00
1 parent 24609d6c5c
commit 771ff1f6cd
10 files changed
+352 -71

No files matched your search

+32 -3
View File
@@ -1,5 +1,6 @@
#include "game/map/map.hpp"
#include <algorithm>
#include <cmath>
#include <stdexcept>
#include <unordered_map>
@@ -49,18 +50,45 @@ namespace Map {
return yaml_key;
}
// Parser comú d'un color YAML 3-tupla a bytes. Retorna nullopt
// si el node no és una seqüència de 3 elements. Usat pels
// overrides de sala i, en `entity_manager_loadlevel.cpp`, també
// pels defaults de tipus i overrides de spawn (passa pel mateix
// helper per coherència). `clamp` defensiu per a YAMLs que
// entreguen valors fora de 0..255.
auto parseColorTriplet(const fkyaml::node& node) -> std::optional<std::array<std::uint8_t, 3>> {
if (!node.is_sequence() || node.size() != 3) { return std::nullopt; }
auto clamp = [](int v) { return static_cast<std::uint8_t>(std::clamp(v, 0, 255)); };
return std::array<std::uint8_t, 3>{
clamp(node[0].get_value<int>()),
clamp(node[1].get_value<int>()),
clamp(node[2].get_value<int>()),
};
}
// Llegeix el bloc opcional `lighting:` del YAML d'una sala i
// actualitza `light_level` (si declara `level`) i el mapping
// `g_room_emitters`. Idempotent: cada `Map::loadFrom` neteja el
// mapping abans de poblar-lo, així no s'arrosseguen overrides
// actualitza `light_level`, `lighting_mode` i el mapping
// `g_room_emitters`. Idempotent: cada `Map::loadFrom` reseteja
// tot l'estat abans de poblar-lo, així no s'arrosseguen valors
// d'una sala anterior.
void loadLightingBlock(const fkyaml::node& yaml) {
g_room_emitters.clear();
lighting_mode = Lighting::Mode::Subtractive;
if (!yaml.contains("lighting")) { return; }
const auto& lighting = yaml["lighting"];
if (lighting.contains("level")) {
light_level = lighting["level"].get_value<float>();
}
if (lighting.contains("mode")) {
const auto MODE_STR = lighting["mode"].get_value<std::string>();
if (MODE_STR == "additive") {
lighting_mode = Lighting::Mode::Additive;
} else if (MODE_STR == "subtractive") {
lighting_mode = Lighting::Mode::Subtractive;
} else {
Log::warn("Map", "lighting.mode '{}' desconegut — s'usa subtractive", MODE_STR);
}
}
if (!lighting.contains("emitters") || !lighting["emitters"].is_mapping()) { return; }
const auto& em = lighting["emitters"];
for (auto it = em.begin(); it != em.end(); ++it) {
@@ -73,6 +101,7 @@ namespace Map {
ov.enabled = true;
if (val.contains("radius")) { ov.radius = val["radius"].get_value<int>(); }
if (val.contains("flicker")) { ov.flicker = val["flicker"].get_value<bool>(); }
if (val.contains("color")) { ov.color = parseColorTriplet(val["color"]); }
}
g_room_emitters[KEY] = ov;
}