js/Mobilizing/renderer/3D/three/ui/Clickable.js
import Component from "../../../../core/Component";
import Pointer from "../../../../input/Pointer";
import Mouse from "../../../../input/Mouse";
import Touch from "../../../../input/Touch";
export default class Clickable extends Component {
/**
Makes a Mesh clickable
*
@param {Object} params Parameters object, given by the constructor.
@param {Pointer} params.pointer a Pointer input object to use for the interaction. If none provided, a Pointer is created internally by this class, but it needs a canvas reference (i.e the canvas uses by the renderer)
@param {Camera} params.camera the camera used in the scene to compute the pick on the mesh
@param {Mesh} params.mesh the target mesh to make clickable
@param {Canvas} params.canvas the canvas to use for the Pointer input to work (i.e the canvas uses by the renderer)
@param {Boolean} params.continuous set the hover (enter) behavious continuous (i.e not only once on the mesh entering, but at each pointer's move)
@param {onPress} params.onPress onPress Handler
@param {onRelease} params.onRelease onRelease Handler
@param {continuous} params.continuous defines if the events triggered by this clickable should be conituous (every frame) or not (on event only)
@param {onEnter} params.onEnter Handler
@param {onLeave} params.onLeave Handler
*/
constructor({
camera = undefined,
mesh = undefined,
canvas = undefined,
pointer = undefined,
continuous = false,
onPress = undefined,
onRelease = undefined,
onEnter = undefined,
onLeave = undefined,
} = {}) {
super(...arguments);
this.camera = camera;
this.mesh = mesh;
this.canvas = canvas;
this.pointer = pointer;
this.continuous = continuous;
this.onPress = onPress;
this.onRelease = onRelease;
this.onEnter = onEnter;
this.onLeave = onLeave;
this.picked = false;
this.hovered = false;
}
/**
* Setup for this clickable instance
*
* @method setup
*/
setup() {
super.setup();
//No pointer given, build it
if (this.pointer === undefined) {
const mouse = new Mouse({ "target": this.canvas });
this.context.addComponent(mouse);
mouse.setup();
mouse.on();
const touch = new Touch({ "target": this.canvas });
this.context.addComponent(touch);
touch.setup();
touch.on();
this.pointer = new Pointer();
this.pointer.add(mouse);
this.pointer.add(touch);
this.context.addComponent(this.pointer);
this.pointer.setup();
this.pointer.on();
//console.log(mouse,context);
}
this.pointer.events.on("on", (event) => {
const pick = this.mesh.transform.pick(this.camera, event.x, event.y);
if (pick) {
this.picked = true;
if (this.onPress) {
this.onPress(pick);
}
}
else {
this.picked = false;
}
});
this.pointer.events.on("off", (event) => {
const pick = this.mesh.transform.pick(this.camera, event.x, event.y);
if (this.picked === true) {
if (this.onRelease) {
this.onRelease(pick);
}
}
});
this.pointer.events.on("moved", (event) => {
const pick = this.mesh.transform.pick(this.camera, event.x, event.y);
if (pick) {
this.picked = true;
if (!this.continuous) {
if (!this.hovered) {
if (this.onEnter) {
this.onEnter(pick);
}
}
}
else {
if (this.onEnter) {
this.onEnter(pick);
}
}
this.hovered = true;
}
else {
//avoid useless recall
if (this.picked) {
if (this.onLeave) {
this.onLeave();
}
this.hovered = false;
this.picked = false;
}
}
});
}
}