start adding appearance layers support tool
right now it just shows stuff. next step is to make them clickable to open tools for managing the layer!
This commit is contained in:
parent
0cdb6d0da1
commit
63b865ef7c
4 changed files with 87 additions and 18 deletions
|
@ -82,6 +82,7 @@ export function Item({ item, itemNameId, outfitState, dispatchToOutfit }) {
|
|||
<SupportOnly>
|
||||
<LoadableItemSupportDrawer
|
||||
item={item}
|
||||
outfitState={outfitState}
|
||||
isOpen={supportDrawerIsOpen}
|
||||
onClose={() => setSupportDrawerIsOpen(false)}
|
||||
/>
|
||||
|
|
|
@ -14,13 +14,17 @@ import {
|
|||
FormErrorMessage,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
HStack,
|
||||
Link,
|
||||
Select,
|
||||
Spinner,
|
||||
Stack,
|
||||
useBreakpointValue,
|
||||
} from "@chakra-ui/core";
|
||||
import { CheckCircleIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||
|
||||
import { OutfitLayers } from "../../components/OutfitPreview";
|
||||
import useOutfitAppearance from "../../components/useOutfitAppearance";
|
||||
import useSupportSecret from "./useSupportSecret";
|
||||
|
||||
/**
|
||||
|
@ -29,7 +33,7 @@ import useSupportSecret from "./useSupportSecret";
|
|||
* This component controls the drawer element. The actual content is imported
|
||||
* from another lazy-loaded component!
|
||||
*/
|
||||
function ItemSupportDrawer({ item, isOpen, onClose }) {
|
||||
function ItemSupportDrawer({ item, outfitState, isOpen, onClose }) {
|
||||
const placement = useBreakpointValue({
|
||||
base: "bottom",
|
||||
lg: "right",
|
||||
|
@ -53,17 +57,26 @@ function ItemSupportDrawer({ item, isOpen, onClose }) {
|
|||
blockScrollOnMount={false}
|
||||
>
|
||||
<DrawerOverlay>
|
||||
<DrawerContent>
|
||||
<DrawerContent
|
||||
maxHeight={placement === "bottom" ? "90vh" : undefined}
|
||||
overflow="auto"
|
||||
>
|
||||
<DrawerCloseButton />
|
||||
<DrawerHeader>
|
||||
<DrawerHeader color="green.800">
|
||||
{item.name}
|
||||
<Badge colorScheme="pink" marginLeft="3">
|
||||
Support <span aria-hidden="true">💖</span>
|
||||
</Badge>
|
||||
</DrawerHeader>
|
||||
<DrawerBody>
|
||||
<DrawerBody color="green.800">
|
||||
<Box paddingBottom="5">
|
||||
<SpecialColorFields item={item} />
|
||||
<Stack spacing="8">
|
||||
<ItemSupportSpecialColorFields item={item} />
|
||||
<ItemSupportAppearanceFields
|
||||
item={item}
|
||||
outfitState={outfitState}
|
||||
/>
|
||||
</Stack>
|
||||
</Box>
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
|
@ -72,7 +85,7 @@ function ItemSupportDrawer({ item, isOpen, onClose }) {
|
|||
);
|
||||
}
|
||||
|
||||
function SpecialColorFields({ item }) {
|
||||
function ItemSupportSpecialColorFields({ item }) {
|
||||
const supportSecret = useSupportSecret();
|
||||
|
||||
const { loading: itemLoading, error: itemError, data: itemData } = useQuery(
|
||||
|
@ -215,4 +228,54 @@ function SpecialColorFields({ item }) {
|
|||
);
|
||||
}
|
||||
|
||||
function ItemSupportAppearanceFields({ item, outfitState }) {
|
||||
const { speciesId, colorId, pose } = outfitState;
|
||||
const { error, visibleLayers } = useOutfitAppearance({
|
||||
speciesId,
|
||||
colorId,
|
||||
pose,
|
||||
wornItemIds: [item.id],
|
||||
});
|
||||
|
||||
const biologyLayers = visibleLayers.filter((l) => l.source === "pet");
|
||||
const itemLayers = visibleLayers.filter((l) => l.source === "item");
|
||||
itemLayers.sort((a, b) => a.zone.depth - b.zone.depth);
|
||||
|
||||
return (
|
||||
<FormControl>
|
||||
<FormLabel>Appearance layers</FormLabel>
|
||||
<HStack spacing="4" overflow="auto">
|
||||
{itemLayers.map((itemLayer) => (
|
||||
<ItemSupportAppearanceLayer
|
||||
biologyLayers={biologyLayers}
|
||||
itemLayer={itemLayer}
|
||||
/>
|
||||
))}
|
||||
</HStack>
|
||||
{error && <FormErrorMessage>{error.message}</FormErrorMessage>}
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
|
||||
function ItemSupportAppearanceLayer({ biologyLayers, itemLayer }) {
|
||||
return (
|
||||
<Box width="150px" textAlign="center" fontSize="xs">
|
||||
<Box
|
||||
width="150px"
|
||||
height="150px"
|
||||
marginBottom="1"
|
||||
boxShadow="md"
|
||||
borderRadius="md"
|
||||
>
|
||||
<OutfitLayers visibleLayers={[...biologyLayers, itemLayer]} />
|
||||
</Box>
|
||||
<Box>
|
||||
<b>{itemLayer.zone.label}</b>
|
||||
</Box>
|
||||
<Box>Zone ID: {itemLayer.zone.id}</Box>
|
||||
<Box>Layer ID: {itemLayer.id}</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default ItemSupportDrawer;
|
||||
|
|
|
@ -80,7 +80,13 @@ export function OutfitLayers({
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<Box pos="relative" height="100%" width="100%">
|
||||
<Box
|
||||
pos="relative"
|
||||
height="100%"
|
||||
width="100%"
|
||||
// Create a stacking context, so the z-indexed layers don't escape!
|
||||
zIndex="0"
|
||||
>
|
||||
{placeholder && (
|
||||
<FullScreenCenter>
|
||||
<Box
|
||||
|
@ -111,7 +117,7 @@ export function OutfitLayers({
|
|||
`}
|
||||
timeout={200}
|
||||
>
|
||||
<FullScreenCenter>
|
||||
<FullScreenCenter zIndex={layer.zone.depth}>
|
||||
<img
|
||||
src={getBestImageUrlForLayer(layer)}
|
||||
alt=""
|
||||
|
@ -177,7 +183,7 @@ export function OutfitLayers({
|
|||
);
|
||||
}
|
||||
|
||||
export function FullScreenCenter({ children }) {
|
||||
export function FullScreenCenter({ children, zIndex }) {
|
||||
return (
|
||||
<Flex
|
||||
pos="absolute"
|
||||
|
@ -187,6 +193,7 @@ export function FullScreenCenter({ children }) {
|
|||
left="0"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
zIndex={zIndex}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
|
|
|
@ -91,15 +91,12 @@ export function getVisibleLayers(petAppearance, itemAppearances) {
|
|||
|
||||
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
|
||||
// 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 petLayers = petAppearance.layers.map((l) => ({ ...l, source: "pet" }));
|
||||
const itemLayers = validItemAppearances
|
||||
.map((a) => a.layers)
|
||||
.flat()
|
||||
.map((l) => ({ ...l, source: "item" }));
|
||||
let allLayers = [...petLayers, ...itemLayers];
|
||||
|
||||
const allRestrictedZoneIds = validItemAppearances
|
||||
.map((l) => l.restrictedZones)
|
||||
|
@ -123,6 +120,7 @@ export const itemAppearanceFragment = gql`
|
|||
zone {
|
||||
id
|
||||
depth
|
||||
label # HACK: This is for Support tools, but other views don't need it
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue