@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.
1,382 lines (1,371 loc) • 1.92 MB
JavaScript
import { createLoaders as Cg, LODsManager as nr, NEEDLE_progressive as Ge, getRaycastMesh as Jv, setKTX2TranscoderLocation as zS, setDracoDecoderLocation as US, addDracoAndKTX2Loaders as NS, configureLoader as $S } from "./gltf-progressive-DUlhxdv4.js";
import { Vector2 as Z, Vector3 as v, Vector4 as ye, Quaternion as N, Box3 as si, ShadowMaterial as e0, Euler as He, PlaneGeometry as Tn, WebGLRenderer as Vr, PerspectiveCamera as de, OrthographicCamera as Du, Scene as ji, Mesh as G, Texture as Se, Uniform$1 as en, Color as oe, ShaderMaterial as es, MeshStandardMaterial as bt, Box3Helper as WS, GridHelper as t0, Object3D as M, Material as be, Matrix3 as i0, Matrix4 as J, Layers as Eo, PropertyBinding as Va, AnimationClip as Vt, KeyframeTrack as VS, FileLoader as n0, BufferGeometry as nn, TextureLoader as Ar, MeshBasicMaterial as Ce, DoubleSide as Bi, Group as Ms, CylinderGeometry as s0, SphereGeometry as ju, BoxGeometry as Ga, SpriteMaterial as GS, Sprite as HS, Shape as qS, ExtrudeGeometry as XS, Ray as Bs, CubeUVReflectionMapping as kn, LinearSRGBColorSpace as Fs, ShaderChunk as ii, Sphere as Bu, DataTexture as Pg, RGBAFormat as Fu, EquirectangularReflectionMapping as Rs, SRGBColorSpace as zs, Clock as QS, NeutralToneMapping as Ha, AgXToneMapping as zu, ACESFilmicToneMapping as Uu, NoToneMapping as Yd, AxesHelper as Di, MathUtils as As, Fog as o0, DirectionalLight as am, PointLight as kg, PCFSoftShadowMap$1 as YS, BasicNodeLibrary as KS, WebGLRenderTarget as ts, DepthTexture as r0, NearestFilter as Kd, EdgesGeometry as ZS, LineSegments as lm, LineBasicMaterial as Zd, Line as qa, BufferAttribute as st, Raycaster as Nu, ArrayCamera as JS, Plane as Ir, SkinnedMesh as So, InterleavedBufferAttribute as a0, Skeleton as e1, Bone as t1, WebGLCubeRenderTarget as i1, CubeCamera as n1, LoopRepeat as s1, LoopOnce as cm, AnimationMixer as Og, InterpolateLinear as o1, InterpolateDiscrete as r1, InterpolateSmooth as a1, QuaternionKeyframeTrack as sc, BooleanKeyframeTrack as m_, VectorKeyframeTrack as oc, ColorKeyframeTrack as g_, NumberKeyframeTrack as Xf, AudioContext as l1, CompressedTexture as c1, FrontSide as To, Camera as h1, Frustum as y_, AudioListener as d1, PositionalAudio as u1, AudioLoader as hm, Audio as f1, BackSide as $u, PMREMGenerator$1 as p1, EquirectangularRefractionMapping as l0, CubeTexture as c0, CompressedCubeTexture as m1, MeshDepthMaterial as g1, CustomBlending as y1, MaxEquation as _1, AlwaysStencilFunc as b1, GreaterEqualStencilFunc as v1, NotEqualStencilFunc as w1, GreaterStencilFunc as x1, LessEqualStencilFunc as S1, EqualStencilFunc as C1, LessStencilFunc as P1, NeverStencilFunc as __, InvertStencilOp as k1, DecrementWrapStencilOp as O1, IncrementWrapStencilOp as E1, DecrementStencilOp as T1, IncrementStencilOp as M1, ReplaceStencilOp as R1, ZeroStencilOp as A1, KeepStencilOp as I1, AmbientLight as L1, HemisphereLight as D1, Loader as j1, GLSL3 as B1, AlwaysDepth as F1, GreaterEqualDepth as z1, GreaterDepth as U1, LessEqualDepth as N1, LessDepth as $1, NotEqualDepth as W1, EqualDepth as V1, RawShaderMaterial as h0, BatchedMesh as b_, LinearFilter as Jd, UnsignedByteType as G1, MeshPhysicalMaterial as v_, RingGeometry as H1, Line3 as q1, AdditiveBlending as d0, BoxHelper as X1, SpotLight as Q1, DirectionalLightHelper as Y1, CameraHelper as K1, LOD as Z1, Triangle as J1, NormalBlending as eC, ReinhardToneMapping as Eg, LinearToneMapping as Tg, EventDispatcher as Mg, VideoTexture as tC, CatmullRomCurve3 as iC, MirroredRepeatWrapping as w_, ShaderLib as eu, UniformsUtils as u0, MeshNormalMaterial as nC, HalfFloatType as Qf, Source as sC } from "./three.js";
import { GroundedSkybox as Xa, Font as oC, TextGeometry as rC, FontLoader as aC, GLTFLoader as Mo, EXRLoader as Rg, RGBELoader as f0, Stats as lC, nodeFrame as x_, TransformControlsGizmo as S_, OrbitControls as cC, PositionalAudioHelper as hC, HorizontalBlurShader as dC, VerticalBlurShader as uC, GLTFExporter as p0, strToU8 as m0, zipSync as fC, XRControllerModelFactory as pC, XRHandMeshModel as mC, Line2 as gC, LineGeometry as yC, LineMaterial as _C, TransformControls as bC, InteractiveGroup as vC, HTMLMesh as wC, VertexNormalsHelper as xC, OBJLoader as Ag, FBXLoader as g0, mergeVertices as SC } from "./three-examples.js";
import { v5 as dm, ByteBuffer as CC, fetchProfile as PC, MotionController as kC, SIZE_PREFIX_LENGTH as y0, Builder as Ig, createNoise4D as OC, Matrix4 as Yf, BatchedParticleRenderer as EC, ParticleSystem as TC, RenderMode as bs, ConstantColor as MC, Vector4 as RC, ConstantValue as AC, TrailParticle as C_, WorkerBase as IC, MeshBVH as LC } from "./vendor-BFrMaK9q.js";
import { __webpack_exports__default as ke, __webpack_exports__Text as _0, __webpack_exports__update as DC, __webpack_exports__Block as b0, SimpleStateBehavior as jC, __webpack_exports__Inline as Kf, __webpack_exports__FontLibrary as P_, ThreeMeshUI as k_ } from "./three-mesh-ui-B-lqrZWj.js";
const O_ = typeof window < "u" ? window.location.search.includes("debugcontext") : !1;
var fe = /* @__PURE__ */ ((s) => (s.ContextRegistered = "ContextRegistered", s.ContextCreationStart = "ContextCreationStart", s.ContextCreated = "ContextCreated", s.ContextFirstFrameRendered = "ContextFirstFrameRendered", s.ContextDestroying = "ContextDestroying", s.ContextDestroyed = "ContextDestroyed", s.MissingCamera = "MissingCamera", s.ContextClearing = "ContextClearing", s.ContextCleared = "ContextCleared", s))(fe || {});
class ue {
/** The currently active (rendering) Needle Engine context */
static get Current() {
return globalThis["NeedleEngine.Context.Current"];
}
/** @internal */
static set Current(e) {
globalThis["NeedleEngine.Context.Current"] = e;
}
/** Returns the array of all registered Needle Engine contexts. Do not modify */
static get All() {
return this.Registered;
}
/** All currently registered Needle Engine contexts. Do not modify */
static Registered = [];
/** @internal Internal use only */
static register(e) {
this.Registered.indexOf(e) === -1 && (O_ && console.warn("Registering context"), this.Registered.push(e), this.dispatchCallback("ContextRegistered", e));
}
/** @internal Internal use only */
static unregister(e) {
const t = this.Registered.indexOf(e);
t !== -1 && (O_ && console.warn("Unregistering context"), this.Registered.splice(t, 1));
}
static _callbacks = {};
/**
* Register a callback to be called when the given event occurs
*/
static registerCallback(e, t) {
this._callbacks[e] || (this._callbacks[e] = []), this._callbacks[e].push(t);
}
/** Unregister a callback */
static unregisterCallback(e, t) {
if (!this._callbacks[e]) return;
const i = this._callbacks[e].indexOf(t);
i !== -1 && this._callbacks[e].splice(i, 1);
}
/** @internal */
static dispatchCallback(e, t, i) {
if (!this._callbacks[e]) return !0;
const n = { event: e, context: t };
if (i)
for (const r in i)
n[r] = i[r];
const o = new Array();
return this._callbacks[e].forEach((r) => {
const a = r(n);
a instanceof Promise && o.push(a);
}), Promise.all(o);
}
/**
* Register a callback to be called when a context is created
*/
static addContextCreatedCallback(e) {
this.registerCallback("ContextCreated", e);
}
/**
* Register a callback to be called when a context is registered
*/
static addContextDestroyedCallback(e) {
this.registerCallback("ContextDestroyed", e);
}
}
const Zf = /* @__PURE__ */ new Map();
function sn(s = globalThis.location?.hostname) {
if (Zf.has(s)) return Zf.get(s);
const e = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|localhost/.test(s);
return Zf.set(s, e), e === !0;
}
function BC() {
return window.location.hostname.includes("glitch.me");
}
const FC = () => (s) => s;
function Q2(s) {
return FC()(s);
}
function Y2() {
return !!x("debug");
}
class on {
_factory;
_cache = [];
_maxSize;
_index = 0;
constructor(e, t) {
this._factory = e, this._maxSize = t;
}
get() {
const e = this._index % this._maxSize;
return this._index++, this._cache.length <= e && (this._cache[e] = this._factory()), this._cache[e];
}
}
let mr = !1;
const um = new Array();
typeof window < "u" && setTimeout(() => {
if (mr) {
const s = {}, e = new URL(window.location.href), t = new URL(e);
t.searchParams.append("console", "");
const i = t.toString().replace(/=$|=(?=&)/g, "");
for (const o of um) {
const r = new URL(e);
r.searchParams.append(o, ""), s[o] = r.toString().replace(/=$|=(?=&)/g, "");
}
console.log(
`🌵 ?help: Debug Options for Needle Engine.
Append any of these parameters to the URL to enable specific debug options.
Example: ${i} will show an onscreen console window.`
);
const n = mr === !0 ? "" : ` (containing "${mr}")`;
console.group("Available URL parameters:" + n);
for (const o of Object.keys(s).sort())
typeof mr == "string" && !o.toLowerCase().includes(mr.toLowerCase()) || (console.groupCollapsed(o), console.log("Reload with this flag enabled:"), console.log(s[o]), console.groupEnd());
console.groupEnd();
}
}, 100);
function Wu() {
return new URLSearchParams(globalThis.location?.search);
}
function x(s) {
mr && !um.includes(s) && um.push(s);
const e = Wu();
if (e.has(s)) {
const t = e.get(s);
if (t) {
const i = Number(t);
return isNaN(i) ? t : i;
} else return !0;
}
return !1;
}
mr = x("help");
function K2(s, e) {
const t = Wu();
t.has(s) ? t.set(s, e) : t.append(s, e), document.location.search = t.toString();
}
function tu(s, e, t = !0) {
const i = Wu();
i.has(s) ? e === null ? i.delete(s) : i.set(s, e) : e !== null && i.append(s, e), t ? zC(s, i) : v0(s, i);
}
function E_(s, e, t) {
s.has(e) ? s.set(e, t.toString()) : s.append(e, t.toString());
}
function zC(s, e, t) {
window.history.pushState(t, s, "?" + e.toString() + window.location.hash);
}
function v0(s, e, t) {
window.history.replaceState(t, s, "?" + e.toString() + window.location.hash);
}
function Z2(s) {
for (var e = "", t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", i = t.length, n = 0; n < s; n++)
e += t.charAt(Math.floor(Math.random() * i));
return e;
}
function J2(s, e) {
return Math.floor(Math.random() * (e - s + 1)) + s;
}
const T_ = ["smol", "tiny", "giant", "interesting", "smart", "bright", "dull", "extreme", "beautiful", "pretty", "dark", "epic", "salty", "silly", "funny", "lame", "lazy", "loud", "lucky", "mad", "mean", "mighty", "mysterious", "nasty", "odd", "old", "powerful", "quiet", "rapid", "scary", "shiny", "shy", "silly", "smooth", "sour", "spicy", "stupid", "sweet", "tasty", "terrible", "ugly", "unusual", "vast", "wet", "wild", "witty", "wrong", "zany", "zealous", "zippy", "zombie", "zorro"], M_ = ["cat", "dog", "mouse", "pig", "cow", "horse", "sheep", "chicken", "duck", "goat", "panda", "tiger", "lion", "elephant", "monkey", "bird", "fish", "snake", "frog", "turtle", "hamster", "penguin", "kangaroo", "whale", "dolphin", "crocodile", "snail", "ant", "bee", "beetle", "butterfly", "dragon", "eagle", "fish", "giraffe", "lizard", "panda", "penguin", "rabbit", "snake", "spider", "tiger", "zebra"];
function UC() {
const s = T_[Math.floor(Math.random() * T_.length)], e = M_[Math.floor(Math.random() * M_.length)];
return s + "_" + e;
}
function NC(s) {
return s = s.replace(/[^a-z0-9áéÃóúñü \.,_-]/gim, ""), s.trim();
}
function iu(s, e, t = !0, i = !1) {
if (e == null) return null;
if (e.userData && e.userData.guid === s) return e;
if (e.guid == s) return e;
if (i && e.userData?.components) {
for (const n of e.userData.components)
if (n.guid === s) return n;
}
if (t) {
if (e.scenes)
for (const n in e.scenes) {
const o = e.scenes[n], r = iu(s, o, t, i);
if (r) return r;
}
if (e.children)
for (const n in e.children) {
const o = e.children[n], r = iu(s, o, t, i);
if (r) return r;
}
}
}
function Vu(s, e, t) {
if (s != null && typeof s == "object") {
if (t || (t = /* @__PURE__ */ new WeakSet()), t.has(s)) return s;
t.add(s);
let i;
if (Array.isArray(s)) i = [];
else {
i = Object.create(Object.getPrototypeOf(s));
const n = Object.getOwnPropertyDescriptors(s);
for (const o in n) {
const r = n[o];
if (r.set || r.writable !== !1)
try {
i[o] = s[o];
} catch {
}
}
}
for (const n of Object.keys(s)) {
const o = s[n];
e && !e(s, n, o) ? i[n] = o : o?.clone !== void 0 && typeof o.clone == "function" ? i[n] = o.clone() : i[n] = Vu(o, e, t);
}
return i;
}
return s;
}
function Ro(s) {
return new Promise((e, t) => {
setTimeout(e, s);
});
}
function Lg(s, e) {
if (s <= 0) return Promise.resolve();
if (e || (e = ue.Current), !e) return Promise.reject("No context");
const t = e.time.frameCount + s;
return new Promise((i, n) => {
if (!e) return n("No context");
const o = () => {
e.time.frameCount >= t && (e.pre_update_callbacks.splice(e.pre_update_callbacks.indexOf(o), 1), i());
};
e.pre_update_callbacks.push(o);
});
}
const Nh = x("debugresolveurl"), $C = "rel:";
function e3(s, e) {
return $s(s, e);
}
function $s(s, e) {
if (e === void 0)
return Nh && console.warn("getPath: uri is undefined, returning uri", e), e;
if (e.startsWith("./"))
return e;
if (e.startsWith("http"))
return Nh && console.warn("getPath: uri is absolute, returning uri", e), e;
if (s === void 0)
return Nh && console.warn("getPath: source is undefined, returning uri", e), e;
e.startsWith($C) && (e = e.substring(4));
const t = s.lastIndexOf("/");
if (t >= 0) {
const i = s.substring(0, t + 1);
for (; i.endsWith("/") && e.startsWith("/"); ) e = e.substring(1);
const n = i + e;
return Nh && console.log("source:", s, `changed uri
from`, e, `
to `, n, `
basePath: ` + i), n;
}
return e;
}
function WC(s) {
if (s)
return s = s.trim(), s = s.split("?")[0]?.split("#")[0], s;
}
class VC {
subscribeWrite(e) {
this.writeCallbacks.push(e);
}
unsubscribeWrite(e) {
const t = this.writeCallbacks.indexOf(e);
t !== -1 && this.writeCallbacks.splice(t, 1);
}
writeCallbacks = [];
constructor(e, t) {
this._object = e, this._prop = t, this._wrapperProp = /* @__PURE__ */ Symbol("$" + t), this.apply();
}
_applied = !1;
_object;
_prop;
_wrapperProp;
apply() {
if (this._applied || !this._object) return;
const e = this._object, t = this._prop;
if (e[t] === void 0) return;
this._applied = !0, e[this._wrapperProp] !== void 0 && console.warn("Watcher is being applied to an object that already has a wrapper property. This is not (yet) supported");
const i = e[t];
e[this._wrapperProp] = i, Object.defineProperty(e, t, {
get: () => e[this._wrapperProp],
set: (r) => {
e[this._wrapperProp] = r;
for (const a of this.writeCallbacks)
a(r, this._prop);
}
});
}
revoke() {
if (!this._applied || !this._object) return;
this._applied = !1;
const e = this._object, t = this._prop;
Reflect.deleteProperty(e, t);
const i = e[this._wrapperProp];
e[t] = i, Reflect.deleteProperty(e, this._wrapperProp);
}
dispose() {
this.revoke(), this.writeCallbacks.length = 0, this._object = null;
}
}
class Co {
_watches = [];
constructor(e, t) {
if (Array.isArray(t))
for (const i of t)
this._watches.push(new Co(e, i));
else
this._watches.push(new VC(e, t));
}
subscribeWrite(e) {
for (const t of this._watches)
t.subscribeWrite(e);
}
unsubscribeWrite(e) {
for (const t of this._watches)
t.unsubscribeWrite(e);
}
apply() {
for (const e of this._watches)
e.apply();
}
revoke() {
for (const e of this._watches)
e.revoke();
}
dispose() {
for (const e of this._watches)
e.dispose();
this._watches.length = 0;
}
}
const ma = /* @__PURE__ */ Symbol("needle:watches");
function Dg(s, e) {
if (!s[ma])
if (s instanceof Z)
s[ma] = new Co(s, ["x", "y"]);
else if (s instanceof v)
s[ma] = new Co(s, ["x", "y", "z"]);
else if (s instanceof ye || s instanceof N)
s[ma] = new Co(s, ["x", "y", "z", "w"]);
else
return !1;
return s[ma].subscribeWrite(e), !0;
}
function w0(s, e) {
if (!s) return;
const t = s[ma];
t && t.unsubscribeWrite(e);
}
var D;
((s) => {
let e;
function t() {
if (e !== void 0) return e;
if (typeof window > "u") return e = !1;
const ee = window.navigator.userAgent, Ee = /Windows|MacOS|Mac OS/.test(ee), pi = /Windows NT/.test(ee) && /Edg/.test(ee) && !/Win64/.test(ee);
return e = Ee && !pi && !E();
}
s.isDesktop = t;
let i;
function n() {
return i !== void 0 ? i : typeof window.orientation < "u" || navigator.userAgent.indexOf("IEMobile") !== -1 ? i = !0 : i = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent);
}
s.isMobileDevice = n;
function o() {
return a();
}
s.isIPad = o;
let r;
function a() {
if (r !== void 0) return r;
const ee = navigator.userAgent.toLowerCase();
return r = /iPad/.test(navigator.userAgent) || ee.includes("macintosh") && "ontouchend" in document;
}
s.isiPad = a;
let l;
function c() {
return l !== void 0 ? l : l = /Android/.test(navigator.userAgent);
}
s.isAndroidDevice = c;
let h;
function d() {
return h !== void 0 ? h : h = /WebXRViewer\//i.test(navigator.userAgent);
}
s.isMozillaXR = d;
let u;
function p() {
return u !== void 0 ? u : u = /NeedleAppClip\//i.test(navigator.userAgent);
}
s.isNeedleAppClip = p;
let m;
function _() {
if (m !== void 0) return m;
if (E() || a()) return m = !1;
const ee = navigator.userAgent.toLowerCase();
return navigator.userAgentData ? m = navigator.userAgentData.platform === "macOS" : m = ee.includes("mac os x") || ee.includes("macintosh");
}
s.isMacOS = _;
let g;
function y() {
return g !== void 0 ? g : g = a() && "xr" in navigator && H();
}
s.isVisionOS = y;
let b;
const w = ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"];
function E() {
return b !== void 0 ? b : b = w.includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
}
s.isiOS = E;
let P;
function O() {
return P !== void 0 || (P = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)), P;
}
s.isSafari = O;
let L;
function j() {
return L !== void 0 ? L : L = navigator.userAgent.includes("OculusBrowser");
}
s.isQuest = j;
let B;
function H() {
return B !== void 0 || (B = document.createElement("a").relList.supports("ar")), B;
}
s.supportsQuickLookAR = H;
async function X() {
try {
return (await navigator.permissions.query({ name: "microphone" })).state !== "denied";
} catch (ee) {
return console.error("Error querying `microphone` permissions.", ee), !1;
}
}
s.microphonePermissionsGranted = X;
let T;
function V() {
if (T !== void 0) return T;
const ee = navigator.userAgent.match(/iPhone OS (\d+_\d+)/);
if (ee && (T = ee[1].replace("_", ".")), !T) {
const Ee = navigator.userAgent.match(/(?:\(Macintosh;|iPhone;|iPad;).*Version\/(\d+\.\d+)/);
Ee && (T = Ee[1]);
}
return T || (T = null), T;
}
s.getiOSVersion = V;
let q;
function re() {
if (q !== void 0) return q;
const ee = navigator.userAgent.match(/(?:CriOS|Chrome)\/(\d+\.\d+\.\d+\.\d+)/);
return ee ? q = ee[1].replace("_", ".") : q = null, q;
}
s.getChromeVersion = re;
let ae;
function pe() {
if (ae !== void 0) return ae;
const ee = navigator.userAgent.match(/Version\/(\d+\.\d+)/);
return ee && O() ? ae = ee[1] : ae = null, ae;
}
s.getSafariVersion = pe;
})(D || (D = {}));
function t3() {
return D.isDesktop();
}
function i3() {
return D.isMobileDevice();
}
function n3() {
return D.isiPad();
}
function s3() {
return D.isiPad();
}
function o3() {
return D.isAndroidDevice();
}
function r3() {
return D.isMozillaXR();
}
function a3() {
return D.isMacOS();
}
function l3() {
return D.isiOS();
}
function c3() {
return D.isSafari();
}
function h3() {
return D.isQuest();
}
async function d3() {
return D.microphonePermissionsGranted();
}
const _o = /* @__PURE__ */ new WeakMap();
function x0(s, e, t) {
if (!_o.get(s)) {
const n = new MutationObserver((o) => {
GC(s, o);
});
_o.set(s, {
observer: n,
attributeChangedListeners: /* @__PURE__ */ new Map()
}), n.observe(s, { attributes: !0 });
}
const i = _o.get(s).attributeChangedListeners;
return i.has(e) || i.set(e, []), i.get(e).push(t), () => {
S0(s, e, t);
};
}
function S0(s, e, t) {
if (!_o.get(s)) return;
const i = _o.get(s).attributeChangedListeners;
if (!i.has(e)) return;
const n = i.get(e), o = n.indexOf(t);
o !== -1 && (n.splice(o, 1), n.length <= 0 && (i.delete(e), _o.get(s)?.observer.disconnect(), _o.delete(s)));
}
function GC(s, e) {
const t = _o.get(s).attributeChangedListeners;
for (const i of e)
if (i.type === "attributes") {
const n = i.attributeName, o = s.getAttribute(n);
if (t.has(n))
for (const r of t.get(n))
r(o);
}
}
class R_ {
reason;
constructor(e) {
this.reason = e;
}
}
async function C0(s) {
const e = await Promise.allSettled(s).catch((n) => [
new R_(n.message)
]);
let t = !1;
const i = e.map((n) => "value" in n ? n.value : (t = !0, new R_(n.reason)));
return {
anyFailed: t,
results: i
};
}
const HC = x("debugdebug");
let jg = !1;
(x("noerrors") || x("nooverlaymessages")) && (jg = !0);
const Jf = "needle_engine_global_error_container";
var tn = /* @__PURE__ */ ((s) => (s[s.Log = 0] = "Log", s[s.Warn = 1] = "Warn", s[s.Error = 2] = "Error", s))(tn || {});
function P0() {
return O0;
}
const fm = new Array();
function qC(s) {
fm.push(s);
}
let ep = !1;
function XC(...s) {
if (!ep) {
ep = !0;
try {
for (let e = 0; e < fm.length; e++)
fm[e](...s);
} catch (e) {
console.error(e);
}
ep = !1;
}
}
const k0 = console.error, QC = function(...s) {
k0.apply(console, s), ZC(s), br(2, s, {}), KC(...s);
};
function YC(s) {
jg = !s, s ? console.error = QC : console.error = k0;
}
function u3(s) {
return YC(s);
}
let O0 = 0;
function KC(...s) {
O0 += 1, XC(...s);
}
function ZC(s) {
if (Array.isArray(s))
for (let e = 0; e < s.length; e++) {
const t = s[e];
typeof t == "string" && t.startsWith("THREE.PropertyBinding: Trying to update node for track:") && (s[e] = "Some animated objects couldn't be found: see console for details");
}
}
const A_ = /* @__PURE__ */ new Set();
function br(s, e, t = {}, i, n) {
if (jg) return;
if (t.once === !0) {
let a = "";
if (Array.isArray(e))
for (let l = 0; l < e.length; l++) {
let c = e[l];
c instanceof Error && (c = c.message), typeof c != "object" && (l > 0 && (a += " "), a += c);
}
else typeof e == "string" && (a = e);
if (A_.has(a)) return;
A_.add(a);
}
const o = ue.Current;
let r = o?.domElement ?? document.querySelector("needle-engine");
if (o?.isInAR && (r = o.arOverlayElement), !!r) {
if (Array.isArray(e)) {
let a = "";
for (let l = 0; l < e.length; l++) {
let c = e[l];
c instanceof Error && (c = c.message), typeof c != "object" && (l > 0 && (a += " "), a += c);
}
e = a;
}
!e || e.length <= 0 || JC(s, r, e, t);
}
}
const Pa = /* @__PURE__ */ new Map(), I_ = 0.2;
function JC(s, e, t, i = {}) {
if (t == null) return;
const n = tP(e);
if (n.childElementCount >= 20) {
const c = n.lastElementChild;
L_(c);
}
t.length > 400 && (t = t.substring(0, 400) + "...");
const o = i.key ?? t;
if (Pa.has(o)) {
Pa.get(o)?.update(t, i);
return;
}
const r = iP(s, t);
n.prepend(r);
const a = () => {
Pa.delete(o), L_(r);
};
let l = setTimeout(a, Math.max(I_, i.duration ?? 10) * 1e3);
Pa.set(o, {
update: (c, h) => {
c.length > 400 && (c = c.substring(0, 400) + "..."), r.innerHTML = c, h.duration && (clearTimeout(l), l = setTimeout(a, Math.max(I_, h.duration) * 1e3));
},
removeFunction: a
});
}
function f3() {
HC && console.log("Clearing messages");
for (const s of Pa.values())
s?.removeFunction.call(s);
Pa.clear();
}
const eP = `
@import url('https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght@8..144,100..1000&display=swap');
div[data-needle_engine_debug_overlay] {
font-family: 'Roboto Flex', sans-serif;
font-weight: 400;
font-size: 16px;
}
div[data-needle_engine_debug_overlay] strong {
font-weight: 700;
}
div[data-needle_engine_debug_overlay] a {
color: white;
text-decoration: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
div[data-needle_engine_debug_overlay] a:hover {
text-decoration: none;
border: none;
}
div[data-needle_engine_debug_overlay] .log strong {
color: rgba(200,200,200,.9);
}
div[data-needle_engine_debug_overlay] .warn strong {
color: rgba(255,255,230, 1);
}
div[data-needle_engine_debug_overlay] .error strong {
color: rgba(255,100,120, 1);
}
`;
function tP(s) {
globalThis[Jf] || (globalThis[Jf] = /* @__PURE__ */ new Map());
const e = globalThis[Jf];
if (e.has(s))
return e.get(s);
{
const t = document.createElement("div");
e.set(s, t), t.setAttribute("data-needle_engine_debug_overlay", ""), t.classList.add("debug-container"), t.style.cssText = `
position: absolute;
top: 0;
right: 5px;
padding-top: env(safe-area-inset-top, 0px);
max-width: 70%;
max-height: calc(100% - 105px);
z-index: 100000;
pointer-events: scroll;
display: flex;
align-items: end;
flex-direction: column;
color: white;
overflow: auto;
word-break: break-word;
`, D.isNeedleAppClip() && (t.style.left = "5px", t.style.right = "unset");
const i = document.querySelector('meta[name="viewport"]');
i && !i.getAttribute("content")?.includes("viewport-fit=") && i.setAttribute("content", i.getAttribute("content") + ",viewport-fit=cover"), s.shadowRoot ? s.shadowRoot.appendChild(t) : s.appendChild(t);
const n = document.createElement("style");
return n.innerHTML = eP, t.appendChild(n), t;
}
}
const E0 = /* @__PURE__ */ Symbol("logtype"), nu = /* @__PURE__ */ new Map();
function L_(s) {
s.remove();
const e = s[E0], t = nu.get(e) ?? [];
t.push(s), nu.set(e, t);
}
function iP(s, e) {
if (nu.has(s)) {
const i = nu.get(s);
if (i.length > 0) {
const n = i.pop();
return n.innerHTML = e, n;
}
}
const t = document.createElement("div");
switch (t.setAttribute("data-id", "__needle_engine_debug_overlay"), t.style.marginRight = "5px", t.style.padding = ".5em", t.style.backgroundColor = "rgba(0,0,0,.9)", t.style.marginTop = "5px", t.style.marginBottom = "3px", t.style.borderRadius = "8px", t.style.pointerEvents = "all", t.style.userSelect = "text", t.style.maxWidth = "250px", t.style.whiteSpace = "pre-wrap", t.style["backdrop-filter"] = "blur(10px)", t.style["-webkit-backdrop-filter"] = "blur(10px)", t.style.backgroundColor = "rgba(20,20,20,.8)", t.style.boxShadow = "inset 0 0 80px rgba(0,0,0,.2), 0 0 5px rgba(0,0,0,.2)", t.style.border = "1px solid rgba(160,160,160,.2)", t[E0] = s, s) {
case 0:
t.classList.add("log"), t.style.color = "rgba(200,200,200,.7)", t.style.backgroundColor = "rgba(40,40,40,.7)";
break;
case 1:
t.classList.add("warn"), t.style.color = "rgb(255, 255, 150)", t.style.backgroundColor = "rgba(50,50,20,.8)";
break;
case 2:
t.classList.add("error"), t.style.color = "rgb(255, 50, 50", t.style.backgroundColor = "rgba(50,20,20,.8)";
break;
}
return t.title = "Open the browser console (F12) for more information", t.innerHTML = e, t;
}
const nP = x("nodevlogs");
let pm, tp;
function R() {
if (nP) return !1;
if (pm !== void 0) return pm;
if (tp !== void 0) return tp;
let s = sn();
return s || (s = typeof window < "u" && window.location.hostname.endsWith(".local-credentialless.webcontainer.io")), tp = s, s;
}
function p3(s) {
pm = s;
}
class sP {
random(e, t) {
return Array.isArray(e) ? e.length <= 0 ? null : e[Math.floor(Math.random() * e.length)] : e !== void 0 && t !== void 0 ? Math.random() * (t - e) + e : Math.random();
}
/**
* Fills a Vector3 with random values.
* @param target Vector3 to fill with random values
* @param min Minimum value for each component
* @param max Maximum value for each component
*/
randomVector3(e, t = 0, i = 1) {
e.x = this.random(t, i), e.y = this.random(t, i), e.z = this.random(t, i);
}
/**
* Clamps a value between min and max.
* @param value Value to clamp
* @param min Minimum bound
* @param max Maximum bound
* @returns Clamped value
*/
clamp(e, t, i) {
return e < t ? t : e > i ? i : e;
}
/**
* Clamps a value between 0 and 1.
* @param value Value to clamp
* @returns Value clamped to [0, 1]
*/
clamp01(e) {
return this.clamp(e, 0, 1);
}
/**
* Linearly interpolates between two values.
* @param value1 Start value (returned when t=0)
* @param value2 End value (returned when t=1)
* @param t Interpolation factor, clamped to [0, 1]
* @returns Interpolated value
*/
lerp(e, t, i) {
return i = i < 0 ? 0 : i, i = i > 1 ? 1 : i, e + (t - e) * i;
}
/**
* Calculates the linear interpolation parameter that produces the given value.
* Inverse of lerp: if `lerp(a, b, t) = v`, then `inverseLerp(a, b, v) = t`
* @param value1 Start value
* @param value2 End value
* @param t The value to find the parameter for
* @returns The interpolation parameter (may be outside [0,1] if t is outside [value1, value2])
*/
inverseLerp(e, t, i) {
return (i - e) / (t - e);
}
/**
* Remaps a value from one range to another.
* @param value The value to remap.
* @param min1 The minimum value of the current range.
* @param max1 The maximum value of the current range.
* @param min2 The minimum value of the target range.
* @param max2 The maximum value of the target range.
*/
remap(e, t, i, n, o) {
return n + (o - n) * (e - t) / (i - t);
}
/**
* Moves a value towards a target by a maximum step amount.
* Useful for smooth following or gradual value changes.
* @param value1 Current value
* @param value2 Target value
* @param amount Maximum step to move (positive moves toward target)
* @returns New value moved toward target, never overshooting
*/
moveTowards(e, t, i) {
return e += i, (i < 0 && e < t || i > 0 && e > t) && (e = t), e;
}
Rad2Deg = 180 / Math.PI;
Deg2Rad = Math.PI / 180;
Epsilon = 1e-5;
/**
* Converts radians to degrees
*/
toDegrees(e) {
return e * 180 / Math.PI;
}
/**
* Converts degrees to radians
*/
toRadians(e) {
return e * Math.PI / 180;
}
tan(e) {
return Math.tan(e);
}
gammaToLinear(e) {
return Math.pow(e, 2.2);
}
linearToGamma(e) {
return Math.pow(e, 1 / 2.2);
}
/**
* Checks if two vectors are approximately equal within epsilon tolerance.
* Works with Vector2, Vector3, Vector4, and Quaternion.
* @param v1 First vector
* @param v2 Second vector
* @param epsilon Tolerance for comparison (default: Number.EPSILON)
* @returns True if all components are within epsilon of each other
*/
approximately(e, t, i = Number.EPSILON) {
for (const n of oP) {
const o = e[n], r = t[n];
if (o === void 0 || r === void 0) break;
if (Math.abs(o - r) > i)
return !1;
}
return !0;
}
/**
* Easing function: slow start, fast middle, slow end (cubic).
* @param x Input value from 0 to 1
* @returns Eased value from 0 to 1
*/
easeInOutCubic(e) {
return e < 0.5 ? 4 * e * e * e : 1 - Math.pow(-2 * e + 2, 3) / 2;
}
}
const oP = ["x", "y", "z", "w"], F = new sP();
class D_ {
y;
s;
alpha = 0;
constructor(e) {
this.setAlpha(e), this.y = null, this.s = null;
}
setAlpha(e) {
if (e <= 0 || e > 1)
throw new Error();
this.alpha = e;
}
filter(e, t) {
t && this.setAlpha(t);
let i;
return this.y ? i = this.alpha * e + (1 - this.alpha) * this.s : i = e, this.y = e, this.s = i, i;
}
lastValue() {
return this.y;
}
reset(e) {
this.y = e, this.s = e;
}
}
class ip {
/**
* An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
*/
freq;
/**
* Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
*/
minCutOff;
/**
* Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
*/
beta;
/**
* Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
dCutOff;
/**
* The low-pass filter for the signal.
*/
x;
/**
* The low-pass filter for the derivates.
*/
dx;
/**
* The last time the filter was called.
*/
lasttime;
/** Create a new OneEuroFilter
* @param freq - An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
* @param minCutOff - Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
* @param beta - Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
* @param dCutOff - Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
constructor(e, t = 1, i = 0, n = 1) {
if (e <= 0 || t <= 0 || n <= 0)
throw new Error();
this.freq = e, this.minCutOff = t, this.beta = i, this.dCutOff = n, this.x = new D_(this.alpha(this.minCutOff)), this.dx = new D_(this.alpha(this.dCutOff)), this.lasttime = null;
}
alpha(e) {
const t = 1 / this.freq;
return 1 / (1 + 1 / (2 * Math.PI * e) / t);
}
/** Filter your value: call with your value and the current timestamp (e.g. from this.context.time.time) */
filter(e, t = null) {
this.lasttime && t && (this.freq = 1 / (t - this.lasttime)), this.lasttime = t;
const i = this.x.lastValue(), n = i ? (e - i) * this.freq : 0, o = this.dx.filter(n, this.alpha(this.dCutOff)), r = this.minCutOff + this.beta * Math.abs(o);
return this.x.filter(e, this.alpha(r));
}
reset(e) {
e != null && this.x.reset(e), this.x.alpha = this.alpha(this.minCutOff), this.dx.alpha = this.alpha(this.dCutOff), this.lasttime = null;
}
}
class T0 {
x;
y;
z;
/** Create a new OneEuroFilter
* @param freq - An estimate of the frequency in Hz of the signal (> 0), if timestamps are not available.
* @param minCutOff - Min cutoff frequency in Hz (> 0). Lower values allow to remove more jitter.
* @param beta - Parameter to reduce latency (> 0). Higher values make the filter react faster to changes.
* @param dCutOff - Used to filter the derivates. 1 Hz by default. Change this parameter if you know what you are doing.
*/
constructor(e, t = 1, i = 0, n = 1) {
this.x = new ip(e, t, i, n), this.y = new ip(e, t, i, n), this.z = new ip(e, t, i, n);
}
filter(e, t, i = null) {
t.x = this.x.filter(e.x, i), t.y = this.y.filter(e.y, i), t.z = this.z.filter(e.z, i);
}
reset(e) {
this.x.reset(e?.x), this.y.reset(e?.y), this.z.reset(e?.z);
}
}
const kd = "needle:cameraController";
function rP(s) {
return s[kd];
}
function j_(s, e, t) {
t ? s[kd] = e : s[kd] === e && (s[kd] = null);
}
const mm = "needle:autofit";
function aP(s) {
return s[mm] === void 0 ? !0 : s[mm] !== !1;
}
function gm(s, e) {
s[mm] = e;
}
let pn;
const lP = { x: 0, y: 0, width: 0, height: 0 }, cP = x("debugfocusrect");
function hP(s, e, t, i, n) {
s instanceof Element && (cP && s instanceof HTMLElement && (s.style.outline = "2px dashed rgba(255, 150, 0, .8)"), s = s.getBoundingClientRect()), pn = n.domElement.getBoundingClientRect();
const o = lP;
o.x = s.x, o.y = s.y, o.width = s.width, o.height = s.height, o.x -= pn.x, o.y -= pn.y;
const r = pn.width, a = pn.height, l = i.view, c = e.zoom;
let h = l?.offsetX || 0, d = l?.offsetY || 0, u = pn.width, p = pn.height;
u /= c, p /= c, h = u * (c - 1) * 0.5, d = p * (c - 1) * 0.5;
const m = o.x + o.width * 0.5, _ = o.y + o.height * 0.5, g = pn.width * 0.5, y = pn.height * 0.5, b = m - g, w = _ - y;
h -= b / c, d -= w / c, e.offsetX !== void 0 && (h += e.offsetX * (pn.width * 0.5)), e.offsetY !== void 0 && (d -= e.offsetY * (pn.height * 0.5));
const E = l?.offsetX || h, P = l?.offsetY || d;
h = F.lerp(E, h, t), d = F.lerp(P, d, t);
const O = l?.width || r, L = l?.height || a;
u = F.lerp(O, u, t), p = F.lerp(L, p, t), i.setViewOffset(r, a, h, d, u, p), i.updateProjectionMatrix(), e.damping > 0 && (e.damping *= 1 - t, e.damping < 0.01 && (e.damping = 0), e.damping = Math.max(0, e.damping));
}
function dP(s, e, t) {
const i = s.length(), n = e.length(), o = F.lerp(i, n, t);
return s.lerp(e, t).normalize().multiplyScalar(o);
}
const np = new N(), M0 = new N().setFromAxisAngle(new v(0, 1, 0), Math.PI);
function m3(s, e) {
s.lookAt(e), s.quaternion.multiply(M0);
}
function Gu(s, e, t = !0, i = !1) {
if (s === e) return;
np.copy(s.quaternion);
const n = se(e), o = se(s);
if (i) {
if (is(s, xe(e)), t) {
const r = o.y, a = o.sub(vP(s));
a.y = r, s.lookAt(a), s.quaternion.multiply(M0);
}
Number.isNaN(s.quaternion.x) && s.quaternion.copy(np);
return;
}
t && (n.y = o.y), s.lookAt(n), Number.isNaN(s.quaternion.x) && s.quaternion.copy(np);
}
function g3(s, e, t, i = 1) {
if (t) {
const n = U(0, 0, 0), o = e.x / window.innerWidth * 2 - 1, r = -(e.y / window.innerHeight) * 2 + 1;
n.set(
o,
r,
0
), n.unproject(t);
const a = t.worldPosition, l = s.worldPosition.distanceTo(a), c = n.sub(a);
c.multiplyScalar(i * 3.6 * l);
const h = t.worldPosition.add(c);
return s.lookAt(h), h;
}
return null;
}
const uP = new on(() => new v(), 100);
function U(s, e, t) {
const i = uP.get();
return i.set(0, 0, 0), s instanceof v ? i.copy(s) : Array.isArray(s) ? i.set(s[0], s[1], s[2]) : s instanceof DOMPointReadOnly ? i.set(s.x, s.y, s.z) : typeof s == "number" ? (i.x = s, i.y = e !== void 0 ? e : i.x, i.z = t !== void 0 ? t : i.x) : typeof s == "object" && (i.x = s.x, i.y = s.y, i.z = s.z), i;
}
const fP = new on(() => new oe(), 30);
function pP(s) {
const e = fP.get();
return s ? e.copy(s) : e.set(0, 0, 0), e;
}
const mP = new on(() => new N(), 100);
function ki(s, e, t, i) {
const n = mP.get();
return n.identity(), s instanceof N ? n.copy(s) : s instanceof DOMPointReadOnly ? n.set(s.x, s.y, s.z, s.w) : typeof s == "number" && e !== void 0 && t !== void 0 && i !== void 0 ? n.set(s, e, t, i) : typeof s == "object" && "x" in s && "y" in s && "z" in s && "w" in s && n.set(s.x, s.y, s.z, s.w), n;
}
const Bg = new on(() => new v(), 100), B_ = /* @__PURE__ */ Symbol("lastMatrixWorldUpdateKey");
function se(s, e = null, t = !0) {
const i = e ?? Bg.get();
return s ? s.parent ? (t && s.updateWorldMatrix(!0, !1), s.matrixWorldNeedsUpdate && s[B_] !== Date.now() && (s[B_] = Date.now(), s.updateMatrixWorld()), i.setFromMatrixPosition(s.matrixWorld), i) : i.copy(s.position) : i.set(0, 0, 0);
}
function oi(s, e) {
if (!s) return s;
const t = Bg.get();
return e !== t && t.copy(e), s.parent !== null && s.parent.worldToLocal(t), s.position.set(t.x, t.y, t.z), s;
}
function Qa(s, e, t, i) {
const n = Bg.get();
return n.set(e, t, i), oi(s, n), s;
}
const su = new on(() => new N(), 100), Sr = new N(), sp = new N();
function xe(s, e = null) {
if (!s) return su.get().identity();
const t = e ?? su.get();
return s.parent ? (s.getWorldQuaternion(t), t) : t.copy(s.quaternion);
}
function is(s, e) {
if (!s) return;
e !== Sr && Sr.copy(e);
const t = Sr;
s?.parent?.getWorldQuaternion(sp), sp.invert();
const n = sp.multiply(t);
s.quaternion.set(n.x, n.y, n.z, n.w);
}
function R0(s, e, t, i, n) {
Sr.set(e, t, i, n), is(s, Sr);
}
const gP = new on(() => new v(), 100), yP = new v();
function Ke(s, e = null) {
return e || (e = gP.get()), s ? s.parent ? (s.getWorldScale(e), e) : e.copy(s.scale) : e.set(0, 0, 0);
}
function zc(s, e) {
if (!s) return;
if (!s.parent) {
s.scale.copy(e);
return;
}
const t = yP;
s.parent.getWorldScale(t), s.scale.copy(e), s.scale.divide(t);
}
const _P = new v(), F_ = new N();
function y3(s) {
return xe(s, F_), _P.set(0, 0, 1).applyQuaternion(F_);
}
const bP = new on(() => new v(), 100), z_ = new N();
function vP(s, e) {
return e || (e = bP.get().set(0, 0, 1)), xe(s, z_), e.applyQuaternion(z_);
}
const U_ = new He(), N_ = new He(), wP = new v();
function A0(s) {
const e = su.get();
return s.getWorldQuaternion(e), N_.setFromQuaternion(e), N_;
}
function I0(s, e) {
const t = su.get();
is(s, t.setFromEuler(e));
}
function Fg(s) {
const e = A0(s), t = wP;
return t.set(e.x, e.y, e.z), t.x = F.toDegrees(t.x), t.y = F.toDegrees(t.y), t.z = F.toDegrees(t.z), t;
}
function xP(s, e) {
Hu(s, e.x, e.y, e.z, !0);
}
function Hu(s, e, t, i, n = !0) {
n && (e = F.toRadians(e), t = F.toRadians(t), i = F.toRadians(i)), U_.set(e, t, i), Sr.setFromEuler(U_), is(s, Sr);
}
function ym(s, e = !0) {
s && (e ? (function t(i) {
console.groupCollapsed((i.name ? i.name : "(no name : " + i.type + ")") + " %o", i), i.children.forEach(t), console.groupEnd();
})(s) : s.traverse(function(t) {
for (var i = "|___", n = t; n.parent !== null; )
i = " " + i, n = n.parent;
console.log(i + t.name + " <" + t.type + ">");
}));
}
function _3(s) {
let e = s?.name || "";
if (!s) return e;
let t = s.parent;
for (; t; )
e = t.name + "/" + e, t = t.parent;
return e;
}
function SP(s) {
if (s) {
const e = s;
return e.blendMode !== void 0 && e.clampWhenFinished !== void 0 && e.enabled !== void 0 && e.fadeIn !== void 0 && e.getClip !== void 0;
}
return !1;
}
class ou extends es {
static vertex = `
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = vec4(position.xy, 0., 1.0);
}`;
constructor() {
super({
vertexShader: ou.vertex,
uniforms: {
map: new en(null),
flipY: new en(!0),
writeDepth: new en(!1),
depthTexture: new en(null)
},
fragmentShader: `
uniform sampler2D map;
uniform bool flipY;
uniform bool writeDepth;
uniform sampler2D depthTexture;
varying vec2 vUv;
void main(){
vec2 uv = vUv;
if (flipY) uv.y = 1.0 - uv.y;
gl_FragColor = texture2D(map, uv);
if (writeDepth) {
float depth = texture2D(depthTexture, uv).r;
gl_FragDepth = depth;
// float linearDepth = (depth - 0.99) * 100.0; // Enhance near 1.0 values
// gl_FragColor = vec4(linearDepth, linearDepth, linearDepth, 1.0);
}
}`
});
}
reset() {
this.uniforms.map.value = null, this.uniforms.flipY.value = !0, this.uniforms.writeDepth.value = !1, this.uniforms.depthTexture.value = null, this.needsUpdate = !0, this.uniformsNeedUpdate = !0;
}
}
class Lr {
static _planeGeometry;
static _renderer;
static _perspectiveCam;
static _orthographicCam;
static _scene;
static _blitMaterial;
static _mesh;
static get planeGeometry() {
return this._planeGeometry ??= new Tn(2, 2, 1, 1);
}
static get renderer() {
return this._renderer ??= new Vr({ antialias: !1, alpha: !0 });
}
static get perspectiveCam() {
return this._perspectiveCam ??= new de();
}
static get orthographicCam() {
return this._orthographicCam ??= new Du();
}
static get scene() {
return this._scene ??= new ji();
}
static get blitMaterial() {
return this._blitMaterial ??= new ou();
}
static get mesh() {
return this._mesh ??= new G(Lr.planeGeometry, Lr.blitMaterial);
}
/**
* Copy a texture to a new texture
* @param texture the texture to copy
* @param blitMaterial the material to use for copying (optional)
* @returns the newly created, copied texture
*/
static copyTexture(e, t) {
t || (t = this.blitMaterial), this.blitMaterial.reset();
const i = t || this.blitMaterial;
i.uniforms.map.value = e, i.needsUpdate = !0, i.uniformsNeedUpdate = !0;
const n = i.vertexShader;
i.vertexShader = ou.vertex;
const o = this.mesh;
o.material = i, o.frustumCulled = !1, this.scene.children.length = 0, this.scene.add(o), this.renderer.setSize(e.image.width, e.image.height), this.renderer.clear(), this.renderer.render(this.scene, this.perspectiveCam);
const r = new Se(this.renderer.domElement);
return r.name = "Copy", r.needsUpdate = !0, i.vertexShader = n, r;
}
static blit(e, t, i) {
const {
renderer: n = this.renderer,
blitMaterial: o = this.blitMaterial,
flipY: r = !1,
depthTexture: a = null,
depthTest: l = !0,
depthWrite: c = !0
} = i || {};
this.blitMaterial.reset(), o.uniforms.map && (o.uniforms.map.value = e), o.uniforms.flipY && (o.uniforms.flipY.value = r), a ? (o.uniforms.writeDepth = new en(!0), o.uniforms.depthTexture.value = a) : (o.uniforms.writeDepth = new en(!1), o.uniforms.depthTexture.value = null), o.needsUpdate = !0, o.uniformsNeedUpdate = !0;
const h = this.mesh;
h.material = o, h.frustumCulled = !1, this.scene.children.length = 0, this.scene.add(h);
const d = n.getRenderTarget(), u = n.getContext();
l ? u.enable(u.DEPTH_TEST) : u.disable(u.DEPTH_TEST), n.state.buffers.depth.setMask(c), n.setClearColor(new oe(0, 0, 0), 0), n.setRenderTarget(t), n.clear(), n.render(this.scene, this.perspectiveCam), n.setRenderTarget(d), u.enable(u.DEPTH_TEST), n.state.buffers.depth.setMask(!0);
}
/**
* Copy a texture to a HTMLCanvasElement
* @param texture the texture convert
* @param force if true the texture will be copied to a new texture before converting
* @returns the HTMLCanvasElement with the texture or null if the texture could not be copied
*/
static textureToCanvas(e, t = !1) {
if (!e)
return null;
(t === !0 || e.isCompressedTexture === !0) && (e = CP(e));
const i = e.image;
if (PP(i)) {
const n = document.createElement("canvas");
n.width = i.width, n.height = i.height;
const o = n.getContext("2d");
return o ? (o.drawImage(i, 0, 0, i.width, i.height, 0, 0, n.width, n.height), n) : (console.error("Failed getting canvas 2d context"), null);
}
return null;
}
}
function CP(s) {
return Lr.copyTexture(s);
}
function b3(s, e = !1) {
return Lr.textureToCanvas(s, e);
}
function PP(s) {
return typeof HTMLImageElement < "u" && s instanceof HTMLImageElement || typeof HTMLCanvasElement < "u" && s instanceof HTMLCanvasElement || typeof OffscreenCanvas < "u" && s instanceof OffscreenCanvas || typeof ImageBitmap < "u" && s instanceof ImageBitmap;
}
function kP(s) {
const e = s.type;
return e === "Mesh" || e === "SkinnedMesh";
}
function L0(s, e) {
e ? s["needle:rendercustomshadow"] = !0 : s["needle:rendercustomshadow"] = !1;
}
function OP(s) {
if (s) {
if (s["needle:rendercustomshadow"] === !0)
return !0;
if (s["needle:rendercustomshadow"] == null)
return !0;
}
return !1;
}
function Fi(s, e = void 0, t = void 0, i = void 0) {
const n = i || new si();
n.makeEmpty();
const o = [];
function r(l) {
let c = !0;
if (l.visible && aP(l) !== !1 && !(l.type === "TransformControlsGizmo" || l.type === "TransformControlsPlane")) {
if (l instanceof WS && (c = !1), l instanceof t0 && (c = !1), l instanceof Xa && (c = !1), l.isGizmo === !0 && (c = !1), l.material instanceof e0 && (c = !1), kP(l) || (c = !1), t && l.layers.test(t) === !1 && (c = !1), c) {
if (e && Array.isArray(e) && e?.includes(l)) return;
if (typeof e == "function" && e(l) === !0)
return;
}
if (l.isUI !== !0) {
if (c) {
const h = l.children;
l.children = o;
const d = l.position, u = l.scale;
if (Number.isNaN(d.x) || Number.isNaN(d.y) || Number.isNaN(d.z)) {
console.warn(`Object "${l.name}" has NaN values in position or scale.... will ignore it`, d, u);
return;
}
l.geometry === null && (l.geometry = void 0), n.expandByObject(l, !0), l.children = h;
}
for (const h of l.children)
r(h);
}
}
}
let a = !1;
Array.isArray(s) || (s = [s]);
for (const l of s)
l && (a = !0, l.updateMatrixWorld(), r(l));
return a || console.warn("No objects to fit camera to..."), n;
}
function EP(s, e, t) {
const i = Fi([s], t?.ignore), n = new v();
i.getSize(n);
const o = new v();
i.getCenter(o);
const r = new v();
e.getSize(r);
const a = new v();
e.getCenter(a);
const l = new v();
l.set(r.x / n.x, r.y / n.y, r.z / n.z);
const c = Math.min(l.x, l.y, l.z), h = t?.scale !== !1;
if (h && zc(s, Ke(s).multiplyScalar(c)), t?.position !== !1) {
const d = new v();
i.getCenter(d), d.y = i.min.y;
const u = new v();
e.getCenter(u), u.y = e.min.y;
const p = u.clone().sub(d);
h && p.multiplyScalar(c), oi(s, se(s).add(p));
}
return {
boundsBefore: i,
scale: l
};
}
function TP(s, e) {
const t = Fi([s]), i = new v();
t.getCenter(i), i.y = t.min.y;
const n = e.clone().sub(i), o = se(s);
return oi(s, o.add(n)), {
offset: n,
bounds: t
};
}
function D0(s, e, t, i) {
if (Array.isArray(e)) {
let r = !0;
for (let a = 0; a < e.length; a++)
D0(s, e[a], a, e) || (r = !1);