CoreContext
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.
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import * as KVY from "@vladkrutenyuk/three-kvy-core";
const ctx = KVY.CoreContext.create(THREE);
const mesh = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshNormalMaterial());
ctx.root.add(mesh);
const controls = new OrbitControls(ctx.three.camera, ctx.three.renderer.domElement);
ctx.three.mount(document.querySelector("#canvas-container"));
ctx.run();
What is ctx.three?
The ThreeContext
instance. Utility to initialize the core three.js entities, manage their setup and rendering.
Inside of CoreContext
, it is linked so that starting the animation loop with ctx.run()
triggers rendering.
ctx.three.on("mount", (container) => console.log("mount!", container));
ctx.three.on("resize", (width, height) => console.log("resize!", width, height));
ctx.three.on("renderbefore", () => console.log("render!"));
ctx.three.mount(document.querySelector("#canvas-container"));
// >>> "mount!", [HTMLElement]
// >>> "resize!", [number], [number]
// >>> "render!"
ctx.run();
// >>> "render!"
// >>> "render!"
// ... each frame until `stop`
ctx.stop();
All of this (mount/unmount and run/stop) can be called in any order, separately from each other, and as many times as needed.
What is ctx.root
?
The THREE.Object3D
instance that plays the role of entry point of context propagation for objects features aka Object3DFeature
. By default ctx.root
is THREE.Scene
(ctx.root === ctx.three.scene
). You can specify any other root
if you initialize through the constructor.
const grid = new THREE.GridHelper();
ctx.root.add(grid);
class MyFeature extends KVY.Object3DFeature {
useCtx(ctx) {
console.log("ctx was attached", ctx);
return () => console.log("ctx was detached", ctx);
}
}
const feature = KVY.addFeature(grid, MyFeature);
// >>> "ctx was attached", [CoreContext]
ctx.root.remove(grid);
// >>> "ctx was detached", [CoreContext]
For features to work, their objects must be in the hierarchy of ctx.root
.
Read more about this in the API section "Object3DFeatures" under "Context Propagation. Attach and Detach."
What are context modules?
You can read more about modules in the API section CoreContextModule.
There is a wonderful opportunity to extend CoreContext
functionality through pluggable modules (CoreContextModule
). Modules are assigned to ctx
and provide services to features (Object3DFeature
) and enable clean separation of concerns.
class MyModule extends KVY.CoreContextModule {
constructor(label) {
this.label = label;
}
useCtx(ctx) {
console.log(`[${this.label}] assigned to ctx`, ctx)
return () => console.log(`[${this.label}] removed from ctx`, ctx)
}
whoAmI() {
console.log(`I am ${this.label}!`);
}
}
const ctx = KVY.CoreContext.create(THREE, { cucumber: new MyModule("super") });
// >>> "[super] assigned to ctx", [CoreContext]
ctx
.assignModule("tomato", new MyModule("turbo"))
// >>> "[turbo] assigned to ctx", [CoreContext]
.assignModules({ orange: new MyModule("nitro"), apple: new MyModule("mega") });
// >>> "[nitro] assigned to ctx", [CoreContext]
// >>> "[mega] assigned to ctx", [CoreContext]
ctx.modules.cucumber.whoAmI();
// >>> "I am super!"
ctx.modules.tomato.whoAmI();
// >>> "I am turbo!"
ctx.modules.orange.whoAmI();
// >>> "I am nitro!"
ctx.modules.apple.whoAmI();
// >>> "I am mega!"
Assign modules to context
- When initializing
CoreContext
as a dictionary of instances of implementations ofCoreContextModule
. - After initialization through the methods
assignModules
,assignModule
.
Access to context modules
You can access the modules through the dictionary (.modules
)(#modules) where the modules are located by the keys that were specified.
Propagating into features
//TODO: описать вкратце
API
Extends EventEmitter
.
Constructor
new CoreContext( three: ThreeContext, root: Object3D, clock: Clock, modules?: Object )
three
- An instance ofThreeContext
. Utility to manage Three.js setup.modules?
- (optional) Custom dictionary of any your modulesCoreContextModules
.root?
- (optional) An instance of Three.jsObject3D
. The entry point for context propagation. If root is not providen then Three.jsScene
from the givenThreeContext
will be taken as root.
import * as THREE from "three";
import * as KVY from "@vladkrutenyuk/three-kvy-core";
const three = KVY.ThreeContext.create(THREE, { renderer: { antialias: true } })
const modules = {
moduleA: new MyModuleA(),
moduleB: new MyModuleB(),
};
const myCustomRoot = new THREE.Group();
three.scene.add(myCustomRoot);
const ctx = new KVY.CoreContext(three, modules, myCustomRoot);
Static Methods
create( Three: Object, modules?: Object, params?: Object ): CoreContext
Initialization shortcut. Creates and returns a new CoreContext
instance.
Three
- Object containing Three.js class constructorsWebGLRenderer
,Scene
,PerspectiveCamera
,Clock
,Raycaster
. In short, just use importedTHREE
Three.js module.modules
- (optional) Custom dictionary ofCoreContextModule
implementations instances.params
- (optional) Object parametersparams.renderer
- (optional) Object parameters for Three.js WebGLRenderer.
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 } });
Properties
.isCoreContext: Boolean
(readonly) Flag to mark that it is an instance of CoreContext
.
.three: ThreeContext
(readonly) Instance of ThreeContext. Utility to manage Three.js setup.
.root: Object3D
(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.
.modules: Object;
(readonly) Dictionary of assigned modules to this.
.deltaTime: Float
(readonly) The seconds passed since the last frame.
.time: Float
(readonly) The seconds passed since the context loop started (run).
.isCoreContext: Boolean
(readonly) Flag to mark that it is an instance of CoreContext.
.isDestroyed: Boolean
(readonly) Flag to check if this instance is destroyed.
.isRunning: Boolean
(readonly) Flag to check if this instance loop is running.
Methods
.run(): void
Run animation loop and Three.js rendering through. Stoppable as many times as you need by stop()
.
.stop(): void
Stop animation loop and Three.js rendering. Resumable as many times as you need by run()
.
.assignModules( modules: Object ): this
Assigns the given dictionary of modules to this instance. It will be merged with the existing dictionary of modules.
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.
modules
- Dictionary of module instances to assign to this context.
.assignModule( key: String, module: CoreContextModule ): this
Assign module by key to this instance. It will be added to the existing dictionary of modules by the given key.
Note that if the given key is already assigned, it will be skipped, and a warning message will be fired.
key
- The key by which to assign the module to the context in the dictionary.module
- An instance ofCoreContextModule
implementation.
.removeModule( key: String ): this
Remove a module by key that was specified when it was assigned.
key
- key by which a module was assigned.
.findModule( predicate: Function ): CoreContextModule | undefined
.findModuleKey( predicate: Function ): string | undefined
Finds the key of a module in this context using a predicate function.
Returns the key of the first matching instance of CoreContextModule
if found, otherwise undefined
.
predicate
- A predicate function that receives a module instance and returnstrue
if it matches the search criteria.
.destroy(): this
Destroy this instance.
- Sets
.isDestroyed
totrue
permanently. - Stops this animation loop permanently.
- Destroys its
ThreeContext
permanently. - Fires the
"destroy"
event. - Cleans up
.root
from the assigned logic when it was designated asroot
in the given CoreContext. - Removes all assigned modules.
- Removes all listeners from its events.
Events
destroy
Fires when the context has been destroyed.
looprun
Fires when the context loop has been run.
loopstop
Fires when the context loop has been stopped.