move emotion / gender presentation to outfit state

This commit is contained in:
Matt Dunn-Rankin 2020-05-02 22:20:17 -07:00
parent fae2a579c2
commit a064e5b471
3 changed files with 57 additions and 37 deletions

View file

@ -83,6 +83,7 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
<Flex flex="1 1 0" align="center" pl="4">
<PosePicker
outfitState={outfitState}
dispatchToOutfit={dispatchToOutfit}
onLockFocus={() => setFocusIsLocked(true)}
onUnlockFocus={() => setFocusIsLocked(false)}
/>

View file

@ -25,16 +25,15 @@ import twemojiMasc from "../images/twemoji/masc.svg";
import twemojiFem from "../images/twemoji/fem.svg";
import { OutfitLayers } from "./OutfitPreview";
function PosePicker({ outfitState, onLockFocus, onUnlockFocus }) {
function PosePicker({
outfitState,
dispatchToOutfit,
onLockFocus,
onUnlockFocus,
}) {
const theme = useTheme();
const { speciesId, colorId } = outfitState;
const { loading, error, poses, selectPose } = usePoses({
speciesId,
colorId,
});
const checkedInputRef = React.useRef();
const { loading, error, poses } = usePoses(outfitState);
if (loading) {
return null;
@ -52,6 +51,15 @@ function PosePicker({ outfitState, onLockFocus, onUnlockFocus }) {
return null;
}
const onChange = (e) => {
const [emotion, genderPresentation] = e.target.value.split("-");
dispatchToOutfit({
type: "setPose",
emotion,
genderPresentation,
});
};
return (
<Popover
placement="bottom-end"
@ -95,16 +103,7 @@ function PosePicker({ outfitState, onLockFocus, onUnlockFocus }) {
</PopoverTrigger>
<PopoverContent>
<Box p="4">
<table
width="100%"
borderSpacing="8px"
onChange={(e) => {
const [emotion, genderPresentation] = e.target.value.split(
"-"
);
selectPose({ emotion, genderPresentation });
}}
>
<table width="100%">
<thead>
<tr>
<th />
@ -127,21 +126,21 @@ function PosePicker({ outfitState, onLockFocus, onUnlockFocus }) {
<Cell as="td">
<PoseButton
pose={poses.happyMasc}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.happyMasc.isSelected && checkedInputRef}
/>
</Cell>
<Cell as="td">
<PoseButton
pose={poses.sadMasc}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.sadMasc.isSelected && checkedInputRef}
/>
</Cell>
<Cell as="td">
<PoseButton
pose={poses.sickMasc}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.sickMasc.isSelected && checkedInputRef}
/>
</Cell>
@ -153,21 +152,21 @@ function PosePicker({ outfitState, onLockFocus, onUnlockFocus }) {
<Cell as="td">
<PoseButton
pose={poses.happyFem}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.happyFem.isSelected && checkedInputRef}
/>
</Cell>
<Cell as="td">
<PoseButton
pose={poses.sadFem}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.sadFem.isSelected && checkedInputRef}
/>
</Cell>
<Cell as="td">
<PoseButton
pose={poses.sickFem}
speciesId={speciesId}
onChange={onChange}
inputRef={poses.sickFem.isSelected && checkedInputRef}
/>
</Cell>
@ -205,7 +204,7 @@ const GENDER_PRESENTATION_STRINGS = {
FEMININE: "Feminine",
};
function PoseButton({ pose, speciesId, inputRef }) {
function PoseButton({ pose, onChange, inputRef }) {
const theme = useTheme();
if (!pose) {
@ -233,6 +232,7 @@ function PoseButton({ pose, speciesId, inputRef }) {
name="pose"
value={`${pose.emotion}-${pose.genderPresentation}`}
checked={pose.isSelected}
onChange={onChange}
ref={inputRef || null}
/>
<Box
@ -279,7 +279,8 @@ function PoseButton({ pose, speciesId, inputRef }) {
width="50px"
height="50px"
transform={
transformsBySpeciesId[speciesId] || transformsBySpeciesId.default
transformsBySpeciesId[pose.speciesId] ||
transformsBySpeciesId.default
}
>
<OutfitLayers visibleLayers={getVisibleLayers(pose, [])} />
@ -293,11 +294,8 @@ function EmojiImage({ src, "aria-label": ariaLabel }) {
return <Image src={src} aria-label={ariaLabel} width="16px" height="16px" />;
}
function usePoses({ speciesId, colorId }) {
const [selectedPose, selectPose] = React.useState({
emotion: "HAPPY",
genderPresentation: "FEMININE",
});
function usePoses(outfitState) {
const { speciesId, colorId, emotion, genderPresentation } = outfitState;
const { loading, error, data } = useQuery(
gql`
@ -320,9 +318,11 @@ function usePoses({ speciesId, colorId }) {
...petAppearances.find(
(pa) => pa.emotion === e && pa.genderPresentation === gp
),
speciesId,
isSelected:
selectedPose.emotion === e && selectedPose.genderPresentation === gp,
outfitState.emotion === e && outfitState.genderPresentation === gp,
});
console.log(outfitState.emotion, outfitState.genderPresentation, outfitState);
const poses = {
happyMasc: buildPose("HAPPY", "MASCULINE"),
@ -333,7 +333,7 @@ function usePoses({ speciesId, colorId }) {
sickFem: buildPose("SICK", "FEMININE"),
};
return { loading, error, poses, selectPose };
return { loading, error, poses };
}
const transformsBySpeciesId = {

View file

@ -30,12 +30,14 @@ function useOutfitState() {
"74546",
"57997",
]),
speciesId: "24", // Starry
colorId: "62", // Zafara
speciesId: "24",
colorId: "62",
emotion: "HAPPY",
genderPresentation: "FEMININE",
}
);
const { name, speciesId, colorId } = state;
const { name, speciesId, colorId, emotion, genderPresentation } = state;
// It's more convenient to manage these as a Set in state, but most callers
// will find it more convenient to access them as arrays! e.g. for `.map()`
@ -94,6 +96,8 @@ function useOutfitState() {
allItemIds,
speciesId,
colorId,
emotion,
genderPresentation,
url,
};
@ -106,6 +110,8 @@ function useOutfitState() {
name: urlParams.get("name"),
speciesId: urlParams.get("species"),
colorId: urlParams.get("color"),
emotion: urlParams.get("emotion"),
genderPresentation: urlParams.get("genderPresentation"),
wornItemIds: urlParams.getAll("objects[]"),
closetedItemIds: urlParams.getAll("closet[]"),
});
@ -176,6 +182,9 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
wornItemIds.delete(itemId);
closetedItemIds.delete(itemId);
});
case "setPose":
const { emotion, genderPresentation } = action;
return { ...baseState, emotion, genderPresentation };
case "reset":
const { name, speciesId, colorId, wornItemIds, closetedItemIds } = action;
return {
@ -315,12 +324,22 @@ function getZonesAndItems(itemsById, wornItemIds, closetedItemIds) {
}
function buildOutfitUrl(state) {
const { name, speciesId, colorId, wornItemIds, closetedItemIds } = state;
const {
name,
speciesId,
colorId,
emotion,
genderPresentation,
wornItemIds,
closetedItemIds,
} = state;
const params = new URLSearchParams();
params.append("name", name);
params.append("species", speciesId);
params.append("color", colorId);
params.append("emotion", emotion);
params.append("genderPresentation", genderPresentation);
for (const itemId of wornItemIds) {
params.append("objects[]", itemId);
}