fix: zone grid snapping, shelf position panel, deselect on item placement (#394)
* fix: zone grid snapping, shelf position panel, deselect on item placement - Zone tool reads the editor's gridSnapStep (0.5/0.25/0.1/0.05) instead of a hardcoded 0.5 for both cursor move and click snapping. - Shelf inspector gains a Position group (vec3 X/Y/Z sliders), matching the item panel. - Item catalog clears the viewer selection before arming placement so shortcuts (rotate & co) don't hit both the ghost and the selected node. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: move level display naming into @pascal-app/core getDefaultLevelName / getLevelDisplayName ("Ground Floor" / "Floor N" / "Basement N") lived in packages/editor's internal lib, so viewer-only surfaces couldn't reach them and fell back to hand-rolled "Level N" labels. The helpers are pure domain logic, so they move to core and export from its barrel; the editor package's seven call sites now import them from there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7539387ff5
commit
d36e8fcc78
@@ -184,7 +184,7 @@ export const ZoneTool: React.FC = () => {
|
||||
const [gridX, gridZ] = snapWorldXZForActiveBuilding(
|
||||
event.position[0],
|
||||
event.position[2],
|
||||
0.5,
|
||||
useEditor.getState().gridSnapStep,
|
||||
).local
|
||||
cursorPosition = [gridX, gridZ]
|
||||
levelYRef.current = event.localPosition[1]
|
||||
@@ -217,7 +217,7 @@ export const ZoneTool: React.FC = () => {
|
||||
const [gridX, gridZ] = snapWorldXZForActiveBuilding(
|
||||
event.position[0],
|
||||
event.position[2],
|
||||
0.5,
|
||||
useEditor.getState().gridSnapStep,
|
||||
).local
|
||||
let clickPoint: [number, number] = [gridX, gridZ]
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useViewer } from '@pascal-app/viewer'
|
||||
import { Check, ChevronDown, Eye, EyeOff, Layers2, Plus, Trash2 } from 'lucide-react'
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { getLevelDisplayName } from '../../../lib/level-name'
|
||||
import { getLevelDisplayName } from '@pascal-app/core'
|
||||
import { createLocalGuideImage } from '../../../lib/local-guide-image'
|
||||
import { cn } from '../../../lib/utils'
|
||||
import useEditor, { type GridSnapStep } from '../../../store/use-editor'
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useEffect, useState } from 'react'
|
||||
import { create } from 'zustand'
|
||||
import { useShallow } from 'zustand/shallow'
|
||||
import { Dialog, DialogContent, DialogTitle } from './../../../components/ui/primitives/dialog'
|
||||
import { getLevelDisplayName } from '../../../lib/level-name'
|
||||
import { getLevelDisplayName } from '@pascal-app/core'
|
||||
import { useCommandRegistry } from '../../../store/use-command-registry'
|
||||
import { usePaletteViewRegistry } from '../../../store/use-palette-view-registry'
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
buildLevelDuplicateCreateOps,
|
||||
type LevelDuplicatePreset,
|
||||
} from '../../lib/level-duplication'
|
||||
import { getDefaultLevelName, getLevelDisplayName } from '../../lib/level-name'
|
||||
import { getDefaultLevelName, getLevelDisplayName } from '@pascal-app/core'
|
||||
import { deleteLevelWithFallbackSelection } from '../../lib/level-selection'
|
||||
import {
|
||||
getEditorClipboardSnapshot,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { AssetInput } from '@pascal-app/core'
|
||||
import { resolveCdnUrl } from '@pascal-app/viewer'
|
||||
import { resolveCdnUrl, useViewer } from '@pascal-app/viewer'
|
||||
import Image from 'next/image'
|
||||
import { useEffect } from 'react'
|
||||
import {
|
||||
@@ -96,6 +96,10 @@ export function ItemCatalog({
|
||||
key={index}
|
||||
onClick={() => {
|
||||
triggerSFX('sfx:menu-click')
|
||||
// Drop the current selection before arming placement — keeping
|
||||
// it would route shortcuts (rotate & co) to both the ghost and
|
||||
// the selected node.
|
||||
useViewer.getState().setSelection({ selectedIds: [], zoneId: null })
|
||||
setSelectedItem(item)
|
||||
setTool('item')
|
||||
setMode('build')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import type { LevelNode } from '@pascal-app/core'
|
||||
import { useEffect, useState } from 'react'
|
||||
import type { LevelDuplicatePreset } from '../../lib/level-duplication'
|
||||
import { getLevelDisplayName } from '../../lib/level-name'
|
||||
import { getLevelDisplayName } from '@pascal-app/core'
|
||||
import { cn } from '../../lib/utils'
|
||||
import {
|
||||
Dialog,
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
buildLevelDuplicateCreateOps,
|
||||
type LevelDuplicatePreset,
|
||||
} from './../../../../../lib/level-duplication'
|
||||
import { getDefaultLevelName } from './../../../../../lib/level-name'
|
||||
import { getDefaultLevelName } from '@pascal-app/core'
|
||||
import { deleteLevelWithFallbackSelection } from './../../../../../lib/level-selection'
|
||||
import { createLocalGuideImage } from './../../../../../lib/local-guide-image'
|
||||
import { cn } from './../../../../../lib/utils'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useViewer } from '@pascal-app/viewer'
|
||||
import { Layers } from 'lucide-react'
|
||||
import { memo, useCallback, useState } from 'react'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { getDefaultLevelName } from '../../../../../lib/level-name'
|
||||
import { getDefaultLevelName } from '@pascal-app/core'
|
||||
import { InlineRenameInput } from './inline-rename-input'
|
||||
import { focusTreeNode, TreeNode, TreeNodeWrapper } from './tree-node'
|
||||
import { TreeNodeActions } from './tree-node-actions'
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
type AnyNodeId,
|
||||
type BuildingNode,
|
||||
emitter,
|
||||
getLevelDisplayName,
|
||||
type LevelNode,
|
||||
useScene,
|
||||
type ZoneNode,
|
||||
@@ -30,7 +31,6 @@ import {
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { getLevelDisplayName } from '../lib/level-name'
|
||||
import { cn } from '../lib/utils'
|
||||
import { ActionButton } from './ui/action-menu/action-button'
|
||||
import {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import type { LevelNode } from '@pascal-app/core'
|
||||
|
||||
export function getDefaultLevelName(level: number): string {
|
||||
if (level === 0) return 'Ground Floor'
|
||||
if (level > 0) return `Floor ${level}`
|
||||
return `Basement ${-level}`
|
||||
}
|
||||
|
||||
export function getLevelDisplayName(level: Pick<LevelNode, 'name' | 'level'>): string {
|
||||
return level.name || getDefaultLevelName(level.level)
|
||||
}
|
||||
Reference in New Issue
Block a user