UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

133 lines (132 loc) 4.79 kB
"use strict"; import { TypedNode } from "../_Base"; import { NodeContext } from "../../poly/NodeContext"; import { pushOnArrayAtEntry } from "../../../core/MapUtils"; import { Poly } from "../../Poly"; export class TypedEventNode extends TypedNode { constructor() { super(...arguments); // ensures that event nodes are cooked when scene is loaded // private _eval_all_params_on_dirty_bound = this._eval_all_params_on_dirty.bind(this); // _eval_all_params_on_dirty() { // this.params.eval_all(); // } this._cookWithoutInputsBound = this._cookWithoutInputs.bind(this); } static context() { return NodeContext.EVENT; } initializeBaseNode() { this.uiData.setLayoutHorizontal(); this.addPostDirtyHook("cookWithoutInputsOnDirty", this._cookWithoutInputsBound); this.io.inputs.setDependsOnInputs(false); this.io.connections.initInputs(); this.io.connection_points.spare_params.initializeNode(); } _cookWithoutInputs() { this.cookController.cookMainWithoutInputs(); } cook() { this.cookController.endCook(); } // eval_params_and_processEvent(event_context: EventContext<Event>, connection_point: BaseEventConnectionPoint) { // // not evaluation params now, since we are evaluating them on dirty // // this.params.eval_all().then(()=>{ // this.processEvent(event_context, connection_point) // // }) // } processEventViaConnectionPoint(eventContext, connectionPoint) { if (connectionPoint.event_listener) { connectionPoint.event_listener(eventContext); } else { this.processEvent(eventContext); } } processEvent(event_context) { } // // // It may be more practical to use cook, rather than process_event // to benefit from params evaluation. // But that would mean that each node receiving an event would make the successors dirty, // which may also be problematic. So for now, I use process_event // // async dispatchEventToOutput(output_name, event_context) { this.run_on_dispatch_hook(output_name, event_context); const index = this.io.outputs.getOutputIndex(output_name); if (index >= 0) { const outputConnections = this.io.connections.outputConnectionsByOutputIndex(index); if (outputConnections) { let destNode; if (!Poly.playerMode()) { const dispatcher = this.scene().eventsDispatcher.connectionTriggerDispatcher; outputConnections.forEach((connection) => { dispatcher.dispatchTrigger(connection); }); } outputConnections.forEach((connection) => { destNode = connection.nodeDest(); const destNodeConnectionPoints = destNode.io.inputs.namedInputConnectionPoints(); if (destNodeConnectionPoints) { const connection_point = destNodeConnectionPoints[connection.inputIndex()]; destNode.processEventViaConnectionPoint(event_context, connection_point); } }); } } else { console.warn(`requested output '${output_name}' does not exist on node '${this.path()}'`); } } /** * onDispatch is called when an output triggers an event. * * Here is an example usage to listen to events: * * ``` ts *let _currentState = false; *function setHit( newState ){ * if( _currentState != newState ){ * if( newState ){ * playSound(); * } * _currentState = newState; * } *} * *const raycastNode = scene.node('<path to the node>'); *raycastNode.onDispatch('hit', ()=>setHit(true) ); *raycastNode.onDispatch('miss', ()=>setHit(false) ); * ``` * * Alternatively, you can also have the following arguments from the callback * * - viewer: the [viewer](https://polygonjs.com/docs/api/TypedViewer) displaying the scene. * - event: the mouse/pointer/keyboard event that originally triggered the event * - emitter: the domElement the event was triggered from (either the canvas or the document) * - value: an optional value linked to the event. * * ``` ts *raycastNode.onDispatch('hit',(eventContext)=>{ * const {viewer, event, emitter, value} = eventContext; *}); * ``` * */ onDispatch(outputName, callback) { this._on_dispatch_hooks_by_output_name = this._on_dispatch_hooks_by_output_name || /* @__PURE__ */ new Map(); pushOnArrayAtEntry(this._on_dispatch_hooks_by_output_name, outputName, callback); } run_on_dispatch_hook(output_name, event_context) { if (this._on_dispatch_hooks_by_output_name) { const hooks = this._on_dispatch_hooks_by_output_name.get(output_name); if (hooks) { for (const hook of hooks) { hook(event_context); } } } } } export class BaseEventNodeClass extends TypedEventNode { }