import * as RE from 'rogue-engine'; import * as THREE from 'three' import RaycastReceiver from './RaycastReceiver.re'; export default class RaycastReporter extends RE.Component { // @RE.Prop("Select") something; // somethingOptions = ["One", "Two"] mouse: THREE.Vector2 raycaster: THREE.Raycaster updated: boolean @RE.PropList("String") receiverClass = ["RaycastReceiver"] allHovered: Array = [] awake() { } start() { this.mouse = new THREE.Vector2(0, 0) this.raycaster = new THREE.Raycaster() this.updated = false RE.Input.touch.enabled = true } normalizeScreenInput(browserVector, gameVector) { const bounds = RE.Runtime.rogueDOMContainer.getBoundingClientRect(); gameVector.x = ((browserVector.x - bounds.left) / bounds.width) * 2 - 1; gameVector.y = -((browserVector.y - bounds.top) / bounds.height) * 2 + 1 } getMouseInput() { if (!RE.Input.mouse.isMoving) { return } this.normalizeScreenInput(RE.Input.mouse, this.mouse) this.updated = true } getTouchInput() { if (RE.Input.touch.touches.length == 0) { return } this.normalizeScreenInput(RE.Input.touch.touches[0], this.mouse) this.updated = true } update() { this.updated = false this.getMouseInput() this.getTouchInput() if (!this.updated) { return } this.raycaster.setFromCamera(this.mouse, this.object3d as THREE.Camera) let intersects = this.raycaster.intersectObjects(RE.App.currentScene.children) let listeningComponents: Array = [] intersects.forEach(intersect => { let object3d = RE.App.currentScene.getObjectByProperty('uuid', intersect.object.uuid) if (object3d == null) { console.error("Could not find object in current scene") return } let component = this.crawlSceneToFindReceiver(object3d) if (component == null) { return } listeningComponents = listeningComponents.filter((dataThing) => { if (component == null) { return } dataThing.component.object3d.uuid != component.object3d.uuid }) listeningComponents.push(new DataThing(component, intersect)) }) //unhover all previously hovered components for (let i = 0; i < this.allHovered.length; i++) { let dataThing = this.allHovered[i] if (!listeningComponents.includes(dataThing)) { dataThing.component.onMouseOut() } } this.allHovered = [] for (let i = 0; i < listeningComponents.length; i++) { let dataThing = listeningComponents[i] this.allHovered.push(dataThing) if (dataThing.component && dataThing.component.onMouseOver(dataThing.intersect) === false) { break; } } } crawlSceneToFindReceiver(object3d): RaycastReceiver | null { const component = RE.getComponent(RaycastReceiver, object3d) if (component != null) { return component } if (object3d.parent == null) { return null } return this.crawlSceneToFindReceiver(object3d.parent) } } class DataThing { component: RaycastReceiver intersect: THREE.Intersection constructor(component, intersect) { this.component = component this.intersect = intersect } } RE.registerComponent(RaycastReporter);