An event emitted on one class that supports EventDispatcher doesn't get picked up by another class that supports EventDispatcher.
How do I get the communication working app-wide so that I can pass messages around?
At the moment it seems that it only supports passing a message to its own class.
I'm using this boilerplate which gives me three.js and es6:
https://github.com/paulmg/ThreeJS-Webpack-ES6-Boilerplate
I've updated the packages manually to use three.js r97.
I'm looking at the EventDispatcher class and I'm thinking this is a clean way for me to pass messages around the system while keeping it decoupled. For example, I have some HTML UI that watches a checkbox.
Trimmed down to the core example, I have interaction.js:
import {EventDispatcher} from 'three';
// Manages all input interactions
export default class Interaction {
constructor() {
// Add event dispatcher support
Object.assign( this, EventDispatcher.prototype );
// setup the trigger for the event
let outer = this;
$("#" + Config.uiElements.boxOpenStateId).change(function() {
console.log("event emitting");
outer.dispatchEvent( { type: 'boxOpenStateToggled', message: { isChecked: "example" } } );
console.log("event emitted");
});
// setup a event listener
this.addEventListener( 'boxOpenStateToggled', function ( event ) {
console.log("event caught in Interaction.js", event);
});
}
}
And I have boxmanager.js (trimmed down to the core bits):
import {EventDispatcher} from 'three';
export default class BoxManager {
constructor() {
// Add event dispatcher support
Object.assign( this, EventDispatcher.prototype );
}
setupBoxes(manager) {
console.log("adding event listener on BoxManager.js");
this.addEventListener( 'boxOpenStateToggled', function ( event ) {
console.log("event caught by BoxManager.js", event);
} );
}
}
When I trigger the boxOpenStateToggled
event on Interaction
the BoxManager
event listener doesn't capture it.
I get a console log like this:
adding event listener on BoxManager.js
adding event listener on Interaction.js
(I trigger the event)
event emitting
event caught in Interaction.js {type: "boxOpenStateToggled", message: {…}, target: Interaction}
event emitted
What I was expecting here was to see "event caught in BoxManager" as well - is it a system-wide event dispatcher? Or can it only dispatch events internally on a per-class basis?
I wasn't sure if it was the way I was using it with so I have tried:
using the extends
keyword on the class to give the EventDispatcher
functionality and it works but only within the class.
using the .call
version initially which was in an earlier release of three.js.
I can't find any real discussion or examples of using EventDispatcher or see where it is even used in the library.
Have I misunderstood its purpose? Am I using it wrong?
You could consider doing something like this:
const myEventBus = new THREE.EventDispatcher()
const foo = new Foo(myEventBus)
const bar = new Bar(myEventBus)
If you want to avoid passing the instance to objects like this, or making factories, you could do something like this:
//Events.js
const Events = new THREE.EventDispatcher()
export default Events
And then:
//Foo.js
import Events from 'common/Events'
import {BOX_OPEN} from 'Bar'
export default class Foo {
constructor(){
Events.addEventListener( BOX_OPEN, this.onBoxOpen);
}
}
Dispatch
//Bar.js
export const BOX_OPEN = 'box_open'
export default class Bar {
constructor(){
$("#" + Config.uiElements.boxOpenStateId).change(this.onChange);
}
onChange = () => {
console.log("event emitting");
Events.dispatchEvent({ type: BOX_OPEN, message: { isChecked: "example" } });
console.log("event emitted");
}
}