Fix dizzy-eye SMIL restart during nausea recovery drain
Replace blobbi reference equality with stable visual-identity primitive comparisons in MemoizedBlobbiVisual memo and SVG renderer useMemo deps. This prevents SVG DOM rebuilds (which restart SMIL animateTransform) when the upstream companion object gets a new reference during the imperative gradient-drain loop.
This commit is contained in:
@@ -123,7 +123,16 @@ const MemoizedBlobbiVisual = memo(function MemoizedBlobbiVisual({
|
||||
}, (prev, next) => {
|
||||
return (
|
||||
prev.stage === next.stage &&
|
||||
prev.blobbi === next.blobbi &&
|
||||
// Compare blobbi by visual-identity primitives, NOT by reference.
|
||||
// This prevents SVG rebuilds (and SMIL animation restarts) when the
|
||||
// upstream companion object gets a new reference with identical content
|
||||
// — e.g. during nausea recovery where only angerRise.level changes.
|
||||
prev.blobbi.id === next.blobbi.id &&
|
||||
prev.blobbi.baseColor === next.blobbi.baseColor &&
|
||||
prev.blobbi.secondaryColor === next.blobbi.secondaryColor &&
|
||||
prev.blobbi.eyeColor === next.blobbi.eyeColor &&
|
||||
prev.blobbi.adult?.evolutionForm === next.blobbi.adult?.evolutionForm &&
|
||||
prev.blobbi.seed === next.blobbi.seed &&
|
||||
prev.recipeFingerprint === next.recipeFingerprint &&
|
||||
prev.recipeLabel === next.recipeLabel &&
|
||||
prev.emotion === next.emotion &&
|
||||
|
||||
@@ -94,11 +94,12 @@ export function BlobbiAdultSvgRenderer({
|
||||
}
|
||||
|
||||
return animatedSvg;
|
||||
// recipeFingerprint replaces recipeProp in the dep list so that
|
||||
// level-only changes do NOT trigger a full SVG rebuild. The closure
|
||||
// captures the current recipeProp for the rare structural rebuilds.
|
||||
// Deps use stable primitives from blobbi (not the object reference) and
|
||||
// recipeFingerprint (not recipeProp) so that level-only changes and
|
||||
// upstream reference churn do NOT trigger full SVG rebuilds. The closure
|
||||
// captures the current blobbi/recipeProp for the rare structural rebuilds.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [blobbi, recipeFingerprint, recipeLabel, emotion, bodyEffects]);
|
||||
}, [blobbi.id, blobbi.baseColor, blobbi.secondaryColor, blobbi.eyeColor, blobbi.adult?.evolutionForm, blobbi.seed, recipeFingerprint, recipeLabel, emotion, bodyEffects]);
|
||||
|
||||
const safeSvg = useMemo(() => sanitizeBlobbiSvg(customizedSvg), [customizedSvg]);
|
||||
|
||||
|
||||
@@ -90,8 +90,12 @@ export function BlobbiBabySvgRenderer({
|
||||
}
|
||||
|
||||
return animatedSvg;
|
||||
// Deps use stable primitives from blobbi (not the object reference) and
|
||||
// recipeFingerprint (not recipeProp) so that level-only changes and
|
||||
// upstream reference churn do NOT trigger full SVG rebuilds. The closure
|
||||
// captures the current blobbi/recipeProp for the rare structural rebuilds.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [blobbi, recipeFingerprint, recipeLabel, emotion, bodyEffects]);
|
||||
}, [blobbi.id, blobbi.baseColor, blobbi.secondaryColor, blobbi.eyeColor, blobbi.seed, recipeFingerprint, recipeLabel, emotion, bodyEffects]);
|
||||
|
||||
const safeSvg = useMemo(() => sanitizeBlobbiSvg(customizedSvg), [customizedSvg]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user