fix(animation): ColorTransition epsilon para convergencia garantizada

Problema: lerpU8 truncaba incrementos <1, causando que las animaciones
nunca terminaran. Con delta_ms=16ms y duration=500ms, el factor t=0.032
hacía que diferencias de 1 (ej: 99→100) nunca convergieran.

Solución: Añadir epsilon check después del lerp. Si la diferencia en
cada canal RGBA es ≤1, forzar snap al target y devolver false.

Esto elimina los redraws infinitos en idle reportados por el usuario.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
R.Eugenio 2026-01-03 12:04:04 +01:00
parent f4b1b75914
commit 908815b585

View file

@ -739,6 +739,19 @@ pub const ColorTransition = struct {
.a = lerpU8(self.current.a, target.a, t), .a = lerpU8(self.current.a, target.a, t),
}; };
// EPSILON FIX: Forzar convergencia cuando estamos "suficientemente cerca"
// Sin esto, lerpU8 trunca incrementos <1 y la animación nunca termina.
// Umbral de 1 es imperceptible al ojo pero garantiza convergencia.
const dr = @abs(@as(i16, self.current.r) - @as(i16, target.r));
const dg = @abs(@as(i16, self.current.g) - @as(i16, target.g));
const db = @abs(@as(i16, self.current.b) - @as(i16, target.b));
const da = @abs(@as(i16, self.current.a) - @as(i16, target.a));
if (dr <= 1 and dg <= 1 and db <= 1 and da <= 1) {
self.current = target; // Snap al target
return false; // Animación terminada
}
return true; return true;
} }