/* eslint-disable @typescript-eslint/ban-types */ import type { DefineComponent, VNode, VNodeRef } from 'vue' import type * as THREE from 'three' import type { EventProps as PointerEventHandlerEventProps } from '../composables/usePointerEventHandler' // Based on React Three Fiber types by Pmndrs // https://github.com/pmndrs/react-three-fiber/blob/v9/packages/fiber/src/three-types.ts export type AttachFnType = (parent: any, self: O) => () => void export type AttachType = string | AttachFnType export type ConstructorRepresentation = new (...args: any[]) => any export type NonFunctionKeys

= { [K in keyof P]-?: P[K] extends Function ? never : K }[keyof P] export type Overwrite = Omit> & O export type Properties = Pick> export type Mutable

= { [K in keyof P]: P[K] | Readonly } export type Args = T extends ConstructorRepresentation ? ConstructorParameters : any[] export interface TresCatalogue { [name: string]: ConstructorRepresentation } export type TresCamera = THREE.OrthographicCamera | THREE.PerspectiveCamera export interface InstanceProps { args?: Args

object?: T visible?: boolean dispose?: null attach?: AttachType } interface TresBaseObject { attach?: string removeFromParent?: () => void dispose?: () => void [prop: string]: any // for arbitrary properties } export interface LocalState { type: string // objects and parent are used when children are added with `attach` instead of being added to the Object3D scene graph objects: TresObject3D[] parent: TresObject3D | null primitive?: boolean eventCount: number handlers: Partial memoizedProps: { [key: string]: any } } // Custom type for geometry and material properties in Object3D export interface TresObject3D extends THREE.Object3D { geometry?: THREE.BufferGeometry & TresBaseObject material?: THREE.Material & TresBaseObject __tres: LocalState /* userData: { tres__materialViaProp: boolean tres__geometryViaProp: boolean [key: string]: any } */ } export type TresObject = TresBaseObject & (TresObject3D | THREE.BufferGeometry | THREE.Material | THREE.Fog) export interface TresScene extends THREE.Scene { userData: { // keys are prefixed with tres__ to avoid name collisions tres__registerCamera?: (newCamera: THREE.Camera, active?: boolean) => void tres__deregisterCamera?: (camera: THREE.Camera) => void tres__registerAtPointerEventHandler?: (object: THREE.Object3D & PointerEventHandlerEventProps) => void tres__deregisterAtPointerEventHandler?: (object: THREE.Object3D) => void tres__registerBlockingObjectAtPointerEventHandler?: (object: THREE.Object3D) => void tres__deregisterBlockingObjectAtPointerEventHandler?: (object: THREE.Object3D) => void [key: string]: any } } // Events // eslint-disable-next-line import/namespace export interface Intersection extends THREE.Intersection { /** The event source (the object which registered the handler) */ eventObject: TresObject } export interface IntersectionEvent extends Intersection { /** The event source (the object which registered the handler) */ eventObject: TresObject /** An array of intersections */ intersections: Intersection[] /** vec3.set(pointer.x, pointer.y, 0).unproject(camera) */ unprojectedPoint: THREE.Vector3 /** Normalized event coordinates */ pointer: THREE.Vector2 /** Delta between first click and this event */ delta: number /** The ray that pierced it */ ray: THREE.Ray /** The camera that was used by the raycaster */ camera: TresCamera /** stopPropagation will stop underlying handlers from firing */ stopPropagation: () => void /** The original host event */ nativeEvent: TSourceEvent /** If the event was stopped by calling stopPropagation */ stopped: boolean } export type ThreeEvent = IntersectionEvent & Properties export type DomEvent = PointerEvent | MouseEvent | WheelEvent export interface Events { onClick: EventListener onContextMenu: EventListener onDoubleClick: EventListener onWheel: EventListener onPointerDown: EventListener onPointerUp: EventListener onPointerLeave: EventListener onPointerMove: EventListener onPointerCancel: EventListener onLostPointerCapture: EventListener } export interface EventHandlers { onClick?: (event: ThreeEvent) => void onContextMenu?: (event: ThreeEvent) => void onDoubleClick?: (event: ThreeEvent) => void onPointerUp?: (event: ThreeEvent) => void onPointerDown?: (event: ThreeEvent) => void onPointerOver?: (event: ThreeEvent) => void onPointerOut?: (event: ThreeEvent) => void onPointerEnter?: (event: ThreeEvent) => void onPointerLeave?: (event: ThreeEvent) => void onPointerMove?: (event: ThreeEvent) => void onPointerMissed?: (event: MouseEvent) => void onPointerCancel?: (event: ThreeEvent) => void onWheel?: (event: ThreeEvent) => void } interface MathRepresentation { set(...args: number[] | [THREE.ColorRepresentation]): any } interface VectorRepresentation extends MathRepresentation { setScalar(s: number): any } export interface VectorCoordinates { x: number y: number z: number } export type MathType = T extends THREE.Color ? ConstructorParameters | THREE.ColorRepresentation // eslint-disable-next-line max-len : T extends VectorRepresentation | THREE.Layers | THREE.Euler ? T | Parameters | number | VectorCoordinates : T | Parameters export type TresVector2 = MathType export type TresVector3 = MathType export type TresVector4 = MathType export type TresColor = MathType export type TresLayers = MathType export type TresQuaternion = MathType export type TresEuler = MathType type WithMathProps

= { [K in keyof P]: P[K] extends MathRepresentation | THREE.Euler ? MathType : P[K] } interface RaycastableRepresentation { raycast(raycaster: THREE.Raycaster, intersects: THREE.Intersection[]): void } type EventProps

= P extends RaycastableRepresentation ? Partial : unknown export interface VueProps

{ children?: VNode[] ref?: VNodeRef key?: string | number | symbol } type ElementProps> = Partial< Overwrite, VueProps

& EventProps

> > export type ThreeElement = Mutable< Overwrite, Omit, T>, 'object'>> > type ThreeExports = typeof THREE type ThreeInstancesImpl = { [K in keyof ThreeExports as Uncapitalize]: ThreeExports[K] extends ConstructorRepresentation ? ThreeElement : never } export interface ThreeInstances extends ThreeInstancesImpl { primitive: Omit, 'args'> & { object: object } } type TresComponents = { [K in keyof ThreeInstances as `Tres${Capitalize}`]: DefineComponent } declare module 'vue' { export interface GlobalComponents extends TresComponents { } } /* eslint-enable @typescript-eslint/ban-types */