Files
SteelXR2/src/components/three/XRPanel3D.tsx
T
gpt-engineer-app[bot] 7532aa93a6 Changes
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
2026-05-14 17:59:46 +00:00

104 lines
2.7 KiB
TypeScript

import { useState, ReactNode } from 'react';
import { Text } from '@react-three/drei';
import * as THREE from 'three';
interface XR3DButtonProps {
position?: [number, number, number];
size?: [number, number];
label: string;
icon?: string;
active?: boolean;
disabled?: boolean;
onClick?: () => void;
color?: string;
fontSize?: number;
}
/** Flat 3D button suitable for in-XR HUD. Reacts to controller raycast. */
export function XR3DButton({
position = [0, 0, 0],
size = [0.08, 0.025],
label,
icon,
active = false,
disabled = false,
onClick,
color,
fontSize = 0.008,
}: XR3DButtonProps) {
const [hovered, setHovered] = useState(false);
const [w, h] = size;
const bgColor = disabled
? '#222'
: active
? (color ?? '#3b82f6')
: hovered
? '#444'
: '#1a1a1a';
const fgColor = disabled ? '#555' : active ? '#ffffff' : '#e5e7eb';
const borderColor = active ? (color ?? '#3b82f6') : hovered ? '#666' : '#333';
return (
<group
position={position}
onPointerOver={(e) => { e.stopPropagation(); if (!disabled) setHovered(true); }}
onPointerOut={(e) => { e.stopPropagation(); setHovered(false); }}
onClick={(e) => { e.stopPropagation(); if (!disabled && onClick) onClick(); }}
>
{/* Border */}
<mesh position={[0, 0, -0.0005]}>
<planeGeometry args={[w + 0.002, h + 0.002]} />
<meshBasicMaterial color={borderColor} transparent opacity={0.95} />
</mesh>
{/* Background */}
<mesh>
<planeGeometry args={[w, h]} />
<meshBasicMaterial color={bgColor} transparent opacity={0.92} side={THREE.DoubleSide} />
</mesh>
<Text
position={[0, 0, 0.001]}
fontSize={fontSize}
color={fgColor}
anchorX="center"
anchorY="middle"
maxWidth={w * 0.95}
>
{icon ? `${icon} ${label}` : label}
</Text>
</group>
);
}
interface XR3DPanelProps {
position?: [number, number, number];
size?: [number, number];
color?: string;
opacity?: number;
children?: ReactNode;
}
/** Background panel for grouping XR3DButtons. */
export function XR3DPanel({
position = [0, 0, 0],
size = [0.4, 0.3],
color = '#0a0a0a',
opacity = 0.85,
children,
}: XR3DPanelProps) {
const [w, h] = size;
return (
<group position={position}>
<mesh position={[0, 0, -0.001]}>
<planeGeometry args={[w + 0.004, h + 0.004]} />
<meshBasicMaterial color="#3b82f6" transparent opacity={0.6} />
</mesh>
<mesh>
<planeGeometry args={[w, h]} />
<meshBasicMaterial color={color} transparent opacity={opacity} side={THREE.DoubleSide} />
</mesh>
{children}
</group>
);
}