1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00

teardown listeners, object pool, renderer mouse leave event

This commit is contained in:
Sander Moolin 2021-03-25 14:03:28 -04:00
parent c325d47617
commit 2b917a52e6

View File

@ -1,3 +1,4 @@
import { Vector2 } from 'three';
import { watch } from 'vue';
import { bindProp } from '../tools/index.js';
@ -13,7 +14,8 @@ export default {
onPointerEnter: { type: Function, default: null },
onPointerOver: { type: Function, default: null },
onPointerLeave: { type: Function, default: null },
usePointerEvents: { type: Boolean, default: false }
usePointerEvents: { type: Boolean, default: false },
pointerObjects: { type: [Boolean, Array], default: null }
},
data() {
return {
@ -24,6 +26,12 @@ export default {
// setup() {},
unmounted() {
if (this._parent) this._parent.remove(this.o3d);
// teardown listeners
this.three.offBeforeRender(this.pointerHandler);
if (this.three.mouse_move_element) {
this.three.mouse_move_element.removeEventListener('mouseleave', this.renderElementLeaveHandler)
}
},
methods: {
initObject3D(o3d) {
@ -39,7 +47,12 @@ export default {
watch(() => this.lookAt, (v) => { this.o3d.lookAt(v.x, v.y, v.z); }, { deep: true });
if (this.onPointerEnter || this.onPointerOver || this.onPointerLeave) {
this.three.onBeforeRender(this.pointerHandler)
this.three.onBeforeRender(this.pointerHandler);
}
if (this.onPointerLeave) {
// we need to wait a tick so the mouse_move_element is created
// TODO: more robust fix
this.$nextTick(() => this.three.mouse_move_element.addEventListener('mouseleave', this.renderElementLeaveHandler));
}
// find first viable parent
@ -58,19 +71,40 @@ export default {
add(o) { this.o3d.add(o); },
remove(o) { this.o3d.remove(o); },
pointerHandler() {
this.three.raycaster.setFromCamera(this.three.mouse, this.three.camera)
const intersects = this.three.raycaster.intersectObjects([this.o3d])
if (intersects.length) {
// pass single intersection if we only have one, for convenience
const toPass = intersects.length === 1 ? intersects[0] : intersects;
this.three.raycaster.setFromCamera(this.three.mouse, this.three.camera);
// determine what we're raycasting against
let objectsToCastAgainst = this.pointerObjects;
if (objectsToCastAgainst) {
// cast against all objects in scene if prop is `true`
if (objectsToCastAgainst === true) {
objectsToCastAgainst = this.three.scene.children;
}
} else {
// default: just cast against this object
objectsToCastAgainst = [this.o3d];
}
// find all intersects
const intersects = this.three.raycaster.intersectObjects(objectsToCastAgainst);
// determine if the first intersect is this object
const match = intersects.length &&
intersects[0].object.uuid === this.o3d.uuid
? intersects[0]
: null;
// if so, let's start the callback process
if (match) {
// pointer is newly over o3d
if (!this.pointerOver) {
this.pointerOver = true;
if (this.onPointerEnter) {
this.onPointerEnter({ object: this.o3d, intersects: toPass });
this.onPointerEnter({
object: this.o3d,
intersect: match
});
if (this.usePointerEvents) {
this.$emit('pointerEnter', toPass);
@ -79,7 +113,10 @@ export default {
}
// pointer is still over o3d
else if (this.onPointerOver) {
this.onPointerOver({ object: this.o3d, intersects: toPass });
this.onPointerOver({
object: this.o3d,
intersect: match
});
if (this.usePointerEvents) {
this.$emit('pointerOver', toPass);
@ -100,6 +137,12 @@ export default {
}
}
}
},
renderElementLeaveHandler() {
// since the mouse is off the renderer, we'll set its values to an unreachable number
this.three.mouse.x = this.three.mouse.y = Infinity;
// then run the normal pointer handler with these updated mouse values
this.pointerHandler();
}
},
render() {