diff --git a/src/app/WardrobePage/OutfitControls.js b/src/app/WardrobePage/OutfitControls.js index 4dea405..b7a5636 100644 --- a/src/app/WardrobePage/OutfitControls.js +++ b/src/app/WardrobePage/OutfitControls.js @@ -29,7 +29,11 @@ import useOutfitAppearance from "../components/useOutfitAppearance"; * OutfitControls is the set of controls layered over the outfit preview, to * control things like species/color and sharing links! */ -function OutfitControls({ outfitState, dispatchToOutfit }) { +function OutfitControls({ + outfitState, + dispatchToOutfit, + showAnimationControls, +}) { const [focusIsLocked, setFocusIsLocked] = React.useState(false); const onLockFocus = React.useCallback(() => setFocusIsLocked(true), [ setFocusIsLocked, @@ -140,11 +144,13 @@ function OutfitControls({ outfitState, dispatchToOutfit }) { d="inline-flex" // Not sure why requires this to style right! ^^` /> - - - - - + {showAnimationControls && ( + + + + + + )} } controls={ } itemsAndSearch={ diff --git a/src/app/components/OutfitCanvas.js b/src/app/components/OutfitCanvas.js index 514e716..1599ad9 100644 --- a/src/app/components/OutfitCanvas.js +++ b/src/app/components/OutfitCanvas.js @@ -8,7 +8,13 @@ const EaselContext = React.createContext({ removeResizeListener: () => {}, }); -function OutfitCanvas({ children, width, height, pauseMovieLayers }) { +function OutfitCanvas({ + children, + width, + height, + pauseMovieLayers = true, + onChangeHasAnimations = null, +}) { const [stage, setStage] = React.useState(null); const resizeListenersRef = React.useRef([]); const canvasRef = React.useRef(null); @@ -43,6 +49,14 @@ function OutfitCanvas({ children, width, height, pauseMovieLayers }) { if (afterFirstDraw) { stage.on("drawend", afterFirstDraw, null, true); } + + if (onChangeHasAnimations) { + const hasAnimations = stage.children.some((c) => + createjsNodeHasAnimations(c) + ); + onChangeHasAnimations(hasAnimations); + } + // NOTE: We don't bother firing an update, because we trust the ticker // to do it on the next frame. }, @@ -52,6 +66,14 @@ function OutfitCanvas({ children, width, height, pauseMovieLayers }) { const removeChild = React.useCallback( (child) => { stage.removeChild(child); + + if (onChangeHasAnimations) { + const hasAnimations = stage.children.some((c) => + createjsNodeHasAnimations(c) + ); + onChangeHasAnimations(hasAnimations); + } + // NOTE: We don't bother firing an update, because we trust the ticker // to do it on the next frame. (And, I don't understand why, but // updating here actually paused remaining movies! So, don't!) diff --git a/src/app/components/OutfitPreview.js b/src/app/components/OutfitPreview.js index a22dd99..e6ddd24 100644 --- a/src/app/components/OutfitPreview.js +++ b/src/app/components/OutfitPreview.js @@ -39,6 +39,7 @@ function OutfitPreview({ loadingDelayMs, spinnerVariant, engine = "images", + onChangeHasAnimations = null, }) { const { loading, error, visibleLayers } = useOutfitAppearance({ speciesId, @@ -72,6 +73,7 @@ function OutfitPreview({ loadingDelayMs={loadingDelayMs} spinnerVariant={spinnerVariant} engine={engine} + onChangeHasAnimations={onChangeHasAnimations} doTransitions /> ); @@ -89,6 +91,7 @@ export function OutfitLayers({ spinnerVariant = "overlay", doTransitions = false, engine = "images", + onChangeHasAnimations = null, }) { const containerRef = React.useRef(null); const [canvasSize, setCanvasSize] = React.useState(0); @@ -158,6 +161,7 @@ export function OutfitLayers({ width={canvasSize} height={canvasSize} pauseMovieLayers={isPaused} + onChangeHasAnimations={onChangeHasAnimations} > {visibleLayers.map((layer) => layer.canvasMovieLibraryUrl ? (