Accueil / npm / three@0.186.1 / src / nodes / utils / EventNode.js

EventNode.js

import Node from '../core/Node.js';
import { NodeUpdateType } from '../core/constants.js';

/**
 * EventNode is a node that executes a callback during specific update phases.
 *
 * @augments Node
 */
class EventNode extends Node {

	static get type() {

		return 'EventNode';

	}

	/**
	 * Creates an EventNode.
	 *
	 * @param {string} eventType - The type of event
	 * @param {Function} callback - The callback to execute on update.
	 */
	constructor( eventType, callback ) {

		super( 'void' );

		this.eventType = eventType;
		this.callback = callback;

		if ( eventType === EventNode.OBJECT ) {

			this.updateType = NodeUpdateType.OBJECT;

		} else if ( eventType === EventNode.MATERIAL ) {

			this.updateType = NodeUpdateType.RENDER;

		} else if ( eventType === EventNode.FRAME ) {

			this.updateType = NodeUpdateType.FRAME;

		} else if ( eventType === EventNode.AFTER_OBJECT ) {

			this.updateAfterType = NodeUpdateType.OBJECT;

		} else if ( eventType === EventNode.BEFORE_OBJECT ) {

			this.updateBeforeType = NodeUpdateType.OBJECT;

		} else if ( eventType === EventNode.BEFORE_MATERIAL ) {

			this.updateBeforeType = NodeUpdateType.RENDER;

		} else if ( eventType === EventNode.BEFORE_FRAME ) {

			this.updateBeforeType = NodeUpdateType.FRAME;

		}

	}

	setup( builder ) {

		const { eventType, callback } = this;

		if ( eventType === EventNode.BEFORE_RENDER_PIPELINE ) {

			const callbacks = builder.context.onBeforePipelineCallbacks;

			if ( callbacks ) {

				callbacks.push( callback );

			}

		} else if ( eventType === EventNode.AFTER_RENDER_PIPELINE ) {

			const callbacks = builder.context.onAfterPipelineCallbacks;

			if ( callbacks ) {

				callbacks.push( callback );

			}

		}

		return super.setup( builder );

	}

	update( frame ) {

		this.callback( frame );

	}

	updateBefore( frame ) {

		this.callback( frame );

	}

	updateAfter( frame ) {

		this.callback( frame );

	}

}

EventNode.OBJECT = 'object';
EventNode.MATERIAL = 'material';
EventNode.FRAME = 'frame';
EventNode.AFTER_OBJECT = 'afterObject';
EventNode.BEFORE_OBJECT = 'beforeObject';
EventNode.BEFORE_MATERIAL = 'beforeMaterial';
EventNode.BEFORE_FRAME = 'beforeFrame';
EventNode.BEFORE_RENDER_PIPELINE = 'beforeRenderPipeline';
EventNode.AFTER_RENDER_PIPELINE = 'afterRenderPipeline';

export default EventNode;

/**
 * Helper to create an EventNode and add it to the stack.
 *
 * @param {string} type - The event type.
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
const createEvent = ( type, callback ) => new EventNode( type, callback ).toStack();

/**
 * Creates an event that triggers a function every time an object (Mesh|Sprite) is rendered.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnObjectUpdate = ( callback ) => createEvent( EventNode.OBJECT, callback );

/**
 * Creates an event that triggers a function when the first object that uses the material is rendered.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnMaterialUpdate = ( callback ) => createEvent( EventNode.MATERIAL, callback );

/**
 * Creates an event that triggers a function every frame.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnFrameUpdate = ( callback ) => createEvent( EventNode.FRAME, callback );

/**
 * Creates an event that triggers a function every time an object (Mesh|Sprite) has been rendered.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnAfterObjectUpdate = ( callback ) => createEvent( EventNode.AFTER_OBJECT, callback );

/**
 * Creates an event that triggers a function before an object (Mesh|Sprite) is updated.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnBeforeObjectUpdate = ( callback ) => createEvent( EventNode.BEFORE_OBJECT, callback );

/**
 * Creates an event that triggers a function before the material is updated.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnBeforeMaterialUpdate = ( callback ) => createEvent( EventNode.BEFORE_MATERIAL, callback );

/**
 * Creates an event that triggers a function before every frame.
 *
 * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnBeforeFrameUpdate = ( callback ) => createEvent( EventNode.BEFORE_FRAME, callback );

/**
 * Creates an event that triggers a function before the render pipeline is rendered.
 *
 * The node must be part of a node chain that is used as the output of a `RenderPipeline`,
 * otherwise the event is ignored.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnBeforeRenderPipeline = ( callback ) => createEvent( EventNode.BEFORE_RENDER_PIPELINE, callback );

/**
 * Creates an event that triggers a function after the render pipeline is rendered.
 *
 * The node must be part of a node chain that is used as the output of a `RenderPipeline`,
 * otherwise the event is ignored.
 *
 * @param {Function} callback - The callback function.
 * @returns {EventNode}
 */
export const OnAfterRenderPipeline = ( callback ) => createEvent( EventNode.AFTER_RENDER_PIPELINE, callback );