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.

148 lines (123 loc) 4.16 kB
import { serializable } from "../../engine/engine_serialization_decorator.js"; import { getParam } from "../../engine/engine_utils.js"; import { Behaviour, GameObject } from "../Component.js"; const debug = getParam("debugxrflags"); const disable = getParam("disablexrflags"); if (disable) { console.warn("XRFlags are disabled") } export enum XRStateFlag { Never = 0, Browser = 1 << 0, AR = 1 << 1, VR = 1 << 2, FirstPerson = 1 << 3, ThirdPerson = 1 << 4, All = 0xffffffff } export class XRState { public static Global: XRState = new XRState(); public Mask: XRStateFlag = XRStateFlag.Browser | XRStateFlag.ThirdPerson; public Has(state: XRStateFlag) { const res = (this.Mask & state); return res !== 0; } public Set(state: number) { if (debug) console.warn("Set XR flag state to", state) this.Mask = state as number; XRFlag.Apply(); } public Enable(state: number) { this.Mask |= state; XRFlag.Apply(); } public Disable(state: number) { this.Mask &= ~state; XRFlag.Apply(); } public Toggle(state: number) { this.Mask ^= state; XRFlag.Apply(); } public EnableAll() { this.Mask = 0xffffffff | 0; XRFlag.Apply(); } public DisableAll() { this.Mask = 0; XRFlag.Apply(); } } /** * @category XR * @category Utilities * @group Components */ export class XRFlag extends Behaviour { private static registry: XRFlag[] = []; public static Apply() { for (const r of this.registry) r.UpdateVisible(XRState.Global); } private static firstApply: boolean; private static buffer: XRState = new XRState(); @serializable() public visibleIn!: number; awake() { XRFlag.registry.push(this); } onEnable(): void { if (!XRFlag.firstApply) { XRFlag.firstApply = true; XRFlag.Apply(); } else { this.UpdateVisible(XRState.Global); } } onDestroy(): void { const i = XRFlag.registry.indexOf(this); if (i >= 0) XRFlag.registry.splice(i, 1); } public get isOn(): boolean { return this.gameObject.visible; } public UpdateVisible(state: XRState | XRStateFlag | null = null) { if (disable) { return; } // XR flags set visibility of whole hierarchy which is like setting the whole object inactive // so we need to ignore the enabled state of the XRFlag component // if(!this.enabled) return; let res: boolean | undefined = undefined; const flag = state as number; if (flag && typeof flag === "number") { console.assert(typeof flag === "number", "XRFlag.UpdateVisible: state must be a number", flag); if (debug) console.log(flag); XRFlag.buffer.Mask = flag; state = XRFlag.buffer; } if (state instanceof XRState) { if (debug) console.warn(this.name, "use passed in mask", state.Mask, this.visibleIn) res = state.Has(this.visibleIn); } else { if (debug) console.log(this.name, "use global mask") XRState.Global.Has(this.visibleIn); } if (res === undefined) return; if (res) { if (debug) console.log(this.name, "is visible", this.gameObject.uuid) // this.gameObject.visible = true; GameObject.setActive(this.gameObject, true); } else { if (debug) console.log(this.name, "is not visible", this.gameObject.uuid); const isVisible = this.gameObject.visible; if (!isVisible) return; this.gameObject.visible = false; // console.trace("DISABLE", this.name); // GameObject.setActive(this.gameObject, false); } } }