62 lines
2.5 KiB
JavaScript
62 lines
2.5 KiB
JavaScript
import { Raycaster, Vector3 } from "three"
|
|
|
|
class Draggable{
|
|
constructor(engine, defaultDistance){
|
|
const objects = [];
|
|
const raycaster = new Raycaster();
|
|
let v = new Vector3;
|
|
let dragging = null;
|
|
this.add = function(object, dragZone, fn, distance){
|
|
objects.push(object);
|
|
object._draggable = {fn, dragZone, distance: distance || defaultDistance}
|
|
}
|
|
|
|
this.remove = function(object){
|
|
delete object._draggable;
|
|
objects.splice(objects.indexOf(object), 1);
|
|
}
|
|
|
|
this.handleController = function(controller, action){
|
|
raycaster.setFromXRController(controller);
|
|
this.handle(action);
|
|
}
|
|
|
|
this.handleMouse = function (mouse, action) {
|
|
raycaster.setFromCamera(mouse, engine.camera);
|
|
this.handle(action);
|
|
};
|
|
|
|
this.handle = function(action){
|
|
if (['start', 'selectstart'].includes(action)){
|
|
let forExecute = [];
|
|
objects.forEach(o=>{
|
|
o.getWorldPosition(v);
|
|
if (engine.cameraWorld.position.distanceTo(v) <= o._draggable.distance && o.visible){
|
|
const intersects = raycaster.intersectObject(o);
|
|
if (intersects[0]) forExecute.push({o, i:intersects[0]})
|
|
}
|
|
});
|
|
|
|
if (forExecute[0]) {
|
|
let s = forExecute.sort((a,b)=>a.i.distance-b.i.distance)[0];
|
|
s.o._draggable.fn.start && s.o._draggable.fn.start(s.i);
|
|
dragging = s;
|
|
dragging.zone = raycaster.intersectObject(s.o._draggable.dragZone)[0];
|
|
}
|
|
}else if (['end', 'selectend'].includes(action) && dragging){
|
|
dragging.o._draggable.fn.end && dragging.o._draggable.fn.end(dragging);
|
|
dragging = null;
|
|
}else if(['drag', 'move'].includes(action) && dragging){
|
|
const intersect = raycaster.intersectObject(dragging.o._draggable.dragZone)[0];
|
|
if (intersect?.uv && dragging.zone?.uv){
|
|
dragging.o.position.x += -4*(dragging.zone.uv.x - intersect.uv.x);
|
|
dragging.o.position.y += 4*(dragging.zone.uv.y - intersect.uv.y);
|
|
dragging.o._draggable.fn.drag && dragging.o._draggable.fn.drag(dragging);
|
|
dragging.zone = intersect;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export { Draggable } |