🚀 Auto-deploy: melhoria no snap e medição AR em 24/05/2026 12:38:19

This commit is contained in:
2026-05-24 12:38:19 +00:00
parent 6046d655df
commit 377346893e
2 changed files with 31 additions and 11 deletions
+20 -11
View File
@@ -53,11 +53,15 @@ const WristToggle = forwardRef<THREE.Group, { open: boolean; onToggle: () => voi
);
export function XRHudInWorld(props: XRHudInWorldProps) {
const { camera } = useThree();
const { camera, gl } = useThree();
const leftCtrl = useXRInputSourceState('controller', 'left');
const rightCtrl = useXRInputSourceState('controller', 'right');
const [open, setOpen] = useState(true);
const [tab, setTab] = useState<Tab>('scene');
const open = useModelStore((s) => s.xrHudOpen);
const setOpen = useModelStore((s) => s.setXrHudOpen);
const tab = useModelStore((s) => s.xrHudTab) as Tab;
const setTab = useModelStore((s) => s.setXrHudTab) as unknown as (t: Tab) => void;
/** When pinned, the panel stays fixed in world space and does NOT follow the head. */
const [pinned, setPinned] = useState(true);
/** While true, the panel is glued to the right controller (drag mode). */
@@ -82,7 +86,7 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
if (gp) {
const aBtn = gp.buttons[4];
const pressed = !!aBtn?.pressed;
if (pressed && !lastABtn.current) setOpen((v) => !v);
if (pressed && !lastABtn.current) setOpen(!open);
lastABtn.current = pressed;
}
@@ -150,11 +154,11 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
}
}
// Head-locked fallback toggle — always visible in lower-left of FOV,
// Head-locked fallback toggle — always visible in lower-right of FOV,
// so the user can reopen the menu even without controllers or if the
// panel is positioned out of view.
if (headLockRef.current) {
const offset = new THREE.Vector3(-0.18, -0.18, -0.5).applyQuaternion(camera.quaternion);
const offset = new THREE.Vector3(0.18, -0.18, -0.5).applyQuaternion(camera.quaternion);
headLockRef.current.position.copy(camera.position).add(offset);
headLockRef.current.quaternion.copy(camera.quaternion);
}
@@ -165,16 +169,21 @@ export function XRHudInWorld(props: XRHudInWorldProps) {
return (
<>
<WristToggle ref={wristRef} open={open} onToggle={() => setOpen((v) => !v)} />
{/* Head-locked fallback: always-visible quick controls in lower-left of FOV */}
<WristToggle ref={wristRef} open={open} onToggle={() => setOpen(!open)} />
{/* Head-locked fallback: always-visible quick controls in lower-right of FOV */}
<group ref={headLockRef} renderOrder={999}>
<XR3DButton position={[0, 0.018, 0]} size={[0.07, 0.022]}
<XR3DButton position={[0, 0.026, 0]} size={[0.07, 0.022]}
label={open ? '✕ Menu' : '☰ Menu'} active={open}
onClick={() => { setOpen((v) => !v); reanchorRequested.current = true; }}
onClick={() => { setOpen(!open); reanchorRequested.current = true; }}
fontSize={0.0085} />
<XR3DButton position={[0, -0.008, 0]} size={[0.07, 0.022]}
<XR3DButton position={[0, 0, 0]} size={[0.07, 0.022]}
label={showGrid ? 'Grid ON' : 'Grid OFF'} active={showGrid}
onClick={() => setShowGrid(!showGrid)} fontSize={0.0085} />
<XR3DButton position={[0, -0.026, 0]} size={[0.07, 0.022]}
label="✕ Sair AR" active={false}
onClick={() => {
gl.xr.getSession()?.end();
}} fontSize={0.0085} />
<RecIndicator />
</group>
{open && (
+11
View File
@@ -299,6 +299,12 @@ interface ModelStore {
xrFeatures: XRFeatureFlags;
setXRFeature: (key: keyof XRFeatureFlags, value: boolean) => void;
resetXRFeatures: () => void;
// ── WebXR HUD states persistent cache ────
xrHudOpen: boolean;
setXrHudOpen: (open: boolean) => void;
xrHudTab: string;
setXrHudTab: (tab: string) => void;
}
/** Sync top-level legacy `model` / `fineTuning` from active SceneModel. */
@@ -673,4 +679,9 @@ export const useModelStore = create<ModelStore>((set, get) => ({
saveXRFeatures(next);
set({ xrFeatures: next });
},
xrHudOpen: true,
setXrHudOpen: (open) => set({ xrHudOpen: open }),
xrHudTab: 'scene',
setXrHudTab: (tab) => set({ xrHudTab: tab }),
}));