WIP pose picker support
This commit is contained in:
parent
5334801aba
commit
10a6eff299
5 changed files with 195 additions and 85 deletions
|
@ -15,12 +15,14 @@ import {
|
|||
useColorModeValue,
|
||||
useTheme,
|
||||
} from "@chakra-ui/core";
|
||||
import loadable from "@loadable/component";
|
||||
|
||||
import {
|
||||
getVisibleLayers,
|
||||
petAppearanceFragment,
|
||||
} from "../components/useOutfitAppearance";
|
||||
import { OutfitLayers } from "../components/OutfitPreview";
|
||||
import SupportOnly from "./support/SupportOnly";
|
||||
|
||||
// From https://twemoji.twitter.com/, thank you!
|
||||
import twemojiSmile from "../../images/twemoji/smile.svg";
|
||||
|
@ -29,6 +31,12 @@ import twemojiSick from "../../images/twemoji/sick.svg";
|
|||
import twemojiMasc from "../../images/twemoji/masc.svg";
|
||||
import twemojiFem from "../../images/twemoji/fem.svg";
|
||||
|
||||
const PosePickerSupport = loadable(() => import("./support/PosePickerSupport"));
|
||||
|
||||
const PosePickerSupportSwitch = loadable(() =>
|
||||
import("./support/PosePickerSupport").then((m) => m.PosePickerSupportSwitch)
|
||||
);
|
||||
|
||||
/**
|
||||
* PosePicker shows the pet poses available on the current species/color, and
|
||||
* lets the user choose which want they want!
|
||||
|
@ -53,6 +61,7 @@ function PosePicker({
|
|||
const theme = useTheme();
|
||||
const checkedInputRef = React.useRef();
|
||||
const { loading, error, poseInfos } = usePoses(speciesId, colorId, pose);
|
||||
const [isInSupportMode, setIsInSupportMode] = React.useState(false);
|
||||
|
||||
if (loading) {
|
||||
return null;
|
||||
|
@ -127,89 +136,28 @@ function PosePicker({
|
|||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<Box p="4">
|
||||
<table width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiSmile} alt="Happy" />
|
||||
</Cell>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiCry} alt="Sad" />
|
||||
</Cell>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiSick} alt="Sick" />
|
||||
</Cell>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiMasc} alt="Masculine" />
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.happyMasc}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.happyMasc.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sadMasc}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.sadMasc.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sickMasc}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.sickMasc.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
</tr>
|
||||
<tr>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiFem} alt="Feminine" />
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.happyFem}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.happyFem.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sadFem}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.sadFem.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sickFem}
|
||||
onChange={onChange}
|
||||
inputRef={
|
||||
poseInfos.sickFem.isSelected && checkedInputRef
|
||||
}
|
||||
/>
|
||||
</Cell>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Box p="4" position="relative">
|
||||
{isInSupportMode ? (
|
||||
<PosePickerSupport
|
||||
speciesId={speciesId}
|
||||
colorId={colorId}
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : (
|
||||
<PosePickerTable
|
||||
poseInfos={poseInfos}
|
||||
onChange={onChange}
|
||||
checkedInputRef={checkedInputRef}
|
||||
/>
|
||||
)}
|
||||
<SupportOnly>
|
||||
<Box position="absolute" top="5" left="3">
|
||||
<PosePickerSupportSwitch
|
||||
isChecked={isInSupportMode}
|
||||
onChange={(e) => setIsInSupportMode(e.target.checked)}
|
||||
/>
|
||||
</Box>
|
||||
</SupportOnly>
|
||||
</Box>
|
||||
<PopoverArrow />
|
||||
</PopoverContent>
|
||||
|
@ -220,6 +168,81 @@ function PosePicker({
|
|||
);
|
||||
}
|
||||
|
||||
function PosePickerTable({ poseInfos, onChange, checkedInputRef }) {
|
||||
return (
|
||||
<table width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiSmile} alt="Happy" />
|
||||
</Cell>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiCry} alt="Sad" />
|
||||
</Cell>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiSick} alt="Sick" />
|
||||
</Cell>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiMasc} alt="Masculine" />
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.happyMasc}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.happyMasc.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sadMasc}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.sadMasc.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sickMasc}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.sickMasc.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
</tr>
|
||||
<tr>
|
||||
<Cell as="th">
|
||||
<EmojiImage src={twemojiFem} alt="Feminine" />
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.happyFem}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.happyFem.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sadFem}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.sadFem.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
<Cell as="td">
|
||||
<PoseOption
|
||||
poseInfo={poseInfos.sickFem}
|
||||
onChange={onChange}
|
||||
inputRef={poseInfos.sickFem.isSelected && checkedInputRef}
|
||||
/>
|
||||
</Cell>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
function Cell({ children, as }) {
|
||||
const Tag = as;
|
||||
return (
|
||||
|
|
87
src/app/WardrobePage/support/PosePickerSupport.js
Normal file
87
src/app/WardrobePage/support/PosePickerSupport.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
import React from "react";
|
||||
import gql from "graphql-tag";
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { Box, Select, Switch } from "@chakra-ui/core";
|
||||
|
||||
import { petAppearanceFragment } from "../../components/useOutfitAppearance";
|
||||
import HangerSpinner from "../../components/HangerSpinner";
|
||||
|
||||
function PosePickerSupport({ speciesId, colorId }) {
|
||||
const { loading, error, data } = useQuery(
|
||||
gql`
|
||||
query PosePickerSupport($speciesId: ID!, $colorId: ID!) {
|
||||
petAppearances(speciesId: $speciesId, colorId: $colorId) {
|
||||
id
|
||||
petStateId
|
||||
bodyId
|
||||
pose
|
||||
...PetAppearanceForOutfitPreview
|
||||
}
|
||||
}
|
||||
${petAppearanceFragment}
|
||||
`,
|
||||
{ variables: { speciesId, colorId } }
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Box display="flex" justifyContent="center">
|
||||
<HangerSpinner boxSize="32px" />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Box color="red.400" marginTop="8">
|
||||
{error.message}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box display="flex" justifyContent="flex-end">
|
||||
<Select size="sm" width="auto">
|
||||
{data.petAppearances.map((pa) => (
|
||||
<option key={pa.petStateId}>
|
||||
{POSE_NAMES[pa.pose]} ({pa.petStateId})
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export function PosePickerSupportSwitch({ isChecked, onChange }) {
|
||||
return (
|
||||
<Box as="label" display="flex" flexDirection="row" alignItems="center">
|
||||
<Box fontSize="sm">
|
||||
<span role="img" aria-label="Support">
|
||||
💖
|
||||
</span>
|
||||
</Box>
|
||||
<Switch
|
||||
colorScheme="pink"
|
||||
marginLeft="1"
|
||||
size="sm"
|
||||
isChecked={isChecked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const POSE_NAMES = {
|
||||
HAPPY_MASC: "Happy Masc",
|
||||
SAD_MASC: "Sad Masc",
|
||||
SICK_MASC: "Sick Masc",
|
||||
HAPPY_FEM: "Happy Fem",
|
||||
SAD_FEM: "Sad Fem",
|
||||
SICK_FEM: "Sick Fem",
|
||||
UNCONVERTED: "Unconverted",
|
||||
UNKNOWN: "Unknown",
|
||||
};
|
||||
|
||||
export default PosePickerSupport;
|
|
@ -81,6 +81,7 @@ function HangerSpinner(props) {
|
|||
animation: 1.6s infinite fade-pulse;
|
||||
}
|
||||
`}
|
||||
{...props}
|
||||
>
|
||||
<HangerIcon color="green.300" {...props} />
|
||||
</Box>
|
||||
|
|
|
@ -587,7 +587,6 @@ const resolvers = {
|
|||
colorId,
|
||||
});
|
||||
const petStates = await petStatesForPetTypeLoader.load(petType.id);
|
||||
petStates.sort((a, b) => a.id - b.id);
|
||||
return petStates.map((petState) => ({ id: petState.id }));
|
||||
},
|
||||
outfit: (_, { id }) => ({ id }),
|
||||
|
|
|
@ -355,7 +355,7 @@ const buildPetStatesForPetTypeLoader = (db, loaders) =>
|
|||
const [rows, _] = await db.execute(
|
||||
`SELECT * FROM pet_states
|
||||
WHERE pet_type_id IN (${qs}) AND glitched = 0
|
||||
ORDER BY (mood_id = 1) DESC`,
|
||||
ORDER BY (mood_id = 1) DESC, id`,
|
||||
petTypeIds
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue