fix item scale surface

This commit is contained in:
wass08
2026-02-23 12:41:55 +09:00
parent 6581e25e9f
commit 49c4794ecb
4 changed files with 11 additions and 6 deletions
@@ -34,13 +34,15 @@ function MoveItemContent({ movingNode }: { movingNode: ItemNode }) {
draftNode,
// Duplicates start fresh in floor mode; wall/ceiling draft is created lazily by ensureDraft
initialState: isNew ? { surface: 'floor', wallId: null, ceilingId: null, surfaceItemId: null } : getInitialState(movingNode),
// Preserve the original item's scale so Y-position calculations use the correct height
defaultScale: isNew ? movingNode.scale : undefined,
initDraft: (gridPosition) => {
if (isNew) {
// Duplicate: use the same create() path as ItemTool so ghost rendering works correctly.
// Floor items get a draft immediately; wall/ceiling items are created lazily on surface entry.
gridPosition.copy(new Vector3(...movingNode.position))
if (!movingNode.asset.attachTo) {
draftNode.create(gridPosition, movingNode.asset, movingNode.rotation)
draftNode.create(gridPosition, movingNode.asset, movingNode.rotation, movingNode.scale)
}
} else {
draftNode.adopt(movingNode)
@@ -411,7 +411,7 @@ export const itemSurfaceStrategy = {
const x = snapToGrid(localPos.x, ourDims[0])
const z = snapToGrid(localPos.z, ourDims[2])
const y = surfaceItem.asset.surface.height
const y = surfaceItem.asset.surface.height * surfaceItem.scale[1]
const worldSnapped = surfaceMesh.localToWorld(new Vector3(x, y, z))
@@ -445,7 +445,7 @@ export const itemSurfaceStrategy = {
const x = snapToGrid(localPos.x, ourDims[0])
const z = snapToGrid(localPos.z, ourDims[2])
const y = surfaceItem.asset.surface.height
const y = surfaceItem.asset.surface.height * surfaceItem.scale[1]
const worldSnapped = surfaceMesh.localToWorld(new Vector3(x, y, z))
@@ -18,7 +18,7 @@ export interface DraftNodeHandle {
/** Whether the current draft was adopted (move mode) vs created (create mode) */
readonly isAdopted: boolean
/** Create a new draft item at the given position. Returns the created node or null. */
create: (gridPosition: Vector3, asset: AssetInput, rotation?: [number, number, number]) => ItemNode | null
create: (gridPosition: Vector3, asset: AssetInput, rotation?: [number, number, number], scale?: [number, number, number]) => ItemNode | null
/** Take ownership of an existing scene node as the draft (for move mode). */
adopt: (node: ItemNode) => void
/** Commit the current draft. Create mode: delete+recreate. Move mode: update in place. */
@@ -40,13 +40,14 @@ export function useDraftNode(): DraftNodeHandle {
const adoptedRef = useRef(false)
const originalStateRef = useRef<OriginalState | null>(null)
const create = useCallback((gridPosition: Vector3, asset: AssetInput, rotation?: [number, number, number]): ItemNode | null => {
const create = useCallback((gridPosition: Vector3, asset: AssetInput, rotation?: [number, number, number], scale?: [number, number, number]): ItemNode | null => {
const currentLevelId = useViewer.getState().selection.levelId
if (!currentLevelId) return null
const node = ItemNode.parse({
position: [gridPosition.x, gridPosition.y, gridPosition.z],
rotation: rotation ?? [0, 0, 0],
scale: scale ?? [1, 1, 1],
name: asset.name,
asset,
parentId: currentLevelId,
@@ -66,6 +66,8 @@ export interface PlacementCoordinatorConfig {
onCommitted: () => boolean
onCancel?: () => void
initialState?: PlacementState
/** Scale to use when lazily creating a draft (e.g. for wall/ceiling duplicates). Defaults to [1,1,1]. */
defaultScale?: [number, number, number]
}
export function usePlacementCoordinator(config: PlacementCoordinatorConfig): React.ReactNode {
@@ -140,7 +142,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
cursorGroupRef.current.position.set(...result.cursorPosition)
cursorGroupRef.current.rotation.y = result.cursorRotationY
draftNode.create(gridPosition.current, asset, [0, result.cursorRotationY, 0])
draftNode.create(gridPosition.current, asset, [0, result.cursorRotationY, 0], configRef.current.defaultScale)
const draft = draftNode.current
if (draft) {