fix(animation): ColorTransition epsilon check ANTES del lerp
El check anterior estaba DESPUÉS del lerpU8, causando loop infinito: - lerpU8 trunca incrementos <1, current no cambia - dr = |current - target| sigue siendo > 1 (ej: 10) - return true → pide más frames - Repeat forever Nuevo algoritmo: 1. Calcular diferencia PRIMERO 2. Si diferencia <= 2 en todos los canales → snap directo 3. Solo hacer lerp si diferencia > 2 Umbral aumentado de 1 a 2 para mayor margen de seguridad. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
908815b585
commit
d92ce07bb3
1 changed files with 16 additions and 20 deletions
|
|
@ -719,13 +719,22 @@ pub const ColorTransition = struct {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Already at target?
|
||||
if (self.current.r == target.r and
|
||||
self.current.g == target.g and
|
||||
self.current.b == target.b and
|
||||
self.current.a == target.a)
|
||||
{
|
||||
return false;
|
||||
// EPSILON CHECK PRIMERO: Si estamos "suficientemente cerca", snap directo
|
||||
// Esto evita el problema de lerpU8 truncando incrementos <1
|
||||
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));
|
||||
|
||||
// Umbral pequeño (<=2) para garantizar convergencia sin saltos visibles
|
||||
if (dr <= 2 and dg <= 2 and db <= 2 and da <= 2) {
|
||||
if (self.current.r != target.r or self.current.g != target.g or
|
||||
self.current.b != target.b or self.current.a != target.a)
|
||||
{
|
||||
self.current = target; // Snap final
|
||||
return true; // Un último frame para el snap
|
||||
}
|
||||
return false; // Ya en target, animación terminada
|
||||
}
|
||||
|
||||
// Calculate interpolation factor (chase towards target)
|
||||
|
|
@ -739,19 +748,6 @@ pub const ColorTransition = struct {
|
|||
.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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue