From dda94bd107511fbaa875daab1199f4f8dac71235 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 24 May 2026 19:22:23 +0000 Subject: [PATCH] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/XRHudInWorld.tsx | 33 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/components/three/XRHudInWorld.tsx b/src/components/three/XRHudInWorld.tsx index dd41d6e..9366008 100644 --- a/src/components/three/XRHudInWorld.tsx +++ b/src/components/three/XRHudInWorld.tsx @@ -1,6 +1,7 @@ import { useRef, useState, forwardRef } from 'react'; 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 { Text } from '@react-three/drei'; import { XR3DButton, XR3DPanel } from './XRPanel3D'; @@ -56,7 +57,11 @@ export function XRHudInWorld(props: XRHudInWorldProps) { const { camera } = useThree(); const leftCtrl = useXRInputSourceState('controller', 'left'); const rightCtrl = useXRInputSourceState('controller', 'right'); + const xrSession = useXR((s) => s.session); + const navigate = useNavigate(); 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('scene'); /** When pinned, the panel stays fixed in world space and does NOT follow the head. */ const [pinned, setPinned] = useState(true); @@ -77,12 +82,12 @@ export function XRHudInWorld(props: XRHudInWorldProps) { const dragInitialized = useRef(false); 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; if (gp) { - const aBtn = gp.buttons[4]; - const pressed = !!aBtn?.pressed; - if (pressed && !lastABtn.current) setOpen((v) => !v); + const xBtn = gp.buttons[4]; + const pressed = !!xBtn?.pressed; + if (pressed && !lastABtn.current) setHudVisible((v) => !v); lastABtn.current = pressed; } @@ -166,15 +171,25 @@ export function XRHudInWorld(props: XRHudInWorldProps) { return ( <> setOpen((v) => !v)} /> - {/* Head-locked fallback: always-visible quick controls in lower-left of FOV */} - - + { setOpen((v) => !v); reanchorRequested.current = true; }} fontSize={0.0085} /> - setShowGrid(!showGrid)} fontSize={0.0085} /> + { + // 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} /> {open && (