84 lines
2 KiB
JavaScript
84 lines
2 KiB
JavaScript
|
import gql from "graphql-tag";
|
||
|
import { useQuery } from "@apollo/react-hooks";
|
||
|
|
||
|
/**
|
||
|
* useOutfitAppearance downloads the outfit's appearance data, and returns
|
||
|
* visibleLayers for rendering.
|
||
|
*/
|
||
|
export default function useOutfitAppearance(outfitState) {
|
||
|
const { wornItemIds, speciesId, colorId } = outfitState;
|
||
|
|
||
|
const { loading, error, data } = useQuery(
|
||
|
gql`
|
||
|
query($wornItemIds: [ID!]!, $speciesId: ID!, $colorId: ID!) {
|
||
|
petAppearance(speciesId: $speciesId, colorId: $colorId) {
|
||
|
...AppearanceForOutfitPreview
|
||
|
}
|
||
|
|
||
|
items(ids: $wornItemIds) {
|
||
|
id
|
||
|
appearanceOn(speciesId: $speciesId, colorId: $colorId) {
|
||
|
...AppearanceForOutfitPreview
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
${itemAppearanceFragment}
|
||
|
`,
|
||
|
{
|
||
|
variables: { wornItemIds, speciesId, colorId },
|
||
|
}
|
||
|
);
|
||
|
|
||
|
const visibleLayers = getVisibleLayers(data);
|
||
|
|
||
|
return { loading, error, visibleLayers };
|
||
|
}
|
||
|
|
||
|
function getVisibleLayers(data) {
|
||
|
if (!data) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
const allAppearances = [
|
||
|
data.petAppearance,
|
||
|
...(data.items || []).map((i) => i.appearanceOn),
|
||
|
].filter((a) => a);
|
||
|
let allLayers = allAppearances.map((a) => a.layers).flat();
|
||
|
|
||
|
// Clean up our data a bit, by ensuring only one layer per zone. This
|
||
|
// shouldn't happen in theory, but sometimes our database doesn't clean up
|
||
|
// after itself correctly :(
|
||
|
allLayers = allLayers.filter((l, i) => {
|
||
|
return allLayers.findIndex((l2) => l2.zone.id === l.zone.id) === i;
|
||
|
});
|
||
|
|
||
|
const allRestrictedZoneIds = allAppearances
|
||
|
.map((l) => l.restrictedZones)
|
||
|
.flat()
|
||
|
.map((z) => z.id);
|
||
|
|
||
|
const visibleLayers = allLayers.filter(
|
||
|
(l) => !allRestrictedZoneIds.includes(l.zone.id)
|
||
|
);
|
||
|
visibleLayers.sort((a, b) => a.zone.depth - b.zone.depth);
|
||
|
|
||
|
return visibleLayers;
|
||
|
}
|
||
|
|
||
|
export const itemAppearanceFragment = gql`
|
||
|
fragment AppearanceForOutfitPreview on Appearance {
|
||
|
layers {
|
||
|
id
|
||
|
imageUrl(size: SIZE_600)
|
||
|
zone {
|
||
|
id
|
||
|
depth
|
||
|
}
|
||
|
}
|
||
|
|
||
|
restrictedZones {
|
||
|
id
|
||
|
}
|
||
|
}
|
||
|
`;
|