diff --git a/src/components/PreviewStep.tsx b/src/components/PreviewStep.tsx index a637cf7..2b2dc6e 100644 --- a/src/components/PreviewStep.tsx +++ b/src/components/PreviewStep.tsx @@ -1,4 +1,4 @@ -import React, { Suspense, useEffect, useRef, useState } from 'react'; +import React, { Suspense, useEffect, useRef, useState, useMemo } from 'react'; import { Canvas } from '@react-three/fiber'; import { OrbitControls, Center, Environment } from '@react-three/drei'; import * as THREE from 'three'; @@ -8,6 +8,7 @@ import { createBinGeometry, generateSTL, exportSTL } from '../services/geometryG import { Download, Package, Info, Loader2, Share2, Check, Ruler } from 'lucide-react'; import { generateShareUrl } from '../utils/share'; +// --- DrawerFrame (Каркас ящика) --- const DrawerFrame = ({ config }: { config: AppConfig }) => { const { width, depth, height } = config.drawer; const offset = 0.5; @@ -21,29 +22,43 @@ const DrawerFrame = ({ config }: { config: AppConfig }) => { ) } +// --- BinMesh (Ячейка) --- interface BinMeshProps { part: GeneratedPart; thickness: number; - cornerRadius: number; // <--- ADDED PROP + cornerRadius: number; // Важный проп для радиуса isSelected: boolean; onClick: () => void; } const BinMesh: React.FC = ({ part, thickness, cornerRadius, isSelected, onClick }) => { - const geometry = React.useMemo(() => { - // PASS cornerRadius HERE + // 1. Создаем основную геометрию ячейки + const geometry = useMemo(() => { return createBinGeometry(part.width, part.depth, part.height, thickness, cornerRadius); }, [part, thickness, cornerRadius]); + // 2. Создаем геометрию для рамки выделения + // Используем EdgesGeometry с порогом 20 градусов. + // Это скроет линии на плавных изгибах (где угол между полигонами ~5-6 градусов), + // но оставит четкие грани сверху, снизу и по углам. + const edgesGeometry = useMemo(() => { + return new THREE.EdgesGeometry(geometry, 20); + }, [geometry]); + return ( + {/* Сама модель */} { e.stopPropagation(); onClick(); }}> - + + + {/* Подсветка выделения (теперь повторяет форму скругления) */} {isSelected && ( - - {/* Для подсветки оставляем обычный бокс, т.к. edgesGeometry на extrude выглядит грязно */} - + )} @@ -51,6 +66,7 @@ const BinMesh: React.FC = ({ part, thickness, cornerRadius, isSele ); }; +// --- PreviewStep (Основной компонент) --- interface Props { parts: GeneratedPart[]; config: AppConfig; @@ -70,7 +86,6 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => { }, [selectedId]); const handleDownload = (part: GeneratedPart) => { - // PASS config.cornerRadius HERE const geometry = createBinGeometry(part.width, part.depth, part.height, config.wallThickness, config.cornerRadius); const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial()); exportSTL(mesh, `${part.name.replace(/\s+/g, '_')}.stl`); @@ -82,7 +97,6 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => { try { const zip = new JSZip(); parts.forEach(part => { - // PASS config.cornerRadius HERE const geometry = createBinGeometry(part.width, part.depth, part.height, config.wallThickness, config.cornerRadius); const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial()); const stlData = generateSTL(mesh); @@ -135,12 +149,15 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => { return (
+ {/* Верхняя панель: Размеры + Поделиться */}
+
Размеры ящика:
+
Ширина: @@ -157,6 +174,7 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => { мм
+
+ {/* 3D Viewer */}
@@ -184,6 +203,7 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => {
  • • Скролл: Масштаб
  • + = ({ parts, config, splits }) => { key={part.id} part={part} thickness={config.wallThickness} - cornerRadius={config.cornerRadius || 0} // PASS PROP + cornerRadius={config.cornerRadius || 0} // <-- ИСПРАВЛЕНО: Передаем радиус isSelected={selectedId === part.id} onClick={() => setSelectedId(part.id)} /> @@ -219,6 +239,7 @@ export const PreviewStep: React.FC = ({ parts, config, splits }) => {
    + {/* Sidebar List */}