UNPKG

@vladkrutenyuk/three-kvy-core

Version:

Everything you need to create any-complexity 3D apps with Three.js. Empower Three.js with a modular, lifecycle-managed context that seamlessly propagates through objects via reusable features providing structured logic.

627 lines (610 loc) 30.4 kB
declare namespace KVY { import * as THREE from 'three'; import { EventEmitter } from 'eventemitter3'; /** * Removes the first occurrence of a specified item from an array. * * @template T - The type of elements in the array. * @param {T[]} array - The array from which to remove the item. * @param {T} item - The item to remove from the array. * @returns {boolean} - Returns `true` if the item was found and removed, otherwise `false`. */ declare function removeArrayItem<T>(array: T[], item: T): boolean; declare const defineProps: <T>(o: T, properties: PropertyDescriptorMap & ThisType<any>) => T; declare const readOnly: (value: any) => PropertyDescriptor; declare const notEnumer: (value: any) => PropertyDescriptor; var props = /*#__PURE__*/Object.freeze({ __proto__: null, defineProps: defineProps, notEnumer: notEnumer, readOnly: readOnly }); /** * Traverses the ancestors of a given THREE.Object3D target and applies a callback function to each ancestor. * The traversal is interruptible based on the return value of the callback function. * * @param {THREE.Object3D} target - The starting THREE.Object3D whose ancestors will be traversed. * @param {(ancestor: THREE.Object3D) => boolean} callback - A function that is called with each ancestor. If the callback returns true, the traversal continues; if false, the traversal stops. */ declare function traverseUp(target: THREE.Object3D, callback: (ancestor: THREE.Object3D) => boolean): void; type ThreeContextParams = { renderer?: THREE.WebGLRendererParameters; }; /** * A utility for initializing core [Three.js](https://threejs.org) entities, managing their setup, and handling rendering. * @see {@link https://three-kvy-core.vladkrutenyuk.ru/docs/api/three-context | Official Documentation} * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/core/ThreeContext.ts | Source} */ declare class ThreeContext extends EventEmitter<ThreeContextEventMap, ThreeContext> { /** * Shortcut to create an instance of ThreeContext. * @param {typeof import("three")} Three - Three.js `THREE` imported module, object containing class constructors `WebGLRenderer`, `PerspectiveCamera`, `Scene`, `Clock`, `Raycaster`. * @param {{renderer: THREE.WebGLRendererParameters}} params - (optional) Object parameters * @returns {ThreeContext} An instance of ThreeContext * @example * ```js import * as THREE from "three"; import * as KVY from "@vladkrutenyuk/three-kvy-core"; const three = new KVY.ThreeContext.create(THREE, { renderer: { antialias: true } }); ``` */ static create(Three: { WebGLRenderer: typeof THREE.WebGLRenderer; PerspectiveCamera: typeof THREE.PerspectiveCamera; Scene: typeof THREE.Scene; Clock: typeof THREE.Clock; Raycaster: typeof THREE.Raycaster; }, params?: ThreeContextParams): ThreeContext; /** * (readonly) flag to mark that it is an instance of ThreeContext. * @type {true} */ readonly isThreeContext: true; /** * (readonly) instance of Three.js `WebGLRenderer` used for rendering your awesome scene. * @type {THREE.WebGLRenderer} */ readonly renderer: THREE.WebGLRenderer; /** * An instance of Three.js `PerspectiveCamera` camera which is used in rendering. Fires event `camerachanged` on set. */ get camera(): THREE.PerspectiveCamera; set camera(value: THREE.PerspectiveCamera); /** (readonly) instance of Three.js `Scene` that contains all objects to be rendered. */ readonly scene: THREE.Scene; /** (readonly) instance of Three.js `Clock` */ readonly clock: THREE.Clock; /** (readonly) instance of Three.js `Raycaster`. */ readonly raycaster: THREE.Raycaster; /** (readonly) HTML element where the renderer canvas is appended on mount. */ get container(): HTMLDivElement | null; /** * (readonly) flag to check if the renderer canvas is currently mounted. * @type {boolean} */ get isMounted(): boolean; /** * (readonly) flag to check whether this instance has been destroyed. */ get isDestroyed(): boolean; private _camera; private _container; private _resizeObserver; private _isMounted; private _isDestroyed; private _srcRenderFn; private _renderFn; /** * This creates a new {@link ThreeContext} instance. * @param {THREE.WebGLRenderer} renderer - An instance of Three.js `WebGLRenderer` * @param {THREE.PerspectiveCamera} camera - An instance of Three.js `PerspectiveCamera` * @param {THREE.Scene} scene - An instance of Three.js `Scene` * @param {THREE.Clock} clock - An instance of Three.js `Clock` * @param {THREE.Raycaster} raycaster - An instance of Three.js `Raycaster` */ constructor(renderer: THREE.WebGLRenderer, camera: THREE.PerspectiveCamera, scene: THREE.Scene, clock: THREE.Clock, raycaster: THREE.Raycaster); /** * Renders the scene using the current render function. Fires `renderbefore` and `renderafter` events. */ render(): void; /** * Overrides the render function with a custom implementation. * @param {Function} fn * @returns */ overrideRender(fn: () => void): this; /** * Resets the render function to its default implementation. */ resetRender(): this; /** * Append the renderer canvas to the given HTML container, initializes event listeners and resize observer. * Fires `mount` event. * @param {HTMLDivElement} container - The HTML container element where to mount (append) renderer canvas. */ mount(container: HTMLDivElement): this | undefined; /** * Remove the renderer canvas from DOM it was mounted, removes event listeners, disconnect resize observer. * Fires `"unmount"` event. */ unmount(): this | undefined; /** * Destroys this instance, releasing resources and preventing further rendering. * Fires `"destroy"` event. */ destroy(): void; private resizeHandler; private cameraChanged; } declare const ev: Readonly<{ RenderBefore: "renderbefore"; RenderAfter: "renderafter"; Mount: "mount"; Unmount: "unmount"; Destroy: "destroy"; CameraChanged: "camerachanged"; Resize: "resize"; }>; type ThreeContextEventMap = { [ev.RenderBefore]: []; [ev.RenderAfter]: []; [ev.Mount]: [root: HTMLDivElement]; [ev.Unmount]: []; [ev.Destroy]: []; [ev.Resize]: [width: number, height: number]; [ev.CameraChanged]: [ newCamera: THREE.PerspectiveCamera, prevCamera: THREE.PerspectiveCamera ]; }; /** * Base class, acting as a pluggable module, for extending {@link CoreContext} functionality.\ * It enables clean separation of concerns while maintaining full access to context capabilities.\ * Modules are assigned to context {@link CoreContext}, can provide services to features {@link Object3DFeature}, and manage their own * lifecycle through the {@link useCtx useCtx(ctx)} pattern. * @see {@link https://three-kvy-core.vladkrutenyuk.ru/docs/api/core-context-module | Official Documentation} * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/core/CoreContextModule.ts | Source} */ declare abstract class CoreContextModule<TEventTypes extends EventEmitter.ValidEventTypes = string | symbol, TModules extends ModulesRecord = ModulesRecordDefault> extends EventEmitter<TEventTypes> { /** Read-only flag to mark that it is an instance of {@link CoreContextModule}.*/ readonly isCoreContextModule: true; /** * (readonly) Getter for the instance of {@link CoreContext} this is assigned to. * @warning **Throws exception** if try to access before assign. */ get ctx(): CoreContext<TModules>; /** (readonly) Flag to check if this instance has been assigned to some {@link CoreContext}. */ get hasCtx(): boolean; private _ctx?; constructor(); /** * Overridable Lifecycle Method. Called when the module is assigned to a {@link CoreContext}. \ * The returned cleanup function (optional) is called when the module is removed from the context.\ * Also cleanup is called if context is destroyed.\ * Calling the method manually is prohibited. * @param {CoreContext} ctx - An instance of {@link CoreContext} to which this module was assigned. * @returns {Function | undefined} */ protected useCtx(ctx: CoreContext<TModules>): ReturnOfUseCtx; } type ReturnOfUseCtx = undefined | (() => void) | void; interface ICoreContextModuleProtected { _ctx?: CoreContext<ModulesRecordDefault>; useCtx<TModules extends ModulesRecord>(ctx: CoreContext<TModules>): ReturnOfUseCtx; } declare const Evnt: Readonly<{ AttCtx: "attachedctx"; DetCtx: "detachedctx"; FtAdd: "featureadded"; FtRem: "featureremoved"; Dstr: "destroy"; }>; type Object3DFeaturabilityEventTypes<TModules extends ModulesRecord = {}> = { [Evnt.AttCtx]: [ctx: CoreContext<TModules>]; [Evnt.DetCtx]: [ctx: CoreContext<TModules>]; [Evnt.FtAdd]: [feature: Object3DFeature<TModules>]; [Evnt.FtRem]: [feature: Object3DFeature<TModules>]; }; declare const key = "__kvy_ftblty__"; declare class Object3DFeaturability<TModules extends ModulesRecord = {}, TObj extends THREE.Object3D = THREE.Object3D> extends EventEmitter<Object3DFeaturabilityEventTypes<TModules>> { /** * Extracts {@link Object3DFeaturability} from the given object if it is featurable. * * @param obj - The object to extract {@link Object3DFeaturability} from. * @returns The {@link Object3DFeaturability} instance if available, otherwise `null`. */ static extract<TModules extends ModulesRecord = {}, TObj extends THREE.Object3D = THREE.Object3D>(obj: TObj): Object3DFeaturability<TModules, TObj> | null; /** * Creates or retrieves {@link Object3DFeaturability} for the given object. * If the object already has featurability, it is returned. Otherwise, a new instance is created. * * @param obj - The object to make featurable. * @returns The {@link Object3DFeaturability} instance for the object. */ static from<TModules extends ModulesRecord = {}, TObj extends THREE.Object3D = THREE.Object3D>(obj: TObj): Object3DFeaturability<TModules, TObj>; static destroy<TObj extends THREE.Object3D = THREE.Object3D>(obj: TObj, force?: boolean): void; static log: (target: Object3DFeaturability, msg: string) => void; readonly isObjectFeaturability = true; readonly object: IFeaturablePrivate<TModules, TObj>; get ctx(): CoreContext<TModules> | null; get features(): Object3DFeature<any, string | symbol>[]; private _ctx; private readonly _features; private constructor(); /** * Destroys the featurability instance and removes all features. */ destroy(force?: boolean): void; destroyAllFeatures(): void; /** * Adds a new feature to the object. * @param Feature The feature class. * @param props The properties required for initialization. * @param beforeAttach A callback invoked before attaching the feature. * @returns The created feature instance. */ addFeature<TFeature extends Object3DFeature<any, any>, TProps>(Feature: new (object: IFeaturable, props: TProps) => TFeature, props: keyof TProps extends never ? undefined : TProps, beforeAttach?: (feature: TFeature) => void): TFeature; addFeature<TFeature extends Object3DFeature<any, any>>(Feature: new (object: IFeaturable) => TFeature): TFeature; /** * Retrieves a feature of a specific class, if present. * @param FeatureClass The feature class to search for. * @returns The feature instance, or `null` if not found. */ getFeature<TFeatureClass extends typeof Object3DFeature>(FeatureClass: TFeatureClass): InstanceType<TFeatureClass> | null; /** * Retrieves a feature of a specific class, if present. * @param FeatureClass The feature class to search for. * @returns The feature instance, or `null` if not found. */ getFeatureBy<TFeature extends Object3DFeature = Object3DFeature>(predicate: (feature: TFeature) => boolean): TFeature | null; /** * Removes a feature from the object and destroys it. * @param feature The feature instance to remove. */ destroyFeature<TFeature extends Object3DFeature<any, any>>(feature: TFeature): boolean; /** * Attaches or detaches the object from a `CoreContext`. * @warning You should be careful to use this method manually * @param ctx The `CoreContext` instance, or `null` to detach. * @returns This instance. * @warning Use with caution. */ setCtx(ctx: CoreContext<TModules> | null): this; private onObjectAdded; private inheritCtx; private onObjectRemoved; private attachCtx; private detachCtx; private propagateAttachCtxDown; private propagateDetachCtxDown; private _log; } type IFeaturable<TModules extends ModulesRecord = any, TObj extends THREE.Object3D = THREE.Object3D> = TObj & { isFeaturable: true; }; type IFeaturablePrivate<TModules extends ModulesRecord = any, TObj extends THREE.Object3D = THREE.Object3D> = TObj & { [key]?: Object3DFeaturability<TModules, TObj>; isFeaturable?: true; }; type ModulesRecord = Record<string, CoreContextModule>; type ModulesRecordDefault = Record<string, CoreContextModule & Record<string, any>>; /** * The primary central entity, acting as a main hub, that orchestrates the Three.js environment, animation loop, and module system.\ * Propagates through features `Object3DFeature` which are added to Three.js `Object3D`.\ * Provides an elegant lifecycle management system and handles fundametal initializations. * @see {@link https://three-kvy-core.vladkrutenyuk.ru/docs/api/core-context | Official Documentation} * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/core/CoreContext.ts | Source} */ declare class CoreContext<TModules extends ModulesRecord = ModulesRecordDefault> extends EventEmitter<{ destroy: []; looprun: []; loopstop: []; }> { /** * Initialization shortcut. Creates and returns a new {@link CoreContext} instance. * @param {typeof import("three")} Three - Object containing Three.js class constructors `WebGLRenderer`, `Scene`, `PerspectiveCamera`, `Clock`, `Raycaster`. In short, just use imported [`THREE`](https://threejs.org/docs/manual/en/introduction/Installation.html) Three.js module. * @param {TModules} modules - (optional) Custom dictionary of any your modules {@link CoreContextModules}. * @param {ThreeContextParams} params - (optional) Object paramateres * @example * ```js * import * as THREE from "three"; * import * as KVY from "@vladkrutenyuk/three-kvy-core"; * * const modules = { * moduleA: new MyModuleA(), * moduleB: new MyModuleB(), * }; * const ctx = KVY.CoreContext.create(THREE, modules, { renderer: { antialias: true } }); * ``` * @returns {CoreContext} */ static create<TModules extends ModulesRecord = ModulesRecordDefault>(Three: { Scene: typeof THREE.Scene; WebGLRenderer: typeof THREE.WebGLRenderer; PerspectiveCamera: typeof THREE.PerspectiveCamera; Raycaster: typeof THREE.Raycaster; Clock: typeof THREE.Clock; }, modules?: Partial<TModules>, params?: ThreeContextParams): CoreContext<TModules>; /** (readonly) Flag to mark that it is an instance of {@link CoreContext}. */ readonly isCoreContext: true; /** (readonly) Instance of {@link ThreeContext}. Utility to manage Three.js setup. */ readonly three: ThreeContext; /** (readonly) Dictionary of assinged modules. * @type { { [key:string]: CoreContextModule } } */ readonly modules: TModules; /** * (readonly) Instance of Three.js `Object3D` that plays the role of entry point for a given context propagation.\ * By default, it's Three.js `Scene` instance given in `ThreeContext` of this (`this.root === this.three.scene`).\ * You can specify any other `root` if you initialize the context through constructor. * @type {THREE.Object3D} * */ get root(): IFeaturableRoot<TModules>; /** (readonly) The seconds passed since the last frame. */ get deltaTime(): number; /** (readonly) The seconds passed since the context loop started - by {@link run run()}. */ get time(): number; /** (readonly) Flag to check if this instance is destroyed. */ get isDestroyed(): boolean; /** (readonly) Flag to check if this instance loop is running. */ get isRunning(): boolean; private readonly _root; private readonly _clock; private _time; private _deltaTime; private _isDestroyed; private _isRunning; /** * This creates a new {@link CoreContext} instance. * @param three - An instance of {@link ThreeContext}. Utility to manage Three.js setup. * @param {THREE.Object3D} root - (optional) An instance of Three.js `Object3D`. The entry point for context propagation. If root is not providen then Three.js `Scene` from the given {@link ThreeContext} will be taken as root. * @param {TModules} modules - (optional) Custom dictionary of any your modules {@link CoreContextModules}. */ constructor(three: ThreeContext, root?: THREE.Object3D, modules?: Partial<TModules>); /** Run animation loop and Three.js rendering. Stoppable as many times as you need by `stop()`. */ run(): void; /** Stop animation loop and Three.js rendering. Resumable as many times as you need by `run()`. */ stop(): void; private _cleanups; /** * Assigns the given dictionary of modules to this instance. * It will be merged with the existing dictionary of modules. * * @remarks Note that if the given dictionary contains a key for which a module is already assigned, * it will be skipped, and a warning message will be fired. * * @param {{ [key: string]: CoreContextModule }} modules - Dictionary of module instances to assign to this context. */ assignModules(modules: Partial<TModules>): this; /** * Assign module by key to this instance. * It will be added to the existing dictionary of modules by the given key. * * @remarks Note that if the given key is already assigned, it will be skipped, and a warning message will be fired. * @param {string} key - The key by which to assign the module to the context in the dictionary. * @param {CoreContextModule} module - An instance of `CoreContextModule` implementation. * @returns */ assignModule<TKey extends keyof TModules>(key: TKey, module: TModules[TKey]): void; /** * Remove a module by key that was specified when it was assigned. * @param {string} key - key by which a module was assigned. */ removeModule(key: keyof TModules): void; /** * Destroy this instance. * - Sets {@link isDestroyed} to `true` permanently. * - Stops its animation loop permanently. * - Destroys its {@link three three}: {@link ThreeContext} permanently. * - Fires the `"destroy"` event. * - Cleans up {@link root} from the assigned logic when it was designated as `root` in the given CoreContext. * - Removes all assigned {@link modules}. * - Removes all listeners from its events. */ destroy(): this; } interface IFeaturableRoot<TModules extends ModulesRecord = any> extends IFeaturable<TModules> { isRoot: true; } /** * Base class for implementing reusable components (features) that can be added to any Three.js Object3D.\ * Features get the context {@link CoreContext} when their object is added to ctx.root hierarchy, and lose it when removed, or forcibly on call.\ * Handle the context attach and detach can be through overridable lyfecycle method {@link useCtx useCtx(ctx)} where context is providen as arguement.\ * Built-in overridable lifecycle event methods like {@link onBeforeRender onBeforeRender(ctx)} etc. * Direct access to object {@link object this.object} the feature is attached to. * @see {@link https://three-kvy-core.vladkrutenyuk.ru/docs/api/object-3d-feature | Official Documentation} * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/core/Object3DFeature.ts | Source} */ declare abstract class Object3DFeature<TModules extends ModulesRecord = {}, TEventTypes extends EventEmitter.ValidEventTypes = string | symbol> extends EventEmitter<TEventTypes> { /** (readonly) Flag to mark that it is an instance of `isObject3DFeature`. */ readonly isObject3DFeature: true; /** (readonly) Unique increment number for this feature instance. */ readonly id: number; /** UUID of feature instance. This gets automatically assigned, so this shouldn't be edited. * Its generation way can be changed via overriding `Object3DFeature.generateUUID` static method. */ uuid: string; /** (readonly) An instance of Three.js Object3D which this feature was added to. */ readonly object: IFeaturable<TModules>; /** * (readonly) Getter for the current attached `CoreContext`. * @warning **Throws exception** if try to access before it is attached. */ get ctx(): CoreContext<TModules>; /** (readonly) Flag to check if this feature has attached `CoreContext`. */ get hasCtx(): boolean; private _ftblty; private _ctx; /** * @private Must be initiallized through the `addFeature` static factory method. * @param {IFeaturable<TModules>} object - The object that this feature is going to be attached to. */ constructor(object: IFeaturable); /** * Initializes the feature. Called internally after instantiation. * @private */ init(): void; /** Destroys this feature instance. */ destroy(): void; private ftbltyAttachedToCtxHandler; private ftbltyDetachedFromCtxHandler; private _useCtxReturn; private attachCtx; private detachCtx; /** * Overridable Lifecycle Method. Called when some `CoreContext` is attached to this feature. * The defined returned cleanup function (optional) is called when the context is detached from the feature. * It is prohibitted to be called manually. * * @param {CoreContext<TModules>} ctx - An instance of `CoreContext` which is attached to this feature. * @returns {undefined | (() => void) | void} A cleanup function, or `undefined` if no cleanup is needed. * @override * * @example * ``` * useCtx(ctx) { * const mesh = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial()); * this.object.add(mesh); * * const listener = () => { * // ... * } * const customTicker = ctx.modules.customTicker; * customTicker.on("tick", listener); * * return () => { * this.object.remove(mesh); * mesh.geometry.dispose(); * mesh.material.dispose(); * * customTicker.off("tick", listener); * } * } * ``` */ protected useCtx(ctx: CoreContext<TModules>): undefined | (() => void) | void; /** * When this feature `destroy()` is called. * @override */ protected onDestroy(): void; /** * Before render is called. On each frame after loop run `ctx.run()` or `ctx.three.render()` is called manually. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onBeforeRender(ctx: CoreContext<TModules>): void; /** * After render is called. On each frame after loop run `ctx.run()` or `ctx.three.render()` is called manually. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onAfterRender(ctx: CoreContext<TModules>): void; /** * When container (where mounted) is resized. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onResize(ctx: CoreContext<TModules>): void; /** * When `ctx.three.mount(container)` is called. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onMount(ctx: CoreContext<TModules>): void; /** * When `ctx.three.unmount()` is called. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onUnmount(ctx: CoreContext<TModules>): void; /** * When `ctx.run()` is called. * @param {CoreContext<TModules>} ctx - The current attached instance of `CoreContext`. * @override */ onLoopRun(ctx: CoreContext<TModules>): void; /** * When `ctx.stop()` is called. * @param {CoreContext<TModules>} ctx - The game context. * @override */ onLoopStop(ctx: CoreContext<TModules>): void; private _log; private initCtxEventMethods; /** * initEventHandlerMethod (iehm) */ private iehm; /** * @returns Generates a unique identifier for [`Object3DFeature`](/docs/) instances.\ * By default, it uses [`crypto.randomUUID()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID), but in case of fall back, it returns `${Math.random()}-${Date.now()}`. * You can freely override this static method to any of your own generation, e.g: * ```js * CoreContext.generateUUID = () => nanoid(10) * ``` */ static generateUUID: () => string; /** * Static method for overriding to handle logs. * @param {Object3DFeature} target - The feature instance. * @param {string} msg - The log message. */ static log: (target: Object3DFeature, msg: string) => void; } /** * A static factory method that creates {@link Object3DFeature} and adds it to a given Three.js `Object3D` instance. * It uses a given feature class (not an instance) that extends {@link Object3DFeature} * with optional constructor parameters. Returns an instance of the provided feature class. * @param {THREE.Object3D} obj - The target Three.js `Object3D` instance to which the feature is added. * @param {typeof Object3DFeature} Feature - The feature class to add, which extends {@link Object3DFeature}. * @param {object | undefined} props - An object containing parameters for the feature's constructor. Optional of feature implementation has no custom props in constructor. * @param {(feature: Object3DFeature) => void} [beforeAttach] - (optional) A callback invoked before attaching the feature * @returns {Object3DFeature} The created feature instance. */ declare function addFeature<TObj extends THREE.Object3D, TFeature extends Object3DFeature<any, any>, TProps>(obj: TObj, Feature: new (object: IFeaturable, props: TProps) => TFeature, props: keyof TProps extends never ? undefined : TProps, beforeAttach?: (feature: TFeature) => void): TFeature; declare function addFeature<TObj extends THREE.Object3D, TFeature extends Object3DFeature<any, any>>(obj: TObj, Feature: new (object: IFeaturable) => TFeature): TFeature; /** * A static method that retrieves a feature instance from the given object by its class (constructor). Returns first found such feature instance, or `null` if not. * @param {THREE.Object3D} obj - The target Three.js Object3D instance to search for the feature. * @param {typeof Object3DFeature} FeatureClass - The feature class (constructor) whose instance is being searched for. It must extends Object3DFeature. * @returns {Object3DFeature | null} */ declare function getFeature<TObj extends THREE.Object3D, TFeatureClass extends typeof Object3DFeature>(obj: TObj, FeatureClass: TFeatureClass): InstanceType<TFeatureClass> | null; /** * Finds a feature in the given object using a predicate function. Returns the first matching instance of `Object3DFeature` if found, otherwise `null`. * @param {THREE.Object3D} obj - The target Three.js `Object3D` instance to search within. * @param {(feature: Object3DFeature) => boolean} predicate - A predicate function that receives a feature instance as an argument and returns a boolean indicating whether the feature matches. * @returns {Object3DFeature | null} */ declare function getFeatureBy<TObj extends THREE.Object3D, TFeature extends Object3DFeature>(obj: TObj, predicate: (feature: TFeature) => boolean): TFeature | null; /** * Retrieves all features attached to a given object. Returns a copy of the feature list—an array of `Object3DFeature[]` instances—or `null` if no features were added. * @remarks Note that changing returned array won't affect anything. It returns a **COPY** of this object features list. * @param {THREE.Object3D} obj - The target Three.js `Object3D` instance. * @returns {Object3DFeature[] | null} */ declare function getFeatures<TObj extends THREE.Object3D>(obj: TObj): Object3DFeature[] | null; /** * Destroys and detaches all features from the given object, freeing associated resources. * If `recursively` is set to `true`, this method will apply cleanup recursively to the entire object hierarchy. * @param {THREE.Object3D} obj - The target Three.js `Object3D` instance. * @param {boolean} recursively - (Optional) Default is `false`. A boolean flag indicating whether to apply this method recursively to the object's hierarchy. */ declare function clear<TObj extends THREE.Object3D>(obj: TObj, recursively?: boolean): void; declare const utils: { removeArrayItem: typeof removeArrayItem; props: typeof props; traverseUp: typeof traverseUp; assertDefined: <T>(value: T | null | undefined, name: string) => T; }; declare const REVISION = "2.0.0"; declare global { interface Window { __THREE_KVY_CORE__?: string; } }; export { CoreContext, CoreContextModule, type ICoreContextModuleProtected, type IFeaturable, type IFeaturableRoot, type ModulesRecord, type ModulesRecordDefault, Object3DFeaturability, type Object3DFeaturabilityEventTypes, Object3DFeature, REVISION, type ReturnOfUseCtx, ThreeContext, type ThreeContextEventMap, type ThreeContextParams, addFeature, clear, getFeature, getFeatureBy, getFeatures, utils }; } declare module "@vladkrutenyuk/game-world" { export=KVY;}