54 lines
1.8 KiB
JavaScript
54 lines
1.8 KiB
JavaScript
import { Raycaster, Vector3 } from "three"
|
|
|
|
class Clickable {
|
|
constructor(defaultDistance) {
|
|
const objects = [];
|
|
const raycaster = new Raycaster();
|
|
let v = new Vector3;
|
|
|
|
this.add = function (object, fn, distance) {
|
|
objects.push(object);
|
|
object._clickable = { fn, distance: distance || defaultDistance };
|
|
};
|
|
|
|
this.remove = function (object) {
|
|
objects.splice(objects.indexOf(object), 1);
|
|
delete object._clickable;
|
|
};
|
|
|
|
this.removeAll = function(){
|
|
objects.forEach(o=>delete o._clickable)
|
|
objects.splice(0, objects.length);
|
|
}
|
|
|
|
this.update = function (mouse, camera, event) {
|
|
raycaster.setFromCamera(mouse, camera);
|
|
let forExecute = [];
|
|
objects.filter(o=>{
|
|
do {
|
|
if (o.__active === false) return false;
|
|
o = o.parent;
|
|
} while (o);
|
|
return true;
|
|
}).forEach(o => {
|
|
o.getWorldPosition(v);
|
|
if (camera.position.distanceTo(v) <= o._clickable.distance && o.visible) {
|
|
const intersects = raycaster.intersectObject(o);
|
|
// intersects.forEach(i=>{
|
|
// forExecute.push({o, i})
|
|
// })
|
|
if (intersects[0]) forExecute.push({ o, i: intersects[0] });
|
|
}
|
|
});
|
|
if (forExecute[0]) {
|
|
let sorted = forExecute.sort((a, b) => a.i.distance - b.i.distance);
|
|
sorted[0].o._clickable.fn(sorted[0].i);
|
|
if (this.onclick) {
|
|
this.onclick(sorted[0].o, sorted[0].i, event);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
export {Clickable} |