RaycastReporter.re.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import * as RE from 'rogue-engine';
  2. import * as THREE from 'three'
  3. import RaycastReceiver from './RaycastReceiver.re';
  4. export default class RaycastReporter extends RE.Component {
  5. // @RE.Prop("Select") something;
  6. // somethingOptions = ["One", "Two"]
  7. mouse: THREE.Vector2
  8. raycaster: THREE.Raycaster
  9. updated: boolean
  10. @RE.PropList("String") receiverClass = ["RaycastReceiver"]
  11. allHovered: Array<DataThing> = []
  12. awake() {
  13. }
  14. start() {
  15. this.mouse = new THREE.Vector2(0, 0)
  16. this.raycaster = new THREE.Raycaster()
  17. this.updated = false
  18. RE.Input.touch.enabled = true
  19. }
  20. normalizeScreenInput(browserVector, gameVector) {
  21. const bounds = RE.Runtime.rogueDOMContainer.getBoundingClientRect();
  22. gameVector.x = ((browserVector.x - bounds.left) / bounds.width) * 2 - 1;
  23. gameVector.y = -((browserVector.y - bounds.top) / bounds.height) * 2 + 1
  24. }
  25. getMouseInput() {
  26. if (!RE.Input.mouse.isMoving) {
  27. return
  28. }
  29. this.normalizeScreenInput(RE.Input.mouse, this.mouse)
  30. this.updated = true
  31. }
  32. getTouchInput() {
  33. if (RE.Input.touch.touches.length == 0) {
  34. return
  35. }
  36. this.normalizeScreenInput(RE.Input.touch.touches[0], this.mouse)
  37. this.updated = true
  38. }
  39. update() {
  40. this.updated = false
  41. this.getMouseInput()
  42. this.getTouchInput()
  43. if (!this.updated) {
  44. return
  45. }
  46. this.raycaster.setFromCamera(this.mouse, this.object3d as THREE.Camera)
  47. let intersects = this.raycaster.intersectObjects(RE.App.currentScene.children)
  48. let listeningComponents: Array<DataThing> = []
  49. intersects.forEach(intersect => {
  50. let object3d = RE.App.currentScene.getObjectByProperty('uuid', intersect.object.uuid)
  51. if (object3d == null) {
  52. console.error("Could not find object in current scene")
  53. return
  54. }
  55. let component = this.crawlSceneToFindReceiver(object3d)
  56. if (component == null) {
  57. return
  58. }
  59. listeningComponents = listeningComponents.filter((dataThing) => {
  60. if (component == null) {
  61. return
  62. }
  63. dataThing.component.object3d.uuid != component.object3d.uuid
  64. })
  65. listeningComponents.push(new DataThing(component, intersect))
  66. })
  67. //unhover all previously hovered components
  68. for (let i = 0; i < this.allHovered.length; i++) {
  69. let dataThing = this.allHovered[i]
  70. if (!listeningComponents.includes(dataThing)) {
  71. dataThing.component.onMouseOut()
  72. }
  73. }
  74. this.allHovered = []
  75. for (let i = 0; i < listeningComponents.length; i++) {
  76. let dataThing = listeningComponents[i]
  77. this.allHovered.push(dataThing)
  78. if (dataThing.component && dataThing.component.onMouseOver(dataThing.intersect) === false) {
  79. break;
  80. }
  81. }
  82. }
  83. crawlSceneToFindReceiver(object3d): RaycastReceiver | null {
  84. const component = RE.getComponent(RaycastReceiver, object3d)
  85. if (component != null) {
  86. return component
  87. }
  88. if (object3d.parent == null) {
  89. return null
  90. }
  91. return this.crawlSceneToFindReceiver(object3d.parent)
  92. }
  93. }
  94. class DataThing {
  95. component: RaycastReceiver
  96. intersect: THREE.Intersection
  97. constructor(component, intersect) {
  98. this.component = component
  99. this.intersect = intersect
  100. }
  101. }
  102. RE.registerComponent(RaycastReporter);