UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

70 lines (57 loc) 2.54 kB
import { Object3D } from "three"; import { foreachComponent } from "../../engine/engine_gameobject.js"; import { type IComponent } from "../../engine/engine_types.js"; import { type ICanvasGroup, type IGraphic } from "./Interfaces.js"; import { $shadowDomOwner } from "./Symbols.js"; export class UIRaycastUtils { /** returns the real object when dealing with shadow UI */ static getObject(obj: Object3D): Object3D { const shadowOwner = obj[$shadowDomOwner]; if(shadowOwner) { if((shadowOwner as IComponent).isComponent === true) obj = (shadowOwner as IComponent).gameObject; else obj = shadowOwner; } return obj; }; static isInteractable(obj: Object3D, out?: { canvasGroup?: ICanvasGroup, graphic?: IGraphic }): boolean { // reset state if (out) { out.canvasGroup = undefined; out.graphic = undefined; } if (obj === null || obj === undefined || !obj.visible) return false; obj = this.getObject(obj); if(!obj.visible) return false; const canvasGroup = this.tryFindCanvasGroup(obj); if (canvasGroup?.isCanvasGroup === true) { if (out) out.canvasGroup = canvasGroup as ICanvasGroup; if (canvasGroup.blocksRaycasts === false) return false; if (canvasGroup.interactable === false) return false; } // handle Graphic Raycast target const graphic : IGraphic | undefined = foreachComponent(obj, c => { if ((c as unknown as IGraphic).isGraphic === true) return c; return undefined; }, false); // console.log(obj, graphic?.raycastTarget); if (out) { if (graphic?.isGraphic === true) out.graphic = graphic as IGraphic; } if (graphic?.raycastTarget === false) return false; if (graphic?.layer === 2) return false; return true; } private static tryFindCanvasGroup(obj: Object3D | null): ICanvasGroup | null { if (!obj) return null; // test for canvas groups const res = foreachComponent(obj, c => { const gr = c as unknown as ICanvasGroup; if (gr.blocksRaycasts !== undefined && gr.interactable !== undefined) return gr; return undefined; }, false); if (res !== undefined) return res; return this.tryFindCanvasGroup(obj.parent); } }