117 lines
3.8 KiB
TypeScript
117 lines
3.8 KiB
TypeScript
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>
|
||
);
|
||
}
|