show updated pet appearance in outfit preview!
This commit is contained in:
parent
a064e5b471
commit
6e1e0a5c0b
5 changed files with 110 additions and 52 deletions
|
@ -6,12 +6,29 @@ import { useQuery } from "@apollo/react-hooks";
|
|||
* visibleLayers for rendering.
|
||||
*/
|
||||
export default function useOutfitAppearance(outfitState) {
|
||||
const { wornItemIds, speciesId, colorId } = outfitState;
|
||||
const {
|
||||
wornItemIds,
|
||||
speciesId,
|
||||
colorId,
|
||||
emotion,
|
||||
genderPresentation,
|
||||
} = outfitState;
|
||||
|
||||
const { loading, error, data } = useQuery(
|
||||
gql`
|
||||
query($wornItemIds: [ID!]!, $speciesId: ID!, $colorId: ID!) {
|
||||
petAppearance(speciesId: $speciesId, colorId: $colorId) {
|
||||
query(
|
||||
$wornItemIds: [ID!]!
|
||||
$speciesId: ID!
|
||||
$colorId: ID!
|
||||
$emotion: Emotion!
|
||||
$genderPresentation: GenderPresentation!
|
||||
) {
|
||||
petAppearance(
|
||||
speciesId: $speciesId
|
||||
colorId: $colorId
|
||||
emotion: $emotion
|
||||
genderPresentation: $genderPresentation
|
||||
) {
|
||||
...PetAppearanceForOutfitPreview
|
||||
}
|
||||
|
||||
|
@ -26,7 +43,13 @@ export default function useOutfitAppearance(outfitState) {
|
|||
${petAppearanceFragment}
|
||||
`,
|
||||
{
|
||||
variables: { wornItemIds, speciesId, colorId },
|
||||
variables: {
|
||||
wornItemIds,
|
||||
speciesId,
|
||||
colorId,
|
||||
emotion,
|
||||
genderPresentation,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -41,7 +64,9 @@ export function getVisibleLayers(petAppearance, itemAppearances) {
|
|||
return [];
|
||||
}
|
||||
|
||||
const allAppearances = [petAppearance, ...itemAppearances].filter((a) => a);
|
||||
const validItemAppearances = itemAppearances.filter((a) => a);
|
||||
|
||||
const allAppearances = [petAppearance, ...validItemAppearances];
|
||||
let allLayers = allAppearances.map((a) => a.layers).flat();
|
||||
|
||||
// Clean up our data a bit, by ensuring only one layer per zone. This
|
||||
|
@ -51,7 +76,7 @@ export function getVisibleLayers(petAppearance, itemAppearances) {
|
|||
return allLayers.findIndex((l2) => l2.zone.id === l.zone.id) === i;
|
||||
});
|
||||
|
||||
const allRestrictedZoneIds = itemAppearances
|
||||
const allRestrictedZoneIds = validItemAppearances
|
||||
.map((l) => l.restrictedZones)
|
||||
.flat()
|
||||
.map((z) => z.id);
|
||||
|
|
|
@ -183,21 +183,34 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
|||
closetedItemIds.delete(itemId);
|
||||
});
|
||||
case "setPose":
|
||||
const { emotion, genderPresentation } = action;
|
||||
return { ...baseState, emotion, genderPresentation };
|
||||
return produce(baseState, (state) => {
|
||||
const { emotion, genderPresentation } = action;
|
||||
state.emotion = emotion;
|
||||
state.genderPresentation = genderPresentation;
|
||||
});
|
||||
case "reset":
|
||||
const { name, speciesId, colorId, wornItemIds, closetedItemIds } = action;
|
||||
return {
|
||||
name,
|
||||
speciesId: speciesId ? String(speciesId) : baseState.speciesId,
|
||||
colorId: colorId ? String(colorId) : baseState.colorId,
|
||||
wornItemIds: wornItemIds
|
||||
return produce(baseState, (state) => {
|
||||
const {
|
||||
name,
|
||||
speciesId,
|
||||
colorId,
|
||||
emotion,
|
||||
genderPresentation,
|
||||
wornItemIds,
|
||||
closetedItemIds,
|
||||
} = action;
|
||||
state.name = name;
|
||||
state.speciesId = speciesId ? String(speciesId) : baseState.speciesId;
|
||||
state.colorId = colorId ? String(colorId) : baseState.colorId;
|
||||
state.emotion = emotion;
|
||||
state.genderPresentation = genderPresentation;
|
||||
state.wornItemIds = wornItemIds
|
||||
? new Set(wornItemIds.map(String))
|
||||
: baseState.wornItemIds,
|
||||
closetedItemIds: closetedItemIds
|
||||
: baseState.wornItemIds;
|
||||
state.closetedItemIds = closetedItemIds
|
||||
? new Set(closetedItemIds.map(String))
|
||||
: baseState.closetedItemIds,
|
||||
};
|
||||
: baseState.closetedItemIds;
|
||||
});
|
||||
default:
|
||||
throw new Error(`unexpected action ${JSON.stringify(action)}`);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ const { gql } = require("apollo-server");
|
|||
const connectToDb = require("./db");
|
||||
const buildLoaders = require("./loaders");
|
||||
const neopets = require("./neopets");
|
||||
const { capitalize } = require("./util");
|
||||
const { capitalize, getEmotion, getGenderPresentation } = require("./util");
|
||||
|
||||
const typeDefs = gql`
|
||||
enum LayerImageSize {
|
||||
|
@ -111,7 +111,12 @@ const typeDefs = gql`
|
|||
offset: Int
|
||||
limit: Int
|
||||
): ItemSearchResult!
|
||||
petAppearance(speciesId: ID!, colorId: ID!): PetAppearance
|
||||
petAppearance(
|
||||
speciesId: ID!
|
||||
colorId: ID!
|
||||
emotion: Emotion!
|
||||
genderPresentation: GenderPresentation!
|
||||
): PetAppearance
|
||||
petAppearances(speciesId: ID!, colorId: ID!): [PetAppearance!]!
|
||||
|
||||
petOnNeopetsDotCom(petName: String!): Outfit
|
||||
|
@ -162,34 +167,9 @@ const resolvers = {
|
|||
},
|
||||
PetAppearance: {
|
||||
id: ({ petState }) => petState.id,
|
||||
genderPresentation: ({ petState }) => {
|
||||
if (petState.female === 1) {
|
||||
return "FEMININE";
|
||||
} else if (petState.female === 0) {
|
||||
return "MASCULINE";
|
||||
} else if (petState.female === null) {
|
||||
return null;
|
||||
} else {
|
||||
throw new Error(
|
||||
`unrecognized gender value ${JSON.stringify(petState.female)}`
|
||||
);
|
||||
}
|
||||
},
|
||||
emotion: ({ petState }) => {
|
||||
if (petState.moodId === "1") {
|
||||
return "HAPPY";
|
||||
} else if (petState.moodId === "2") {
|
||||
return "SAD";
|
||||
} else if (petState.moodId === "4") {
|
||||
return "SICK";
|
||||
} else if (petState.moodId === null) {
|
||||
return null;
|
||||
} else {
|
||||
throw new Error(
|
||||
`unrecognized moodId ${JSON.stringify(petState.moodId)}`
|
||||
);
|
||||
}
|
||||
},
|
||||
genderPresentation: ({ petState }) =>
|
||||
getGenderPresentation(petState.female),
|
||||
emotion: ({ petState }) => getEmotion(petState.moodId),
|
||||
approximateThumbnailUrl: ({ petType, petState }) => {
|
||||
return `http://pets.neopets.com/cp/${petType.basicImageHash}/${petState.moodId}/1.png`;
|
||||
},
|
||||
|
@ -285,15 +265,26 @@ const resolvers = {
|
|||
},
|
||||
petAppearance: async (
|
||||
_,
|
||||
{ speciesId, colorId },
|
||||
{ speciesId, colorId, emotion, genderPresentation },
|
||||
{ petTypeLoader, petStateLoader }
|
||||
) => {
|
||||
const petType = await petTypeLoader.load({
|
||||
speciesId,
|
||||
colorId,
|
||||
});
|
||||
|
||||
const petStates = await petStateLoader.load(petType.id);
|
||||
return { petType, petState: petStates[0] };
|
||||
// TODO: This could be optimized into the query condition 🤔
|
||||
const petState = petStates.find(
|
||||
(ps) =>
|
||||
getEmotion(ps.moodId) === emotion &&
|
||||
getGenderPresentation(ps.female) === genderPresentation
|
||||
);
|
||||
if (!petState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { petType, petState };
|
||||
},
|
||||
petAppearances: async (
|
||||
_,
|
||||
|
|
|
@ -6,7 +6,12 @@ describe("PetAppearance", () => {
|
|||
const res = await query({
|
||||
query: gql`
|
||||
query {
|
||||
petAppearance(speciesId: "54", colorId: "75") {
|
||||
petAppearance(
|
||||
speciesId: "54"
|
||||
colorId: "75"
|
||||
emotion: HAPPY
|
||||
genderPresentation: FEMININE
|
||||
) {
|
||||
layers {
|
||||
id
|
||||
imageUrl(size: SIZE_600)
|
||||
|
|
|
@ -2,4 +2,28 @@ function capitalize(str) {
|
|||
return str[0].toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
module.exports = { capitalize };
|
||||
function getEmotion(moodId) {
|
||||
if (moodId === "1") {
|
||||
return "HAPPY";
|
||||
} else if (moodId === "2") {
|
||||
return "SAD";
|
||||
} else if (moodId === "4") {
|
||||
return "SICK";
|
||||
} else if (moodId === null) {
|
||||
return null;
|
||||
} else {
|
||||
throw new Error(`unrecognized moodId ${JSON.stringify(moodId)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getGenderPresentation(modelPetWasFemale) {
|
||||
if (modelPetWasFemale === 1) {
|
||||
return "FEMININE";
|
||||
} else if (modelPetWasFemale === 0) {
|
||||
return "MASCULINE";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { capitalize, getEmotion, getGenderPresentation };
|
||||
|
|
Loading…
Reference in a new issue