🚀 Auto-deploy: melhoria no snap e medição AR em 02/06/2026 21:25:43
This commit is contained in:
@@ -84,20 +84,72 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
|
||||
const headLockRef = useRef<THREE.Group>(null);
|
||||
const targetPos = useRef(new THREE.Vector3());
|
||||
const targetQuat = useRef(new THREE.Quaternion());
|
||||
const lastABtn = useRef(false);
|
||||
const lastButtonsState = useRef({
|
||||
left4: false, // X
|
||||
left5: false, // Y
|
||||
left3: false, // Menu (☰)
|
||||
right4: false, // A
|
||||
right5: false, // B
|
||||
});
|
||||
/** Cached offset from controller to panel at drag start. */
|
||||
const dragOffsetPos = useRef(new THREE.Vector3());
|
||||
const dragOffsetQuat = useRef(new THREE.Quaternion());
|
||||
const dragInitialized = useRef(false);
|
||||
|
||||
useFrame(() => {
|
||||
// Toggle the head-locked 3-button group via left X button (Quest Touch buttons[4])
|
||||
const gp = leftCtrl?.inputSource?.gamepad;
|
||||
if (gp) {
|
||||
const xBtn = gp.buttons[4];
|
||||
const pressed = !!xBtn?.pressed;
|
||||
if (pressed && !lastABtn.current) setHudVisible((v) => !v);
|
||||
lastABtn.current = pressed;
|
||||
// Escuta botões A, B, X, Y e Menu do esquerdo
|
||||
const gpLeft = leftCtrl?.inputSource?.gamepad;
|
||||
const gpRight = rightCtrl?.inputSource?.gamepad;
|
||||
|
||||
let xPressed = false;
|
||||
let yPressed = false;
|
||||
let menuPressed = false;
|
||||
let aPressed = false;
|
||||
let bPressed = false;
|
||||
|
||||
if (gpLeft) {
|
||||
// Esquerdo: Menu (3), X (4), Y (5)
|
||||
const btnMenu = gpLeft.buttons[3];
|
||||
const btnX = gpLeft.buttons[4];
|
||||
const btnY = gpLeft.buttons[5];
|
||||
|
||||
if (btnX?.pressed && !lastButtonsState.current.left4) xPressed = true;
|
||||
if (btnY?.pressed && !lastButtonsState.current.left5) yPressed = true;
|
||||
if (btnMenu?.pressed && !lastButtonsState.current.left3) menuPressed = true;
|
||||
|
||||
lastButtonsState.current.left4 = !!btnX?.pressed;
|
||||
lastButtonsState.current.left5 = !!btnY?.pressed;
|
||||
lastButtonsState.current.left3 = !!btnMenu?.pressed;
|
||||
}
|
||||
|
||||
if (gpRight) {
|
||||
// Direito: A (4), B (5)
|
||||
const btnA = gpRight.buttons[4];
|
||||
const btnB = gpRight.buttons[5];
|
||||
|
||||
if (btnA?.pressed && !lastButtonsState.current.right4) aPressed = true;
|
||||
if (btnB?.pressed && !lastButtonsState.current.right5) bPressed = true;
|
||||
|
||||
lastButtonsState.current.right4 = !!btnA?.pressed;
|
||||
lastButtonsState.current.right5 = !!btnB?.pressed;
|
||||
}
|
||||
|
||||
// Se o menu estiver aberto, pressionar X físico fecha o projeto (encerra sessão AR)
|
||||
if (xPressed && open) {
|
||||
try { xrSession?.end(); } catch (e) { console.warn('[XR] session.end failed', e); }
|
||||
setTimeout(() => navigate('/viewer'), 50);
|
||||
toast.success("Projeto fechado!");
|
||||
} else if (aPressed || bPressed || xPressed || yPressed) {
|
||||
// Se qualquer um dos botões A, B, X, Y for pressionado, abre/traz o menu
|
||||
setOpen(true);
|
||||
reanchorRequested.current = true;
|
||||
}
|
||||
|
||||
// Pressionar o botão de Menu (☰) do controle esquerdo abre o menu de ferramentas diretamente
|
||||
if (menuPressed) {
|
||||
setOpen(true);
|
||||
setTab('tools');
|
||||
reanchorRequested.current = true;
|
||||
}
|
||||
|
||||
// Floating panel:
|
||||
@@ -527,6 +579,7 @@ function ToolsTab(p: XRHudInWorldProps) {
|
||||
const setScaleRatio = useModelStore((s) => s.setScaleRatio);
|
||||
const resetScale = useModelStore((s) => s.resetScale);
|
||||
const clearMeasurements = useModelStore((s) => s.clearMeasurements);
|
||||
const undoLastMeasurement = useModelStore((s) => s.undoLastMeasurement);
|
||||
|
||||
return (
|
||||
<group>
|
||||
@@ -585,21 +638,24 @@ function ToolsTab(p: XRHudInWorldProps) {
|
||||
const preset = SCALE_PRESETS.find((sp) => sp.label === lbl)!;
|
||||
return (
|
||||
<XR3DButton key={lbl}
|
||||
position={[-0.16 + i * 0.06, -0.14, 0]} size={[0.055, 0.022]} label={lbl}
|
||||
position={[-0.16 + i * 0.054, -0.14, 0]} size={[0.05, 0.022]} label={lbl}
|
||||
active={scaleRatio.label === lbl}
|
||||
onClick={() => setScaleRatio(preset)} />
|
||||
);
|
||||
})}
|
||||
<XR3DButton position={[0.10, -0.14, 0]} size={[0.062, 0.022]}
|
||||
<XR3DButton position={[0.076, -0.14, 0]} size={[0.046, 0.022]}
|
||||
label="↺ Reset" color="#dc2626"
|
||||
onClick={resetScale} fontSize={0.0085} />
|
||||
<XR3DButton position={[0.17, -0.14, 0]} size={[0.062, 0.022]}
|
||||
label="✕ Medidas" color="#dc2626"
|
||||
onClick={clearMeasurements} fontSize={0.0085} />
|
||||
onClick={resetScale} fontSize={0.0075} />
|
||||
<XR3DButton position={[0.126, -0.14, 0]} size={[0.05, 0.022]}
|
||||
label="⎌ Desfaz" color="#3b82f6"
|
||||
onClick={undoLastMeasurement} fontSize={0.0075} />
|
||||
<XR3DButton position={[0.18, -0.14, 0]} size={[0.05, 0.022]}
|
||||
label="✕ Limpa" color="#dc2626"
|
||||
onClick={clearMeasurements} fontSize={0.0075} />
|
||||
|
||||
{measureMode && (
|
||||
<Text position={[-0.24, -0.17, 0]} fontSize={0.0065} color="#a3e635" anchorX="left" maxWidth={0.5}>
|
||||
Gatilho D: marcar · A: desfazer · B: limpar · Gatilho E: alternar snap
|
||||
Gatilho D: marcar ponto · Gatilho E: alternar snap · A/B/X/Y: abrir Menu
|
||||
</Text>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user