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.
|
* visibleLayers for rendering.
|
||||||
*/
|
*/
|
||||||
export default function useOutfitAppearance(outfitState) {
|
export default function useOutfitAppearance(outfitState) {
|
||||||
const { wornItemIds, speciesId, colorId } = outfitState;
|
const {
|
||||||
|
wornItemIds,
|
||||||
|
speciesId,
|
||||||
|
colorId,
|
||||||
|
emotion,
|
||||||
|
genderPresentation,
|
||||||
|
} = outfitState;
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(
|
const { loading, error, data } = useQuery(
|
||||||
gql`
|
gql`
|
||||||
query($wornItemIds: [ID!]!, $speciesId: ID!, $colorId: ID!) {
|
query(
|
||||||
petAppearance(speciesId: $speciesId, colorId: $colorId) {
|
$wornItemIds: [ID!]!
|
||||||
|
$speciesId: ID!
|
||||||
|
$colorId: ID!
|
||||||
|
$emotion: Emotion!
|
||||||
|
$genderPresentation: GenderPresentation!
|
||||||
|
) {
|
||||||
|
petAppearance(
|
||||||
|
speciesId: $speciesId
|
||||||
|
colorId: $colorId
|
||||||
|
emotion: $emotion
|
||||||
|
genderPresentation: $genderPresentation
|
||||||
|
) {
|
||||||
...PetAppearanceForOutfitPreview
|
...PetAppearanceForOutfitPreview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +43,13 @@ export default function useOutfitAppearance(outfitState) {
|
||||||
${petAppearanceFragment}
|
${petAppearanceFragment}
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
variables: { wornItemIds, speciesId, colorId },
|
variables: {
|
||||||
|
wornItemIds,
|
||||||
|
speciesId,
|
||||||
|
colorId,
|
||||||
|
emotion,
|
||||||
|
genderPresentation,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -41,7 +64,9 @@ export function getVisibleLayers(petAppearance, itemAppearances) {
|
||||||
return [];
|
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();
|
let allLayers = allAppearances.map((a) => a.layers).flat();
|
||||||
|
|
||||||
// Clean up our data a bit, by ensuring only one layer per zone. This
|
// 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;
|
return allLayers.findIndex((l2) => l2.zone.id === l.zone.id) === i;
|
||||||
});
|
});
|
||||||
|
|
||||||
const allRestrictedZoneIds = itemAppearances
|
const allRestrictedZoneIds = validItemAppearances
|
||||||
.map((l) => l.restrictedZones)
|
.map((l) => l.restrictedZones)
|
||||||
.flat()
|
.flat()
|
||||||
.map((z) => z.id);
|
.map((z) => z.id);
|
||||||
|
|
|
@ -183,21 +183,34 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
||||||
closetedItemIds.delete(itemId);
|
closetedItemIds.delete(itemId);
|
||||||
});
|
});
|
||||||
case "setPose":
|
case "setPose":
|
||||||
|
return produce(baseState, (state) => {
|
||||||
const { emotion, genderPresentation } = action;
|
const { emotion, genderPresentation } = action;
|
||||||
return { ...baseState, emotion, genderPresentation };
|
state.emotion = emotion;
|
||||||
|
state.genderPresentation = genderPresentation;
|
||||||
|
});
|
||||||
case "reset":
|
case "reset":
|
||||||
const { name, speciesId, colorId, wornItemIds, closetedItemIds } = action;
|
return produce(baseState, (state) => {
|
||||||
return {
|
const {
|
||||||
name,
|
name,
|
||||||
speciesId: speciesId ? String(speciesId) : baseState.speciesId,
|
speciesId,
|
||||||
colorId: colorId ? String(colorId) : baseState.colorId,
|
colorId,
|
||||||
wornItemIds: wornItemIds
|
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))
|
? new Set(wornItemIds.map(String))
|
||||||
: baseState.wornItemIds,
|
: baseState.wornItemIds;
|
||||||
closetedItemIds: closetedItemIds
|
state.closetedItemIds = closetedItemIds
|
||||||
? new Set(closetedItemIds.map(String))
|
? new Set(closetedItemIds.map(String))
|
||||||
: baseState.closetedItemIds,
|
: baseState.closetedItemIds;
|
||||||
};
|
});
|
||||||
default:
|
default:
|
||||||
throw new Error(`unexpected action ${JSON.stringify(action)}`);
|
throw new Error(`unexpected action ${JSON.stringify(action)}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ const { gql } = require("apollo-server");
|
||||||
const connectToDb = require("./db");
|
const connectToDb = require("./db");
|
||||||
const buildLoaders = require("./loaders");
|
const buildLoaders = require("./loaders");
|
||||||
const neopets = require("./neopets");
|
const neopets = require("./neopets");
|
||||||
const { capitalize } = require("./util");
|
const { capitalize, getEmotion, getGenderPresentation } = require("./util");
|
||||||
|
|
||||||
const typeDefs = gql`
|
const typeDefs = gql`
|
||||||
enum LayerImageSize {
|
enum LayerImageSize {
|
||||||
|
@ -111,7 +111,12 @@ const typeDefs = gql`
|
||||||
offset: Int
|
offset: Int
|
||||||
limit: Int
|
limit: Int
|
||||||
): ItemSearchResult!
|
): ItemSearchResult!
|
||||||
petAppearance(speciesId: ID!, colorId: ID!): PetAppearance
|
petAppearance(
|
||||||
|
speciesId: ID!
|
||||||
|
colorId: ID!
|
||||||
|
emotion: Emotion!
|
||||||
|
genderPresentation: GenderPresentation!
|
||||||
|
): PetAppearance
|
||||||
petAppearances(speciesId: ID!, colorId: ID!): [PetAppearance!]!
|
petAppearances(speciesId: ID!, colorId: ID!): [PetAppearance!]!
|
||||||
|
|
||||||
petOnNeopetsDotCom(petName: String!): Outfit
|
petOnNeopetsDotCom(petName: String!): Outfit
|
||||||
|
@ -162,34 +167,9 @@ const resolvers = {
|
||||||
},
|
},
|
||||||
PetAppearance: {
|
PetAppearance: {
|
||||||
id: ({ petState }) => petState.id,
|
id: ({ petState }) => petState.id,
|
||||||
genderPresentation: ({ petState }) => {
|
genderPresentation: ({ petState }) =>
|
||||||
if (petState.female === 1) {
|
getGenderPresentation(petState.female),
|
||||||
return "FEMININE";
|
emotion: ({ petState }) => getEmotion(petState.moodId),
|
||||||
} 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)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
approximateThumbnailUrl: ({ petType, petState }) => {
|
approximateThumbnailUrl: ({ petType, petState }) => {
|
||||||
return `http://pets.neopets.com/cp/${petType.basicImageHash}/${petState.moodId}/1.png`;
|
return `http://pets.neopets.com/cp/${petType.basicImageHash}/${petState.moodId}/1.png`;
|
||||||
},
|
},
|
||||||
|
@ -285,15 +265,26 @@ const resolvers = {
|
||||||
},
|
},
|
||||||
petAppearance: async (
|
petAppearance: async (
|
||||||
_,
|
_,
|
||||||
{ speciesId, colorId },
|
{ speciesId, colorId, emotion, genderPresentation },
|
||||||
{ petTypeLoader, petStateLoader }
|
{ petTypeLoader, petStateLoader }
|
||||||
) => {
|
) => {
|
||||||
const petType = await petTypeLoader.load({
|
const petType = await petTypeLoader.load({
|
||||||
speciesId,
|
speciesId,
|
||||||
colorId,
|
colorId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const petStates = await petStateLoader.load(petType.id);
|
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 (
|
petAppearances: async (
|
||||||
_,
|
_,
|
||||||
|
|
|
@ -6,7 +6,12 @@ describe("PetAppearance", () => {
|
||||||
const res = await query({
|
const res = await query({
|
||||||
query: gql`
|
query: gql`
|
||||||
query {
|
query {
|
||||||
petAppearance(speciesId: "54", colorId: "75") {
|
petAppearance(
|
||||||
|
speciesId: "54"
|
||||||
|
colorId: "75"
|
||||||
|
emotion: HAPPY
|
||||||
|
genderPresentation: FEMININE
|
||||||
|
) {
|
||||||
layers {
|
layers {
|
||||||
id
|
id
|
||||||
imageUrl(size: SIZE_600)
|
imageUrl(size: SIZE_600)
|
||||||
|
|
|
@ -2,4 +2,28 @@ function capitalize(str) {
|
||||||
return str[0].toUpperCase() + str.slice(1);
|
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