Adicionou botão Sair AR
X-Lovable-Edit-ID: edt-f602c6ac-5eb0-4c32-9ea0-9d1b4f559559 Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { useRef, useState, forwardRef } from 'react';
|
import { useRef, useState, forwardRef } from 'react';
|
||||||
import { useFrame, useThree } from '@react-three/fiber';
|
import { useFrame, useThree } from '@react-three/fiber';
|
||||||
import { useXRInputSourceState } from '@react-three/xr';
|
import { useXRInputSourceState, useXR } from '@react-three/xr';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { Text } from '@react-three/drei';
|
import { Text } from '@react-three/drei';
|
||||||
import { XR3DButton, XR3DPanel } from './XRPanel3D';
|
import { XR3DButton, XR3DPanel } from './XRPanel3D';
|
||||||
@@ -56,7 +57,11 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
|
|||||||
const { camera } = useThree();
|
const { camera } = useThree();
|
||||||
const leftCtrl = useXRInputSourceState('controller', 'left');
|
const leftCtrl = useXRInputSourceState('controller', 'left');
|
||||||
const rightCtrl = useXRInputSourceState('controller', 'right');
|
const rightCtrl = useXRInputSourceState('controller', 'right');
|
||||||
|
const xrSession = useXR((s) => s.session);
|
||||||
|
const navigate = useNavigate();
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
|
/** Visibility of the small head-locked floating button group (toggled by X button). */
|
||||||
|
const [hudVisible, setHudVisible] = useState(true);
|
||||||
const [tab, setTab] = useState<Tab>('scene');
|
const [tab, setTab] = useState<Tab>('scene');
|
||||||
/** When pinned, the panel stays fixed in world space and does NOT follow the head. */
|
/** When pinned, the panel stays fixed in world space and does NOT follow the head. */
|
||||||
const [pinned, setPinned] = useState(true);
|
const [pinned, setPinned] = useState(true);
|
||||||
@@ -77,12 +82,12 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
|
|||||||
const dragInitialized = useRef(false);
|
const dragInitialized = useRef(false);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
// Toggle via left A button (Quest Touch buttons[4])
|
// Toggle the head-locked 3-button group via left X button (Quest Touch buttons[4])
|
||||||
const gp = leftCtrl?.inputSource?.gamepad;
|
const gp = leftCtrl?.inputSource?.gamepad;
|
||||||
if (gp) {
|
if (gp) {
|
||||||
const aBtn = gp.buttons[4];
|
const xBtn = gp.buttons[4];
|
||||||
const pressed = !!aBtn?.pressed;
|
const pressed = !!xBtn?.pressed;
|
||||||
if (pressed && !lastABtn.current) setOpen((v) => !v);
|
if (pressed && !lastABtn.current) setHudVisible((v) => !v);
|
||||||
lastABtn.current = pressed;
|
lastABtn.current = pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,15 +171,25 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WristToggle ref={wristRef} open={open} onToggle={() => setOpen((v) => !v)} />
|
<WristToggle ref={wristRef} open={open} onToggle={() => setOpen((v) => !v)} />
|
||||||
{/* Head-locked fallback: always-visible quick controls in lower-left of FOV */}
|
{/* Head-locked fallback: floating quick-controls in lower-left of FOV.
|
||||||
<group ref={headLockRef} renderOrder={999}>
|
Toggled on/off by the left controller X button. */}
|
||||||
<XR3DButton position={[0, 0.018, 0]} size={[0.07, 0.022]}
|
<group ref={headLockRef} renderOrder={999} visible={hudVisible}>
|
||||||
|
<XR3DButton position={[0, 0.030, 0]} size={[0.07, 0.022]}
|
||||||
label={open ? '✕ Menu' : '☰ Menu'} active={open}
|
label={open ? '✕ Menu' : '☰ Menu'} active={open}
|
||||||
onClick={() => { setOpen((v) => !v); reanchorRequested.current = true; }}
|
onClick={() => { setOpen((v) => !v); reanchorRequested.current = true; }}
|
||||||
fontSize={0.0085} />
|
fontSize={0.0085} />
|
||||||
<XR3DButton position={[0, -0.008, 0]} size={[0.07, 0.022]}
|
<XR3DButton position={[0, 0.004, 0]} size={[0.07, 0.022]}
|
||||||
label={showGrid ? 'Grid ON' : 'Grid OFF'} active={showGrid}
|
label={showGrid ? 'Grid ON' : 'Grid OFF'} active={showGrid}
|
||||||
onClick={() => setShowGrid(!showGrid)} fontSize={0.0085} />
|
onClick={() => setShowGrid(!showGrid)} fontSize={0.0085} />
|
||||||
|
<XR3DButton position={[0, -0.022, 0]} size={[0.07, 0.022]}
|
||||||
|
label="⏏ Sair AR"
|
||||||
|
onClick={() => {
|
||||||
|
// End the XR session while preserving placement/state in the store,
|
||||||
|
// then return to the Viewer. Re-entering AR restores the same state.
|
||||||
|
try { xrSession?.end(); } catch (e) { console.warn('[XR] session.end failed', e); }
|
||||||
|
setTimeout(() => navigate('/viewer'), 50);
|
||||||
|
}}
|
||||||
|
fontSize={0.0085} />
|
||||||
<RecIndicator />
|
<RecIndicator />
|
||||||
</group>
|
</group>
|
||||||
{open && (
|
{open && (
|
||||||
|
|||||||
Reference in New Issue
Block a user