feat(lighting): offset del centre de la llum per emissor

This commit is contained in:
JailDesigner committed 2026-05-13 18:26:19 +02:00
1 parent dacc4a9909
commit 3a42c7958a
9 files changed
+114 -25

No files matched your search

@@ -157,12 +157,14 @@ namespace {
return c["height"].get_value<int>();
}
// Bloc opcional `light: { radius: N, flicker: bool, color: [r,g,b] }`
// Bloc opcional `light: { radius: N, flicker: bool, color: [r,g,b], offset: [x,y] }`
// de la plantilla. Si manca, el radi és 0 i l'entitat no entra a la
// pasada d'il·luminació. `flicker` activa la modulació "tipus foc"
// del radi (només antorxes l'haurien d'usar). `color` només té
// efecte en mode additive — defecte blanc (255,255,255). La forma
// del gradient (3 anells) i els paràmetres del flicker viuen a
// efecte en mode additive — defecte blanc (255,255,255). `offset`
// desplaça el centre del cercle de llum respecte el centre del
// sprite (default (0, 0); Y creix cap avall). La forma del gradient
// (3 anells) i els paràmetres del flicker viuen a
// data/config/lighting.yaml — no cal declarar-los per entitat.
struct LightTemplate {
int radius{0};
@@ -170,6 +172,8 @@ namespace {
std::uint8_t color_r{255};
std::uint8_t color_g{255};
std::uint8_t color_b{255};
int offset_x{0};
int offset_y{0};
};
// Helper compartit entre les tres capes (tipus, sala via Map, spawn)
@@ -182,6 +186,16 @@ namespace {
return true;
}
// Helper paral·lel a `readColorTriplet` per a `offset: [x, y]` —
// píxels enters, sense clamp (offsets negatius són legítims; Y
// creix cap avall).
auto readOffsetPair(const fkyaml::node& seq, int& x, int& y) -> bool {
if (!seq.is_sequence() || seq.size() != 2) { return false; }
x = seq[0].get_value<int>();
y = seq[1].get_value<int>();
return true;
}
auto readLight(const fkyaml::node& tmpl) -> LightTemplate {
if (!tmpl.contains("light")) { return {}; }
const auto& l = tmpl["light"];
@@ -189,6 +203,7 @@ namespace {
if (l.contains("radius")) { out.radius = l["radius"].get_value<int>(); }
if (l.contains("flicker")) { out.flicker = l["flicker"].get_value<bool>(); }
if (l.contains("color")) { readColorTriplet(l["color"], out.color_r, out.color_g, out.color_b); }
if (l.contains("offset")) { readOffsetPair(l["offset"], out.offset_x, out.offset_y); }
return out;
}
@@ -203,7 +218,7 @@ namespace {
auto resolveLightWithRoom(const std::string& type, LightTemplate type_default) -> LightTemplate {
const auto* room = Map::getRoomEmitterOverride(type);
if (room == nullptr) { return type_default; }
if (!room->enabled) { return {.radius = 0, .flicker = false, .color_r = 255, .color_g = 255, .color_b = 255}; }
if (!room->enabled) { return LightTemplate{}; }
LightTemplate out = type_default;
if (room->radius.has_value()) { out.radius = *room->radius; }
if (room->flicker.has_value()) { out.flicker = *room->flicker; }
@@ -212,17 +227,21 @@ namespace {
out.color_g = (*room->color)[1];
out.color_b = (*room->color)[2];
}
if (room->offset.has_value()) {
out.offset_x = (*room->offset)[0];
out.offset_y = (*room->offset)[1];
}
return out;
}
// Aplica l'override per-spawn (si existeix) per damunt del que ja
// viu a l'entitat (defaults del tipus + override de sala). Tres formes
// a l'entry del YAML de nivell:
// `light: false` → apaga aquesta instància
// `light: true` → informatiu (cau a capes inferiors)
// `light: { radius, flicker, color: [r,g,b] }` → camps presents sobreescriuen;
// els absents respecten el que
// ja duia l'entitat
// `light: false` → apaga aquesta instància
// `light: true` → informatiu (cau a capes inferiors)
// `light: { radius, flicker, color: [r,g,b], offset: [x,y] }` → camps presents sobreescriuen;
// els absents respecten el que
// ja duia l'entitat
void applySpawnLightOverride(Entity& entity, const fkyaml::node& spawn) {
if (!spawn.contains("light")) { return; }
const auto& l = spawn["light"];
@@ -242,6 +261,11 @@ namespace {
std::uint8_t b{};
if (readColorTriplet(l["color"], r, g, b)) { entity.setLightColor(r, g, b); }
}
if (l.contains("offset")) {
int x{};
int y{};
if (readOffsetPair(l["offset"], x, y)) { entity.setLightOffset(x, y); }
}
}
// Bloc `collision: { size: [w, h], base_size: [bw, bh]?, offset: [x, y]? }`
@@ -374,6 +398,7 @@ namespace {
entity->setLightRadius(LIGHT.radius);
entity->setLightFlicker(LIGHT.flicker);
entity->setLightColor(LIGHT.color_r, LIGHT.color_g, LIGHT.color_b);
entity->setLightOffset(LIGHT.offset_x, LIGHT.offset_y);
anchor_out = readAnchor(tmpl);
return entity;
}