Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Character movement and posing modes #837

Merged
merged 10 commits into from
Sep 17, 2024
1 change: 1 addition & 0 deletions pandora-client-web/src/assets/icons/letter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pandora-client-web/src/assets/icons/lips.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pandora-client-web/src/assets/icons/profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pandora-client-web/src/assets/icons/shirt.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions pandora-client-web/src/components/contextMenu/contextMenu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ $context-menu-themes: (
isolation: isolate;
max-height: 100vh;

hr {
width: 90%;
margin: 0;
align-self: center;
}

span, button {
@include center-flex;
margin: 0;
Expand All @@ -42,6 +48,27 @@ $context-menu-themes: (
&:hover {
background-color: #fff4;
}

&.withIcon {
padding: 0.5em;
gap: 0.5em;

>img {
width: 1.8em;
height: 1.8em;
object-fit: contain;

&.invert {
filter: invert(100%);
}
}

>span {
flex: 1;
padding: 0;
justify-content: start;
}
}
}

@each $theme-name, $theme-data in $context-menu-themes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import { Column, Row } from '../../common/container/container';
import { FieldsetToggle } from '../../common/fieldsetToggle';
import { FormCreateStringValidator } from '../../common/form/form';
import { WardrobeModuleConfig } from '../modules/_wardrobeModules';
import { useWardrobeExecuteCallback } from '../wardrobeActionContext';
import { useStaggeredAppearanceActionResult } from '../wardrobeCheckQueue';
import { ActionWarningContent, WardrobeActionButton } from '../wardrobeComponents';
import { useWardrobeContext, useWardrobeExecuteCallback } from '../wardrobeContext';
import { useWardrobeContext } from '../wardrobeContext';
import { useWardrobeTargetItem } from '../wardrobeUtils';
import { WardrobeItemColorization } from './wardrobeItemColor';
import { WardrobeItemName } from './wardrobeItemName';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Immutable } from 'immer';
import _ from 'lodash';
import {
AppearanceAction,
AppearanceItems,
Expand All @@ -9,14 +11,13 @@ import {
Writeable,
} from 'pandora-common';
import React, { ReactElement, useMemo } from 'react';
import { FieldsetToggle } from '../../common/fieldsetToggle';
import _ from 'lodash';
import { ColorInputRGBA } from '../../common/colorInput/colorInput';
import { Immutable } from 'immer';
import { useItemColorString } from '../../../graphics/graphicsLayer';
import { useWardrobeContext, useWardrobeExecuteCallback } from '../wardrobeContext';
import { useWardrobeTargetItems } from '../wardrobeUtils';
import { ColorInputRGBA } from '../../common/colorInput/colorInput';
import { FieldsetToggle } from '../../common/fieldsetToggle';
import { useWardrobeExecuteCallback } from '../wardrobeActionContext';
import { useStaggeredAppearanceActionResult } from '../wardrobeCheckQueue';
import { useWardrobeContext } from '../wardrobeContext';
import { useWardrobeTargetItems } from '../wardrobeUtils';

export function WardrobeItemColorization({ wornItem, item }: {
wornItem: Item<'personal' | 'roomDevice'>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ import { Column, Row } from '../../common/container/container';
import { FieldsetToggle } from '../../common/fieldsetToggle';
import { useSpaceCharacters } from '../../gameContext/gameStateContextProvider';
import { WardrobeModuleConfig } from '../modules/_wardrobeModules';
import { useWardrobeActionContext, useWardrobeExecuteCallback } from '../wardrobeActionContext';
import { useStaggeredAppearanceActionResult } from '../wardrobeCheckQueue';
import { WardrobeActionButton } from '../wardrobeComponents';
import { WardrobeContextSelectRoomInventoryProvider, useWardrobeContext, useWardrobeExecuteCallback } from '../wardrobeContext';
import { WardrobeContextSelectRoomInventoryProvider, useWardrobeContext } from '../wardrobeContext';

export function WardrobeRoomDeviceDeployment({ roomDevice, item }: {
roomDevice: Item<'roomDevice'>;
Expand Down Expand Up @@ -179,7 +180,8 @@ function WardrobeRoomDeviceSlot({ slotName, slotDefinition, occupancy, item }: {
occupancy: CharacterId | null;
item: ItemPath;
}): ReactElement | null {
const { targetSelector, player } = useWardrobeContext();
const { player } = useWardrobeActionContext();
const { targetSelector } = useWardrobeContext();

const characters: readonly ICharacter[] = useSpaceCharacters();

Expand Down Expand Up @@ -250,7 +252,7 @@ export function WardrobeRoomDeviceWearable({ roomDeviceWearable }: {
item: ItemPath;
}): ReactElement | null {
const roomDeviceLink = roomDeviceWearable.roomDeviceLink;
const { globalState } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const roomDevice = useMemo(() => (roomDeviceLink != null
? globalState.getItems({ type: 'roomInventory' })?.find((it) => it.id === roomDeviceLink.device)
: undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { ItemModuleStorage } from 'pandora-common/dist/assets/modules/storage';
import React, { ReactElement, useCallback, useMemo, useState } from 'react';
import { Row } from '../../common/container/container';
import { useCheckAddPermissions } from '../../gameContext/permissionCheckProvider';
import { useWardrobeActionContext, useWardrobePermissionRequestCallback } from '../wardrobeActionContext';
import { ActionWarning, CheckResultToClassName } from '../wardrobeComponents';
import { useWardrobeContext, useWardrobePermissionRequestCallback } from '../wardrobeContext';
import { useWardrobeContext } from '../wardrobeContext';
import { WardrobeModuleProps, WardrobeModuleTemplateProps } from '../wardrobeTypes';

export function WardrobeModuleConfigStorage({ item, moduleName, m }: WardrobeModuleProps<ItemModuleStorage>): ReactElement {
const { target, targetSelector, focuser, actions, globalState } = useWardrobeContext();
const { actions, globalState } = useWardrobeActionContext();
const { target, targetSelector, focuser } = useWardrobeContext();
const [requestPermission] = useWardrobePermissionRequestCallback();
const [ref, setRef] = useState<HTMLElement | null>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import { TextInput } from '../../../common/userInteraction/input/textInput';
import { useInputAutofocus } from '../../../common/userInteraction/inputAutofocus';
import { IconButton } from '../../common/button/button';
import { Scrollbar } from '../../common/scrollbar/scrollbar';
import { useWardrobeActionContext, useWardrobeExecuteChecked } from '../wardrobeActionContext';
import { useStaggeredAppearanceActionResult } from '../wardrobeCheckQueue';
import { ActionWarning, AttributeButton, InventoryAssetPreview, WardrobeActionButton } from '../wardrobeComponents';
import { useWardrobeContext, useWardrobeExecuteChecked } from '../wardrobeContext';
import { useWardrobeContext } from '../wardrobeContext';
import { WardrobeContextExtraItemActionComponent } from '../wardrobeTypes';

export function InventoryAssetView({ className, title, children, assets, container, attributesFilterOptions, spawnStyle }: {
Expand Down Expand Up @@ -367,7 +368,7 @@ export function useAssetPreferences(): Immutable<AssetPreferencesPublic> {
}

export function useAssetPreferenceResolver(): (asset: Asset) => AssetPreferenceType {
const { player } = useWardrobeContext();
const { player } = useWardrobeActionContext();
const preferences = useAssetPreferences();

return React.useCallback((asset) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import _ from 'lodash';
import {
AssetFrameworkCharacterState,
BoneName,
} from 'pandora-common';
import React, { ReactElement, useCallback, useMemo } from 'react';
import { ICharacter } from '../../../character/character';
import _ from 'lodash';
import { useWardrobeExecuteCallback } from '../wardrobeContext';
import { useWardrobeExecuteCallback } from '../wardrobeActionContext';
import { BoneRowElement } from './wardrobePoseView';

export function WardrobeBodySizeEditor({ character, characterState }: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { Button } from '../../common/button/button';
import { Scrollbar } from '../../common/scrollbar/scrollbar';
import { useCheckAddPermissions } from '../../gameContext/permissionCheckProvider';
import { ResolveItemDisplayName, WardrobeItemName } from '../itemDetail/wardrobeItemName';
import { useWardrobeActionContext } from '../wardrobeActionContext';
import { InventoryAssetPreview, StorageUsageMeter, WardrobeActionButton } from '../wardrobeComponents';
import { useWardrobeContext } from '../wardrobeContext';
import { WardrobeHeldItem } from '../wardrobeTypes';
Expand All @@ -43,7 +44,8 @@ export function InventoryItemView({
title: string;
filter?: (item: Item) => boolean;
}): ReactElement | null {
const { target, targetSelector, heldItem, focuser, itemDisplayNameType, actions, globalState } = useWardrobeContext();
const { actions, globalState } = useWardrobeActionContext();
const { target, targetSelector, heldItem, focuser, itemDisplayNameType } = useWardrobeContext();
const focus = useObservable(focuser.current);
const appearance = useWardrobeTargetItems(target);
const itemCount = useMemo(() => AppearanceItemsCalculateTotalCount(appearance), [appearance]);
Expand Down Expand Up @@ -190,7 +192,8 @@ export function InventoryItemViewDropArea({ target, container, insertBefore }: {
container: ItemContainerPath;
insertBefore?: ItemId;
}): ReactElement | null {
const { heldItem, setHeldItem, globalState } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { heldItem, setHeldItem } = useWardrobeContext();

// Check if we are not trying to do NOOP
const identicalContainer = heldItem.type === 'item' &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useConfirmDialog } from '../../dialog/dialog';
import { ExportDialog } from '../../exportImport/exportDialog';
import { ResolveItemDisplayNameType } from '../itemDetail/wardrobeItemName';
import { WardrobeTemplateEditMenu } from '../templateDetail/_wardrobeTemplateDetail';
import { useWardrobeActionContext } from '../wardrobeActionContext';
import { InventoryAssetPreview } from '../wardrobeComponents';
import { useWardrobeContext } from '../wardrobeContext';
import { WardrobeContextExtraItemActionComponent } from '../wardrobeTypes';
Expand All @@ -29,7 +30,8 @@ export function OutfitEditView({ extraActions, outfit, updateOutfit, isTemporary
isTemporary?: boolean;
}): ReactElement | null {
const confirm = useConfirmDialog();
const { heldItem, extraItemActions, globalState, targetSelector } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { heldItem, extraItemActions, targetSelector } = useWardrobeContext();
const [editName, setEditName] = useState(outfit.name);

const [editedItemIndex, setEditedItemIndex] = useState<number | null>(null);
Expand Down Expand Up @@ -276,7 +278,8 @@ export function OutfitEditView({ extraActions, outfit, updateOutfit, isTemporary
function OutfitEditItemDropArea({ insertTemplate }: {
insertTemplate: (newTemplate: ItemTemplate) => void;
}): ReactElement | null {
const { heldItem, setHeldItem, globalState } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { heldItem, setHeldItem } = useWardrobeContext();

const action = useMemo((): (() => void) | null => {
if (heldItem.type === 'nothing')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ import { useConfirmDialog } from '../../dialog/dialog';
import { ImportDialog } from '../../exportImport/importDialog';
import { useDirectoryChangeListener, useDirectoryConnector } from '../../gameContext/directoryConnectorContextProvider';
import { usePlayerState } from '../../gameContext/playerContextProvider';
import { ResolveItemDisplayNameType } from '../itemDetail/wardrobeItemName';
import { useWardrobeActionContext } from '../wardrobeActionContext';
import { InventoryAssetPreview, StorageUsageMeter, WardrobeActionButton } from '../wardrobeComponents';
import { useWardrobeContext } from '../wardrobeContext';
import { OutfitEditView } from './wardrobeOutfitEditView';
import { ResolveItemDisplayNameType } from '../itemDetail/wardrobeItemName';

export function InventoryOutfitView({ targetContainer }: {
targetContainer: ItemContainerPath;
Expand Down Expand Up @@ -312,7 +313,8 @@ function OutfitPreview({ outfit }: {
outfit: AssetFrameworkOutfit;
}): ReactElement {
const assetManager = useAssetManager();
const { target, globalState, showHoverPreview, actionPreviewState } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { target, showHoverPreview, actionPreviewState } = useWardrobeContext();
const { player, playerState } = usePlayerState();

const [isHovering, setIsHovering] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import { SelectionIndicator } from '../../common/selectionIndicator/selectionInd
import { useShardConnector } from '../../gameContext/shardConnectorContextProvider';
import { ResolveItemDisplayName } from '../itemDetail/wardrobeItemName';
import { WardrobeStoredPosePresets } from '../poseDetail/storedPosePresets';
import { useWardrobeContext, useWardrobeExecuteCallback } from '../wardrobeContext';
import { useWardrobeActionContext, useWardrobeExecuteCallback } from '../wardrobeActionContext';
import { useWardrobeContext } from '../wardrobeContext';

type CheckedPosePreset = {
active: boolean;
Expand Down Expand Up @@ -134,7 +135,8 @@ function WardrobePoseCategoriesInternal({ poses, setPose, characterState }: {
}

export function WardrobePoseCategories({ characterState, setPose }: { characterState: AssetFrameworkCharacterState; setPose: (pose: PartialAppearancePose) => void; }): ReactElement {
const { globalState, itemDisplayNameType } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { itemDisplayNameType } = useWardrobeContext();
const roomItems = globalState.getItems({ type: 'roomInventory' });
const poses = useMemo(() => GetFilteredAssetsPosePresets(characterState, roomItems ?? [], itemDisplayNameType), [characterState, roomItems, itemDisplayNameType]);
return (
Expand Down Expand Up @@ -363,7 +365,8 @@ export function WardrobePoseGui({ character, characterState }: {
characterState: AssetFrameworkCharacterState;
}): ReactElement {
const [execute] = useWardrobeExecuteCallback({ allowMultipleSimultaneousExecutions: true });
const { globalState, itemDisplayNameType } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { itemDisplayNameType } = useWardrobeContext();
const roomItems = globalState.getItems({ type: 'roomInventory' });
const assetManager = characterState.assetManager;
const allBones = useMemo(() => assetManager.getAllBones(), [assetManager]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import deleteIcon from '../../../assets/icons/delete.svg';
import { useItemColorRibbon } from '../../../graphics/graphicsLayer';
import { Button } from '../../common/button/button';
import { Scrollbar } from '../../common/scrollbar/scrollbar';
import { WardrobeItemName } from '../itemDetail/wardrobeItemName';
import { useWardrobeActionContext } from '../wardrobeActionContext';
import { InventoryAssetPreview, WardrobeActionButton } from '../wardrobeComponents';
import { useWardrobeContext } from '../wardrobeContext';
import { WardrobeContextExtraItemActionComponent, WardrobeHeldItem } from '../wardrobeTypes';
import { InventoryItemViewDropArea } from './wardrobeItemView';
import { WardrobeItemName } from '../itemDetail/wardrobeItemName';

export function SecondaryInventoryView({ title, secondaryTarget, secondaryTargetContainer = EMPTY_ARRAY, quickActionTarget, quickActionTargetContainer }: {
title: string;
Expand All @@ -27,7 +28,8 @@ export function SecondaryInventoryView({ title, secondaryTarget, secondaryTarget
quickActionTarget: ActionTargetSelector;
quickActionTargetContainer: ItemContainerPath;
}): ReactElement | null {
const { globalState, extraItemActions, showExtraActionButtons, heldItem } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { extraItemActions, showExtraActionButtons, heldItem } = useWardrobeContext();
const navigate = useNavigate();

const extraItemAction = useCallback<WardrobeContextExtraItemActionComponent>(({ target, item }) => {
Expand Down Expand Up @@ -124,7 +126,8 @@ function RoomInventoryViewListItem({ target, itemPath, quickActionTarget, quickA
quickActionTarget: ActionTargetSelector;
quickActionTargetContainer: ItemContainerPath;
}): ReactElement {
const { globalState, heldItem, setHeldItem, showExtraActionButtons } = useWardrobeContext();
const { globalState } = useWardrobeActionContext();
const { heldItem, setHeldItem, showExtraActionButtons } = useWardrobeContext();

const item = EvalItemPath(globalState.getItems(target) ?? EMPTY_ARRAY, itemPath);
const ribbonColor = useItemColorRibbon([], item ?? null);
Expand Down
Loading
Loading