From 189f0e03a05daaf64b96351fa4da9b37c2633387 Mon Sep 17 00:00:00 2001 From: dohyeons Date: Mon, 27 Oct 2025 12:02:15 +0900 Subject: [PATCH] =?UTF-8?q?=EC=83=88=EC=9A=94=EC=86=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=8B=9C=EC=97=90=EB=8F=84=20=EC=9C=84=EB=A1=9C=20?= =?UTF-8?q?=EC=98=AC=EB=A6=AC=EA=B8=B0=20=EC=B2=B4=ED=81=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/widgets/yard-3d/YardEditor.tsx | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/YardEditor.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/YardEditor.tsx index 21435a16..87319916 100644 --- a/frontend/components/admin/dashboard/widgets/yard-3d/YardEditor.tsx +++ b/frontend/components/admin/dashboard/widgets/yard-3d/YardEditor.tsx @@ -129,10 +129,39 @@ export default function YardEditor({ layout, onBack }: YardEditorProps) { return { x: 0, z: 0 }; }; + // 특정 XZ 위치에 배치할 때 적절한 Y 위치 계산 (마인크래프트 쌓기) + const calculateYPosition = (x: number, z: number, existingPlacements: YardPlacement[]) => { + const gridSize = 5; + const halfSize = gridSize / 2; + let maxY = halfSize; // 기본 바닥 높이 (2.5) + + for (const p of existingPlacements) { + // XZ가 겹치는지 확인 + const isXZOverlapping = Math.abs(x - p.position_x) < gridSize && Math.abs(z - p.position_z) < gridSize; + + if (isXZOverlapping) { + // 이 요소의 윗면 높이 + const topY = p.position_y + (p.size_y || gridSize) / 2; + // 새 요소의 Y 위치 (윗면 + 새 요소 높이/2) + const newY = topY + gridSize / 2; + if (newY > maxY) { + maxY = newY; + } + } + } + + return maxY; + }; + // 빈 요소 추가 (로컬 상태에만 추가, 저장 시 서버에 반영) const handleAddElement = () => { const gridSize = 5; const emptyPos = findEmptyGridPosition(gridSize); + const centerX = emptyPos.x + gridSize / 2; + const centerZ = emptyPos.z + gridSize / 2; + + // 해당 위치에 적절한 Y 계산 (쌓기) + const appropriateY = calculateYPosition(centerX, centerZ, placements); const newPlacement: YardPlacement = { id: nextPlacementId, // 임시 음수 ID @@ -142,9 +171,9 @@ export default function YardEditor({ layout, onBack }: YardEditorProps) { quantity: null, unit: null, // 그리드 칸의 중심에 배치 (Three.js Box position은 중심점) - position_x: emptyPos.x + gridSize / 2, // 칸 중심: 0→2.5, 5→7.5, 10→12.5... - position_y: gridSize / 2, // 요소 높이의 절반 (바닥에서 시작) - position_z: emptyPos.z + gridSize / 2, // 칸 중심: 0→2.5, 5→7.5, 10→12.5... + position_x: centerX, // 칸 중심: 0→2.5, 5→7.5, 10→12.5... + position_y: appropriateY, // 쌓기 고려한 Y 위치 + position_z: centerZ, // 칸 중심: 0→2.5, 5→7.5, 10→12.5... size_x: gridSize, size_y: gridSize, size_z: gridSize,