Persist custom world asset configs in runtime snapshots

This commit is contained in:
2026-04-18 17:00:46 +08:00
parent 7ce61e9879
commit ac801fe05f
29 changed files with 3397 additions and 400 deletions

View File

@@ -45,14 +45,20 @@ export const CharacterAnimator: React.FC<CharacterAnimatorProps> = ({
imageClassName,
playbackRate = 1,
}) => {
const [frameIndex, setFrameIndex] = useState(1);
const config =
character.animationMap?.[state] ??
DEFAULT_ANIMATIONS[state] ??
character.animationMap?.[AnimationState.IDLE] ??
DEFAULT_ANIMATIONS[AnimationState.IDLE];
const startFrame = config.startFrame ?? 1;
const frameCount = config.frames;
const startFrame =
typeof config.startFrame === 'number' && Number.isFinite(config.startFrame)
? Math.max(1, Math.floor(config.startFrame))
: 1;
const [frameIndex, setFrameIndex] = useState(startFrame);
const frameCount =
typeof config.frames === 'number' && Number.isFinite(config.frames)
? Math.max(1, Math.floor(config.frames))
: 1;
const fps =
typeof config.fps === 'number' && Number.isFinite(config.fps)
? Math.max(1, config.fps)
@@ -72,26 +78,33 @@ export const CharacterAnimator: React.FC<CharacterAnimatorProps> = ({
fps,
effectivePlaybackRate,
].join('::');
const endFrame = startFrame + frameCount - 1;
const intervalDelay = Math.max(
40,
Math.round(1000 / (fps * effectivePlaybackRate)),
);
useEffect(() => {
setFrameIndex(startFrame);
setFrameIndex((current) => (current === startFrame ? current : startFrame));
}, [animationSignature, startFrame]);
useEffect(() => {
if (frameCount <= 1) return;
const endFrame = startFrame + frameCount - 1;
const interval = window.setInterval(() => {
setFrameIndex(prev => {
return prev >= endFrame ? startFrame : prev + 1;
setFrameIndex((current) => {
if (current < startFrame || current > endFrame) {
return startFrame;
}
return current >= endFrame ? startFrame : current + 1;
});
}, Math.max(40, Math.round(1000 / (fps * effectivePlaybackRate))));
}, intervalDelay);
return () => window.clearInterval(interval);
}, [
animationSignature,
effectivePlaybackRate,
fps,
endFrame,
frameCount,
intervalDelay,
startFrame,
]);