only show play/pause when there are animations
This commit is contained in:
parent
5027a62ec5
commit
53b4d34419
4 changed files with 45 additions and 7 deletions
|
@ -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 <a> requires this to style right! ^^`
|
||||
/>
|
||||
</Box>
|
||||
{showAnimationControls && (
|
||||
<Box gridArea="play-pause" display="flex" justifyContent="center">
|
||||
<DarkMode>
|
||||
<PlayPauseButton />
|
||||
</DarkMode>
|
||||
</Box>
|
||||
)}
|
||||
<Stack
|
||||
gridArea="sharing"
|
||||
alignSelf="flex-end"
|
||||
|
|
|
@ -29,6 +29,10 @@ function WardrobePage() {
|
|||
const toast = useToast();
|
||||
const { loading, error, outfitState, dispatchToOutfit } = useOutfitState();
|
||||
|
||||
// Whether the current outfit preview has animations. Determines whether we
|
||||
// show the play/pause button.
|
||||
const [hasAnimations, setHasAnimations] = React.useState(false);
|
||||
|
||||
usePageTitle(outfitState.name || "Untitled outfit");
|
||||
|
||||
// TODO: I haven't found a great place for this error UI yet, and this case
|
||||
|
@ -64,12 +68,14 @@ function WardrobePage() {
|
|||
appearanceId={outfitState.appearanceId}
|
||||
wornItemIds={outfitState.wornItemIds}
|
||||
engine="canvas"
|
||||
onChangeHasAnimations={setHasAnimations}
|
||||
/>
|
||||
}
|
||||
controls={
|
||||
<OutfitControls
|
||||
outfitState={outfitState}
|
||||
dispatchToOutfit={dispatchToOutfit}
|
||||
showAnimationControls={hasAnimations}
|
||||
/>
|
||||
}
|
||||
itemsAndSearch={
|
||||
|
|
|
@ -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!)
|
||||
|
|
|
@ -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 ? (
|
||||
|
|
Loading…
Reference in a new issue