@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.
151 lines (150 loc) • 6.44 kB
TypeScript
import { EventEmitter } from "eventemitter3";
import { CoreContext, ModulesRecord } from "./CoreContext";
import { IFeaturable } from "./Object3DFeaturablity";
/**
* 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}
*/
export 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;
}