From 083c62efa00ee2bcfe2e04567aea9ac4e9521315 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Fri, 13 Mar 2026 20:35:47 +0800 Subject: [PATCH] break down pet menu component & remove pet menu for user's own doll --- src/routes/scene/+page.svelte | 9 +- .../scene/components/pet-menu/events.ts | 33 +++++ .../scene/components/pet-menu/pet-menu.svelte | 132 ++++++++++++++++++ .../scene/components/pet-menu/position.ts | 25 ++++ 4 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 src/routes/scene/components/pet-menu/events.ts create mode 100644 src/routes/scene/components/pet-menu/pet-menu.svelte create mode 100644 src/routes/scene/components/pet-menu/position.ts diff --git a/src/routes/scene/+page.svelte b/src/routes/scene/+page.svelte index f22a2c9..d898a97 100644 --- a/src/routes/scene/+page.svelte +++ b/src/routes/scene/+page.svelte @@ -69,14 +69,7 @@ targetX={$cursorPositionOnScreen.raw.x} targetY={$cursorPositionOnScreen.raw.y} spriteUrl={$activeDollSpriteUrl} - > - {#if $sceneInteractive} - - {/if} - + /> {/if} {#each Object.entries($friendsCursorPositions) as [friendId, position] (friendId)} {#if $friendActiveDollSpriteUrls[friendId]} diff --git a/src/routes/scene/components/pet-menu/events.ts b/src/routes/scene/components/pet-menu/events.ts new file mode 100644 index 0000000..907932c --- /dev/null +++ b/src/routes/scene/components/pet-menu/events.ts @@ -0,0 +1,33 @@ +export type CloseHandler = () => void; + +export function createDocumentPointerHandler( + isOpen: () => boolean, + rootEl: () => HTMLDivElement | null, + closeMenu: CloseHandler, +) { + return function handleDocumentPointerDown(event: PointerEvent) { + if (!isOpen() || !rootEl()) { + return; + } + + if (event.target instanceof Node && !rootEl()!.contains(event.target)) { + closeMenu(); + } + }; +} + +export function createKeyDownHandler( + isOpen: () => boolean, + closeMenu: CloseHandler, +) { + return function handleKeyDown(event: KeyboardEvent) { + if (!isOpen()) { + return; + } + + if (event.key === "Escape") { + closeMenu(); + event.preventDefault(); + } + }; +} diff --git a/src/routes/scene/components/pet-menu/pet-menu.svelte b/src/routes/scene/components/pet-menu/pet-menu.svelte new file mode 100644 index 0000000..45b8339 --- /dev/null +++ b/src/routes/scene/components/pet-menu/pet-menu.svelte @@ -0,0 +1,132 @@ + + +
+ {#each actions as action, index} + {@const position = getButtonPosition(index, actions.length)} + {@const openDelay = index * 35} + {@const closeDelay = (actions.length - 1 - index) * 25} + + + {/each} + + +
diff --git a/src/routes/scene/components/pet-menu/position.ts b/src/routes/scene/components/pet-menu/position.ts new file mode 100644 index 0000000..e17eb9f --- /dev/null +++ b/src/routes/scene/components/pet-menu/position.ts @@ -0,0 +1,25 @@ +export interface ButtonPosition { + x: number; + y: number; +} + +export function getButtonPosition( + index: number, + total: number, +): ButtonPosition { + if (total <= 1) { + return { x: 0, y: -48 }; + } + + // A specific set of numbers for the buttons to look correct + const startAngle = -160; + const endAngle = -20; + const angle = startAngle + ((endAngle - startAngle) / (total - 1)) * index; + const angleRad = (angle * Math.PI) / 180; + const radius = 48; + + return { + x: Math.cos(angleRad) * radius, + y: Math.sin(angleRad) * radius, + }; +}