better handling of missing poses
This commit is contained in:
parent
2300fe4fbe
commit
5ea717c391
2 changed files with 87 additions and 48 deletions
|
@ -25,14 +25,20 @@ function OutfitPreview({ outfitState }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <OutfitLayers loading={loading} visibleLayers={visibleLayers} />;
|
return (
|
||||||
|
<OutfitLayers
|
||||||
|
loading={loading}
|
||||||
|
visibleLayers={visibleLayers}
|
||||||
|
doAnimations
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OutfitLayers is the raw UI component for rendering outfit layers. It's
|
* OutfitLayers is the raw UI component for rendering outfit layers. It's
|
||||||
* used both in the main outfit preview, and in other minor UIs!
|
* used both in the main outfit preview, and in other minor UIs!
|
||||||
*/
|
*/
|
||||||
export function OutfitLayers({ loading, visibleLayers }) {
|
export function OutfitLayers({ loading, visibleLayers, doAnimations = false }) {
|
||||||
return (
|
return (
|
||||||
<Box pos="relative" height="100%" width="100%">
|
<Box pos="relative" height="100%" width="100%">
|
||||||
<TransitionGroup>
|
<TransitionGroup>
|
||||||
|
@ -41,6 +47,7 @@ export function OutfitLayers({ loading, visibleLayers }) {
|
||||||
// happens here, when the layer exits the DOM.
|
// happens here, when the layer exits the DOM.
|
||||||
<CSSTransition
|
<CSSTransition
|
||||||
key={layer.id}
|
key={layer.id}
|
||||||
|
exit={doAnimations}
|
||||||
classNames={css`
|
classNames={css`
|
||||||
&-exit {
|
&-exit {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
@ -62,14 +69,17 @@ export function OutfitLayers({ loading, visibleLayers }) {
|
||||||
// We manage the fade-in and fade-out separately! The fade-in
|
// We manage the fade-in and fade-out separately! The fade-in
|
||||||
// happens here, when the <Image> finishes preloading and
|
// happens here, when the <Image> finishes preloading and
|
||||||
// applies the src to the underlying <img>.
|
// applies the src to the underlying <img>.
|
||||||
className={css`
|
className={
|
||||||
|
doAnimations &&
|
||||||
|
css`
|
||||||
opacity: 0.01;
|
opacity: 0.01;
|
||||||
|
|
||||||
&[src] {
|
&[src] {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s;
|
||||||
}
|
}
|
||||||
`}
|
`
|
||||||
|
}
|
||||||
// This sets up the cache to not need to reload images during
|
// This sets up the cache to not need to reload images during
|
||||||
// download!
|
// download!
|
||||||
// TODO: Re-enable this once we get our change into Chakra
|
// TODO: Re-enable this once we get our change into Chakra
|
||||||
|
|
|
@ -46,7 +46,8 @@ function PosePicker({
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's only one pose anyway, don't bother showing a picker!
|
// If there's only one pose anyway, don't bother showing a picker!
|
||||||
const numAvailablePoses = Object.values(poses).filter((p) => p).length;
|
const numAvailablePoses = Object.values(poses).filter((p) => p.isAvailable)
|
||||||
|
.length;
|
||||||
if (numAvailablePoses <= 1) {
|
if (numAvailablePoses <= 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -206,15 +207,15 @@ const GENDER_PRESENTATION_STRINGS = {
|
||||||
|
|
||||||
function PoseButton({ pose, onChange, inputRef }) {
|
function PoseButton({ pose, onChange, inputRef }) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
if (!pose) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const genderPresentationStr =
|
const genderPresentationStr =
|
||||||
GENDER_PRESENTATION_STRINGS[pose.genderPresentation];
|
GENDER_PRESENTATION_STRINGS[pose.genderPresentation];
|
||||||
const emotionStr = EMOTION_STRINGS[pose.emotion];
|
const emotionStr = EMOTION_STRINGS[pose.emotion];
|
||||||
|
|
||||||
|
let label = `${emotionStr} and ${genderPresentationStr}`;
|
||||||
|
if (!pose.isAvailable) {
|
||||||
|
label += ` (not modeled yet)`;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
as="label"
|
as="label"
|
||||||
|
@ -228,24 +229,28 @@ function PoseButton({ pose, onChange, inputRef }) {
|
||||||
<VisuallyHidden
|
<VisuallyHidden
|
||||||
as="input"
|
as="input"
|
||||||
type="radio"
|
type="radio"
|
||||||
aria-label={`${emotionStr} and ${genderPresentationStr}`}
|
aria-label={label}
|
||||||
name="pose"
|
name="pose"
|
||||||
value={`${pose.emotion}-${pose.genderPresentation}`}
|
value={`${pose.emotion}-${pose.genderPresentation}`}
|
||||||
checked={pose.isSelected}
|
checked={pose.isSelected}
|
||||||
|
disabled={!pose.isAvailable}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
ref={inputRef || null}
|
ref={inputRef || null}
|
||||||
/>
|
/>
|
||||||
<Box
|
<Box
|
||||||
|
aria-hidden
|
||||||
rounded="full"
|
rounded="full"
|
||||||
boxShadow="md"
|
boxShadow="md"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
width="50px"
|
width="50px"
|
||||||
height="50px"
|
height="50px"
|
||||||
title={
|
title={
|
||||||
// A lil debug output, so that we can quickly identify glitched
|
pose.isAvailable
|
||||||
|
? // A lil debug output, so that we can quickly identify glitched
|
||||||
// PetStates and manually mark them as glitched!
|
// PetStates and manually mark them as glitched!
|
||||||
window.location.hostname.includes("localhost") &&
|
window.location.hostname.includes("localhost") &&
|
||||||
`#${pose.petStateId}`
|
`#${pose.petStateId}`
|
||||||
|
: "Not modeled yet"
|
||||||
}
|
}
|
||||||
position="relative"
|
position="relative"
|
||||||
className={css`
|
className={css`
|
||||||
|
@ -267,10 +272,16 @@ function PoseButton({ pose, onChange, inputRef }) {
|
||||||
left="0"
|
left="0"
|
||||||
right="0"
|
right="0"
|
||||||
zIndex="2"
|
zIndex="2"
|
||||||
className={css`
|
className={cx(
|
||||||
|
css`
|
||||||
border: 0px solid ${theme.colors.green["600"]};
|
border: 0px solid ${theme.colors.green["600"]};
|
||||||
transition: border-width 0.2s;
|
transition: border-width 0.2s;
|
||||||
|
|
||||||
|
&.not-available {
|
||||||
|
border-color: ${theme.colors.gray["500"]};
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
input:checked + * & {
|
input:checked + * & {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
@ -278,8 +289,11 @@ function PoseButton({ pose, onChange, inputRef }) {
|
||||||
input:focus + * & {
|
input:focus + * & {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
}
|
}
|
||||||
`}
|
`,
|
||||||
|
!pose.isAvailable && "not-available"
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
{pose.isAvailable ? (
|
||||||
<Box
|
<Box
|
||||||
width="50px"
|
width="50px"
|
||||||
height="50px"
|
height="50px"
|
||||||
|
@ -290,6 +304,18 @@ function PoseButton({ pose, onChange, inputRef }) {
|
||||||
>
|
>
|
||||||
<OutfitLayers visibleLayers={getVisibleLayers(pose, [])} />
|
<OutfitLayers visibleLayers={getVisibleLayers(pose, [])} />
|
||||||
</Box>
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Flex align="center" justify="center">
|
||||||
|
<Box
|
||||||
|
fontFamily="Delicious"
|
||||||
|
fontSize="3xl"
|
||||||
|
fontWeight="900"
|
||||||
|
color="gray.600"
|
||||||
|
>
|
||||||
|
?
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -320,15 +346,18 @@ function usePoses(outfitState) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const petAppearances = data?.petAppearances || [];
|
const petAppearances = data?.petAppearances || [];
|
||||||
const buildPose = (e, gp) => ({
|
const buildPose = (e, gp) => {
|
||||||
...petAppearances.find(
|
const appearance = petAppearances.find(
|
||||||
(pa) => pa.emotion === e && pa.genderPresentation === gp
|
(pa) => pa.emotion === e && pa.genderPresentation === gp
|
||||||
),
|
);
|
||||||
|
return {
|
||||||
|
...appearance,
|
||||||
speciesId,
|
speciesId,
|
||||||
|
isAvailable: Boolean(appearance),
|
||||||
isSelected:
|
isSelected:
|
||||||
outfitState.emotion === e && outfitState.genderPresentation === gp,
|
outfitState.emotion === e && outfitState.genderPresentation === gp,
|
||||||
});
|
};
|
||||||
console.log(outfitState.emotion, outfitState.genderPresentation, outfitState);
|
};
|
||||||
|
|
||||||
const poses = {
|
const poses = {
|
||||||
happyMasc: buildPose("HAPPY", "MASCULINE"),
|
happyMasc: buildPose("HAPPY", "MASCULINE"),
|
||||||
|
|
Loading…
Reference in a new issue