@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
197 lines (185 loc) • 7.66 kB
text/typescript
import {Constructor} from '../../../../types/GlobalTypes';
import {PolyScene} from '../../PolyScene';
import {BaseEventNodeType} from '../../../nodes/event/_Base';
import {BaseInputEventNodeType} from '../../../nodes/event/_BaseInput';
import {BaseSceneEventsController, BaseSceneEventsControllerClass} from './_BaseEventsController';
import {SceneEventsController} from './SceneEventsController';
import {DragEventsController} from './DragEventsController';
import {KeyboardEventsController} from './KeyboardEventsController';
import {MouseEventsController} from './MouseEventsController';
import {PointerEventsController} from './PointerEventsController';
import {WindowEventsController} from './WindowEventsController';
import {TouchEventsController} from './TouchEventsController';
import {SceneConnectionTriggerDispatcher} from './ConnectionTriggerDispatcher';
import {EventInputType} from '../../../poly/registers/nodes/types/Event';
// import {BaseUserInputJsNodeType} from '../../../nodes/js/_BaseUserInput';
// import {JsType} from '../../../poly/registers/nodes/types/Js';
import {Raycaster} from 'three';
import {ActorEvaluatorGenerator} from '../../../nodes/js/code/assemblers/actor/ActorEvaluatorGenerator';
import {JsType} from '../../../poly/registers/nodes/types/Js';
export class SceneEventsDispatcher {
private _controllers: BaseSceneEventsController<Event, BaseInputEventNodeType>[] = [];
public readonly sceneEventsController = new SceneEventsController();
private _keyboardEventsController?: KeyboardEventsController;
private _mouseEventsController?: MouseEventsController;
private _dragEventsController?: DragEventsController;
private _windowEventsController?: WindowEventsController;
private _touchEventsController?: TouchEventsController;
public readonly pointerEventsController: PointerEventsController = this._createController(PointerEventsController);
constructor(public scene: PolyScene) {}
registerEvaluatorGenerator(evaluatorGenerator: ActorEvaluatorGenerator) {
const controllers = this._findOrCreateControllerForEvaluator(evaluatorGenerator);
if (controllers) {
controllers.forEach((c) => c.registerEvaluatorGenerator(evaluatorGenerator));
}
}
unregisterEvaluatorGenerator(evaluatorGenerator: ActorEvaluatorGenerator) {
const controllers = this._findOrCreateControllerForEvaluator(evaluatorGenerator);
if (controllers) {
controllers.forEach((c) => c.unregisterEvaluatorGenerator(evaluatorGenerator));
}
}
// updateControllersFromJsNodes() {
// const eventDatas = this.scene.actorsManager.eventDatas();
// eventDatas.forEach((type) => {
// this._findOrCreateControllerForEventInputType(type);
// });
// }
registerEventNode(node: BaseInputEventNodeType) {
const controller = this._findOrCreateControllerForEventNode(node);
if (controller) {
controller.registerEventNode(node);
}
}
unregisterEventNode(node: BaseInputEventNodeType) {
const controller = this._findOrCreateControllerForEventNode(node);
if (controller) {
controller.unregisterEventNode(node);
}
}
updateViewerEventListeners(node: BaseInputEventNodeType) {
const controller = this._findOrCreateControllerForEventNode(node);
if (controller) {
controller.updateViewerEventListeners();
}
}
traverseControllers(callback: (controller: BaseSceneEventsController<Event, BaseInputEventNodeType>) => void) {
for (const controller of this._controllers) {
callback(controller);
}
}
setRaycaster(raycaster: Raycaster) {
// giving a raycaster here is useful to still benefit from mouse events, even if not viewer has been created
this.pointerEventsController.setRaycaster(raycaster);
}
// processEvent(event_content: EventContext<Event>) {
// if (!event_content.event) {
// return;
// }
// for (let controller of this._controllers) {
// if (controller.accepts_event(event_content.event)) {
// controller.processEvent(event_content);
// return;
// }
// }
// }
private _findOrCreateControllerForEventNode<T extends BaseEventNodeType>(
node: T
): BaseSceneEventsController<Event, BaseInputEventNodeType> | undefined {
return this._findOrCreateControllerForEventInputType(node.type() as EventInputType);
}
private _findOrCreateControllerForEvaluator(
evaluator: ActorEvaluatorGenerator
): Set<BaseSceneEventsController<Event, BaseInputEventNodeType>> | undefined {
const eventDatas = evaluator.eventDatas;
if (!eventDatas) {
return;
}
const controllers: Set<BaseSceneEventsController<Event, BaseInputEventNodeType>> = new Set();
eventDatas.forEach((eventData) => {
const controller = this._findOrCreateControllerForJsType(eventData.jsType);
if (controller) {
controllers.add(controller);
}
});
return controllers;
}
private _findOrCreateControllerForEventInputType(
type: EventInputType
): BaseSceneEventsController<Event, BaseInputEventNodeType> | undefined {
switch (type) {
case EventInputType.KEYBOARD:
return this.keyboardEventsController;
case EventInputType.MOUSE:
return this.mouseEventsController;
case EventInputType.DRAG:
return this.dragEventsController;
case EventInputType.POINTER:
return this.pointerEventsController;
case EventInputType.TOUCH:
return this.touchEventsController;
case EventInputType.WINDOW:
return this.windowEventsController;
}
}
private _findOrCreateControllerForJsType(
jsType: JsType
): BaseSceneEventsController<Event, BaseInputEventNodeType> | undefined {
switch (jsType) {
case JsType.CURSOR:
case JsType.ON_OBJECT_CLICK:
case JsType.ON_OBJECT_CONTEXT_MENU:
case JsType.ON_OBJECT_HOVER:
case JsType.ON_OBJECT_LONG_PRESS:
case JsType.ON_OBJECT_MOUSE_CLICK:
case JsType.ON_OBJECT_POINTERDOWN:
case JsType.ON_OBJECT_POINTERUP:
case JsType.ON_POINTERDOWN:
case JsType.ON_POINTERUP:
case JsType.RAY_FROM_CURSOR:
return this.pointerEventsController;
case JsType.ON_KEY:
case JsType.ON_KEYDOWN:
case JsType.ON_KEYPRESS:
case JsType.ON_KEYUP:
return this.keyboardEventsController;
}
console.warn(`no event controller defined for jsType`, jsType);
}
get keyboardEventsController() {
return (this._keyboardEventsController =
this._keyboardEventsController || this._createController(KeyboardEventsController));
}
get mouseEventsController() {
return (this._mouseEventsController =
this._mouseEventsController || this._createController(MouseEventsController));
}
get dragEventsController() {
return (this._dragEventsController =
this._dragEventsController || this._createController(DragEventsController));
}
// get pointerEventsController(): PointerEventsController {
// return (this._pointerEventsController =
// this._pointerEventsController || this._createController(PointerEventsController));
// }
get windowEventsController() {
return (this._windowEventsController =
this._windowEventsController || this._createController(WindowEventsController));
}
get touchEventsController() {
return (this._touchEventsController =
this._touchEventsController || this._createController(TouchEventsController));
}
private _createController<T extends BaseSceneEventsControllerClass>(eventConstructor: Constructor<T>): T {
const controller = new eventConstructor(this);
if (!this._controllers.includes(controller)) {
this._controllers.push(controller);
}
return controller;
}
private _connectionTriggerDispatcher: SceneConnectionTriggerDispatcher | undefined;
get connectionTriggerDispatcher() {
return (this._connectionTriggerDispatcher =
this._connectionTriggerDispatcher || new SceneConnectionTriggerDispatcher());
}
}