Changes
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { Move, RotateCw, RefreshCw } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useModelStore } from '@/stores/useModelStore';
|
||||
|
||||
const POSITION_STEP = 0.001; // 1mm
|
||||
const ROTATION_STEP = 0.1; // 0.1°
|
||||
|
||||
function StepButton({ label, onClick }: { label: string; onClick: () => void }) {
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-7 w-7 font-mono text-xs"
|
||||
onClick={onClick}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
function AxisControl({
|
||||
axis,
|
||||
value,
|
||||
unit,
|
||||
onIncrement,
|
||||
onDecrement,
|
||||
displayValue,
|
||||
}: {
|
||||
axis: string;
|
||||
value: number;
|
||||
unit: string;
|
||||
onIncrement: () => void;
|
||||
onDecrement: () => void;
|
||||
displayValue: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="font-mono text-xs text-muted-foreground w-6">{axis}</span>
|
||||
<StepButton label="−" onClick={onDecrement} />
|
||||
<span className="font-mono text-xs text-foreground w-20 text-center">{displayValue}{unit}</span>
|
||||
<StepButton label="+" onClick={onIncrement} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FineTuningControls() {
|
||||
const { fineTuning, setFineTuning, resetFineTuning } = useModelStore();
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-mono text-xs font-semibold uppercase tracking-widest text-muted-foreground">
|
||||
Ajuste Fino
|
||||
</h3>
|
||||
<Button variant="ghost" size="sm" className="h-6 text-[10px] gap-1" onClick={resetFineTuning}>
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
Resetar
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Position */}
|
||||
<div className="rounded-lg border bg-muted/30 p-3 space-y-2">
|
||||
<div className="flex items-center gap-1.5 mb-2">
|
||||
<Move className="h-3.5 w-3.5 text-primary" />
|
||||
<span className="font-mono text-[10px] text-muted-foreground">Posição (±1mm)</span>
|
||||
</div>
|
||||
<AxisControl
|
||||
axis="X"
|
||||
value={fineTuning.posX}
|
||||
unit="mm"
|
||||
displayValue={(fineTuning.posX * 1000).toFixed(1)}
|
||||
onIncrement={() => setFineTuning({ posX: fineTuning.posX + POSITION_STEP })}
|
||||
onDecrement={() => setFineTuning({ posX: fineTuning.posX - POSITION_STEP })}
|
||||
/>
|
||||
<AxisControl
|
||||
axis="Y"
|
||||
value={fineTuning.posY}
|
||||
unit="mm"
|
||||
displayValue={(fineTuning.posY * 1000).toFixed(1)}
|
||||
onIncrement={() => setFineTuning({ posY: fineTuning.posY + POSITION_STEP })}
|
||||
onDecrement={() => setFineTuning({ posY: fineTuning.posY - POSITION_STEP })}
|
||||
/>
|
||||
<AxisControl
|
||||
axis="Z"
|
||||
value={fineTuning.posZ}
|
||||
unit="mm"
|
||||
displayValue={(fineTuning.posZ * 1000).toFixed(1)}
|
||||
onIncrement={() => setFineTuning({ posZ: fineTuning.posZ + POSITION_STEP })}
|
||||
onDecrement={() => setFineTuning({ posZ: fineTuning.posZ - POSITION_STEP })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Rotation */}
|
||||
<div className="rounded-lg border bg-muted/30 p-3 space-y-2">
|
||||
<div className="flex items-center gap-1.5 mb-2">
|
||||
<RotateCw className="h-3.5 w-3.5 text-primary" />
|
||||
<span className="font-mono text-[10px] text-muted-foreground">Rotação Y (±0.1°)</span>
|
||||
</div>
|
||||
<AxisControl
|
||||
axis="Y°"
|
||||
value={fineTuning.rotY}
|
||||
unit="°"
|
||||
displayValue={fineTuning.rotY.toFixed(1)}
|
||||
onIncrement={() => setFineTuning({ rotY: fineTuning.rotY + ROTATION_STEP })}
|
||||
onDecrement={() => setFineTuning({ rotY: fineTuning.rotY - ROTATION_STEP })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border bg-muted/50 p-2">
|
||||
<p className="font-mono text-[10px] text-muted-foreground">
|
||||
No Quest 3: Grip + Joystick esq. = X/Y, Joystick dir. = Z/Rotação
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -26,6 +26,7 @@ function GLBModel({ url }: { url: string }) {
|
||||
const opacity = useModelStore((s) => s.opacity);
|
||||
const renderMode = useModelStore((s) => s.renderMode);
|
||||
const checklist = useModelStore((s) => s.checklist);
|
||||
const fineTuning = useModelStore((s) => s.fineTuning);
|
||||
|
||||
const modelInfo = useMemo(() => {
|
||||
const box = new THREE.Box3().setFromObject(scene);
|
||||
@@ -71,8 +72,18 @@ function GLBModel({ url }: { url: string }) {
|
||||
});
|
||||
}, [scene, opacity, renderMode, checklist]);
|
||||
|
||||
const rotYRad = (fineTuning.rotY * Math.PI) / 180;
|
||||
|
||||
return (
|
||||
<group ref={ref} position={[-modelInfo.center.x, -modelInfo.center.y, -modelInfo.center.z]}>
|
||||
<group
|
||||
ref={ref}
|
||||
position={[
|
||||
-modelInfo.center.x + fineTuning.posX,
|
||||
-modelInfo.center.y + fineTuning.posY,
|
||||
-modelInfo.center.z + fineTuning.posZ,
|
||||
]}
|
||||
rotation={[0, rotYRad, 0]}
|
||||
>
|
||||
<primitive object={scene} />
|
||||
</group>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useModelStore } from '@/stores/useModelStore';
|
||||
import { ModelViewerCanvas } from '@/components/three/ModelViewer';
|
||||
import { ViewerControls } from '@/components/ViewerControls';
|
||||
import { InspectionChecklist } from '@/components/InspectionChecklist';
|
||||
import { FineTuningControls } from '@/components/FineTuningControls';
|
||||
import { useEffect } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
@@ -84,6 +85,10 @@ const Viewer = () => {
|
||||
|
||||
<Separator />
|
||||
|
||||
<FineTuningControls />
|
||||
|
||||
<Separator />
|
||||
|
||||
<InspectionChecklist />
|
||||
|
||||
<div className="rounded-lg border bg-muted/50 p-3">
|
||||
|
||||
Reference in New Issue
Block a user