import { Object3DProps, useFrame } from '@react-three/fiber' import * as React from 'react' import { forwardRef, useRef } from 'react' import { Object3D, Vector3 } from 'three' import { calculateScaleFactor } from './calculateScaleFactor' import { ForwardRefComponent } from '../helpers/ts-utils' const worldPos = /* @__PURE__ */ new Vector3() export interface ScreenSizerProps extends Object3DProps { /** Scale factor. Defaults to 1, which equals 1 pixel size. */ scale?: number } /** * Wraps children in an `Object3D` and attempts to scale from * world units to screen units * scale factor. * * For example, this will render a box of roughly 1x1 pixel size, * independently of how far the camera is. * * ```jsx * * * * ``` */ export const ScreenSizer: ForwardRefComponent = /* @__PURE__ */ forwardRef< Object3D, ScreenSizerProps >(({ scale = 1, ...props }, ref) => { const container = useRef(null!) React.useImperativeHandle(ref, () => container.current, []) useFrame((state) => { const obj = container.current if (!obj) return const sf = calculateScaleFactor(obj.getWorldPosition(worldPos), scale, state.camera, state.size) obj.scale.setScalar(sf * scale) }) return })