import { useState, useEffect, useRef } from 'react' import useStore from '../store/useStore' function Btn({ icon, label, active, onClick, color, title, shortcut, danger }) { const [h, setH] = useState(false) const acc = color || (active ? 'var(--accent)' : null) return ( ) } function Divider() { return
} export default function Toolbar() { const { transformMode, setTransformMode, snapEnabled, setSnapEnabled, lightingPreset, setLightingPreset, isPlaying, setIsPlaying, loopPlayback, setLoopPlayback, selectedModelId, addKeyframe, currentFrame, currentFrame: cf, setCurrentFrame, totalFrames, undo, redo, undoStack, redoStack, showGrid, setShowGrid, showGizmo, setShowGizmo, showCameraObjects, setShowCameraObjects, projectName, setProjectName, saveProject, loadProject, exportProjectJSON, duplicateModel, removeModel, models, } = useStore() const [editName, setEditName] = useState(false) const [nameVal, setNameVal] = useState(projectName) const importRef = useRef() // Global keyboard shortcuts useEffect(() => { const onKey = (e) => { // Skip if typing in an input if (['INPUT','TEXTAREA','SELECT'].includes(e.target.tagName)) return const k = e.code if (k==='KeyG' && !e.ctrlKey) { setTransformMode('translate'); return } if (k==='KeyR' && !e.ctrlKey) { setTransformMode('rotate'); return } if (k==='KeyS' && !e.ctrlKey) { setTransformMode('scale'); return } if (k==='Space') { e.preventDefault(); setIsPlaying(!useStore.getState().isPlaying); return } if (k==='KeyZ' && (e.ctrlKey||e.metaKey) && !e.shiftKey) { e.preventDefault(); undo(); return } if ((k==='KeyZ' && e.shiftKey && (e.ctrlKey||e.metaKey)) || (k==='KeyY' && (e.ctrlKey||e.metaKey))) { e.preventDefault(); redo(); return } if (k==='KeyD' && !e.ctrlKey) { e.preventDefault(); const sel=useStore.getState().selectedModelId; if(sel) duplicateModel(sel); return } if (k==='Delete'||k==='Backspace') { const sel=useStore.getState().selectedModelId; if(sel){ removeModel(sel) }; return } if (k==='KeyL') { setLoopPlayback(!useStore.getState().loopPlayback); return } if (k==='Tab') { e.preventDefault(); setSnapEnabled(!useStore.getState().snapEnabled); return } // Screenshot if (k==='F12') { e.preventDefault(); takeScreenshot(); return } // Save if ((e.ctrlKey||e.metaKey) && k==='KeyS') { e.preventDefault(); const ok=saveProject(); console.log(ok?'Saved':'Save failed'); return } } window.addEventListener('keydown', onKey) return () => window.removeEventListener('keydown', onKey) }, []) const takeScreenshot = () => { const canvas = document.querySelector('canvas') if (!canvas) return const url = canvas.toDataURL('image/png') const a = document.createElement('a') a.href=url; a.download=`screenshot_${Date.now()}.png`; a.click() } const handleImport = (e) => { const file = e.target.files[0] if (!file) return useStore.getState().importProjectJSON(file).then(result => { if (!result?.ok) console.warn('Import failed:', result?.error) }) e.target.value = '' } const tools = [ { id:'translate', icon:'⊹', label:'Move', short:'G' }, { id:'rotate', icon:'↻', label:'Rotate', short:'R' }, { id:'scale', icon:'⤡', label:'Scale', short:'S' }, ] const lights = [ { id:'studio', icon:'◎' }, { id:'outdoor', icon:'◉' }, { id:'dramatic', icon:'◈' }, { id:'neon', icon:'◆' }, ] const canUndo = undoStack?.length > 0 const canRedo = redoStack?.length > 0 return (