/** * Type augmentations and utilities for three.js r183. * * Some properties exist at runtime but were removed or changed in @types/three r183. * This module provides type-safe access without `as any` casts. */ import type { Interpolant, Texture, Source } from 'three'; // #region Module augmentation for properties that exist at runtime but are missing from types declare module 'three' { interface Material { /** Unique ID for this material instance. Exists at runtime via Object.defineProperty. */ readonly id: number; } interface KeyframeTrack { /** Creates an interpolant for sampling this track. Exists at runtime. */ createInterpolant(): Interpolant; } } // #region Texture image type utilities // Texture uses a generic for image data. At runtime this can be // ImageBitmap, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, // or a plain object with {width, height, data} (DataTexture/CompressedTexture). /** Checks if a texture image has width/height dimensions (ImageBitmap, HTMLImageElement, HTMLCanvasElement, etc.) */ export function hasImageDimensions(image: unknown): image is { width: number; height: number } { return image != null && typeof image === 'object' && typeof (image as any).width === 'number' && typeof (image as any).height === 'number'; } /** Get the width/height from a texture, checking image, source.data, and direct properties (e.g. render targets) */ export function getTextureDimensions(texture: Texture): { width: number; height: number } { if (hasImageDimensions(texture.image)) { return { width: texture.image.width, height: texture.image.height }; } const srcData = texture.source?.data; if (hasImageDimensions(srcData)) { return { width: srcData.width, height: srcData.height }; } // RenderTarget textures may have dimensions on the texture itself if (hasImageDimensions(texture)) { return { width: texture.width, height: texture.height }; } return { width: 0, height: 0 }; } /** Checks if a texture image has pixel data (typed array from DataTexture) */ export function hasPixelData(image: unknown): image is { data: ArrayBufferView; width: number; height: number } { return hasImageDimensions(image) && (image as any).data != null; } /** Get the source data of a texture as a dimension-bearing object, or null */ export function getSourceDimensions(texture: Texture): { width: number; height: number } | null { const data = texture.source?.data; if (hasImageDimensions(data)) return data; return null; } /** Checks if a value is a renderable image (ImageBitmap, HTMLImageElement, HTMLCanvasElement, etc.) */ export function isTextureImage(image: unknown): image is TexImageSource | OffscreenCanvas { return image instanceof ImageBitmap || image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || (typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas); }