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.

143 lines (131 loc) 1.28 MB
import{Vector2 as K,Vector3 as b,Vector4 as ye,Quaternion as N,Box3 as Nt,ShadowMaterial as xb,Euler as ct,PlaneGeometry as Sn,WebGLRenderer as br,PerspectiveCamera as de,OrthographicCamera as Md,Scene as qi,Mesh as H,Texture as Se,Uniform$1 as Xi,Color as oe,ShaderMaterial as Hn,MeshStandardMaterial as yt,Box3Helper as oC,GridHelper as Sb,Object3D as M,Material as we,Matrix3 as Cb,Matrix4 as J,Layers as ws,PropertyBinding as Ia,AnimationClip as Mi,KeyframeTrack as sC,FileLoader as Pb,BufferGeometry as Qi,TextureLoader as _r,MeshBasicMaterial as Ce,DoubleSide as Ri,Group as Oo,CylinderGeometry as Ob,SphereGeometry as Rd,BoxGeometry as La,SpriteMaterial as rC,Sprite as aC,Shape as lC,ExtrudeGeometry as cC,Ray as ko,CubeUVReflectionMapping as Mo,LinearSRGBColorSpace as Ro,ShaderChunk as Kt,Sphere as Ed,DataTexture as Im,RGBAFormat as Td,EquirectangularReflectionMapping as Eo,SRGBColorSpace as To,Clock as hC,NeutralToneMapping as Da,AgXToneMapping as Ad,ACESFilmicToneMapping as Id,NoToneMapping as Ld,PCFSoftShadowMap$1 as dC,BasicNodeLibrary as uC,WebGLRenderTarget as Gn,DepthTexture as kb,NearestFilter as Dd,AxesHelper as Ei,MathUtils as Ao,Fog as Mb,DirectionalLight as Lm,PointLight as Dm,EdgesGeometry as pC,LineSegments as jm,LineBasicMaterial as jd,Line as ja,BufferAttribute as tt,Raycaster as Bd,ArrayCamera as mC,Plane as vr,SkinnedMesh as xs,InterleavedBufferAttribute as Rb,Skeleton as gC,Bone as fC,WebGLCubeRenderTarget as yC,CubeCamera as bC,LoopRepeat as _C,LoopOnce as Bm,AnimationMixer as Fm,CompressedTexture as vC,FrontSide as Ss,Camera as wC,Frustum as Eb,AudioListener as xC,PositionalAudio as SC,AudioLoader as Um,VectorKeyframeTrack as CC,QuaternionKeyframeTrack as PC,Audio as OC,BackSide as Fd,PMREMGenerator$1 as kC,EquirectangularRefractionMapping as Tb,CubeTexture as Ab,CompressedCubeTexture as MC,EventDispatcher as zm,MeshDepthMaterial as RC,CustomBlending as EC,MaxEquation as TC,AlwaysStencilFunc as AC,GreaterEqualStencilFunc as IC,NotEqualStencilFunc as LC,GreaterStencilFunc as DC,LessEqualStencilFunc as jC,EqualStencilFunc as BC,LessStencilFunc as FC,NeverStencilFunc as Ib,InvertStencilOp as UC,DecrementWrapStencilOp as zC,IncrementWrapStencilOp as NC,DecrementStencilOp as WC,IncrementStencilOp as VC,ReplaceStencilOp as $C,ZeroStencilOp as HC,KeepStencilOp as GC,AmbientLight as qC,HemisphereLight as XC,Loader as QC,GLSL3 as YC,AlwaysDepth as ZC,GreaterEqualDepth as KC,GreaterDepth as JC,LessEqualDepth as eP,LessDepth as tP,NotEqualDepth as iP,EqualDepth as nP,RawShaderMaterial as Lb,BatchedMesh as Db,LinearFilter as Ud,UnsignedByteType as oP,MeshPhysicalMaterial as jb,RingGeometry as sP,Line3 as rP,AdditiveBlending as Bb,BoxHelper as aP,SpotLight as lP,DirectionalLightHelper as cP,CameraHelper as hP,LOD as dP,Triangle as uP,NormalBlending as pP,ReinhardToneMapping as Nm,LinearToneMapping as Wm,HalfFloatType as Vm,VideoTexture as mP,CatmullRomCurve3 as gP,MirroredRepeatWrapping as Fb,ShaderLib as zd,UniformsUtils as Ub,MeshNormalMaterial as fP,AudioContext as yP}from"./three.min.js";import{createLoaders as $m,LODsManager as wr,NEEDLE_progressive as He,getRaycastMesh as zb,addDracoAndKTX2Loaders as bP,configureLoader as _P,setKTX2TranscoderLocation as vP,setDracoDecoderLocation as wP}from"./gltf-progressive-Clq_N7Zx.min.js";import{GroundedSkybox as Ba,Font as xP,TextGeometry as SP,FontLoader as CP,GLTFLoader as Io,EXRLoader as Hm,RGBELoader as Nb,Stats as PP,nodeFrame as Wb,TransformControlsGizmo as Vb,OrbitControls as OP,PositionalAudioHelper as kP,HorizontalBlurShader as MP,VerticalBlurShader as RP,GLTFExporter as $b,strToU8 as Hb,zipSync as EP,XRControllerModelFactory as TP,XRHandMeshModel as AP,Line2 as IP,LineGeometry as LP,LineMaterial as DP,TransformControls as jP,InteractiveGroup as BP,HTMLMesh as FP,VertexNormalsHelper as UP,OBJLoader as Gm,FBXLoader as Gb,mergeVertices as zP}from"./three-examples.min.js";import{md5 as qb,v5 as Xb,ByteBuffer as NP,fetchProfile as WP,MotionController as VP,SIZE_PREFIX_LENGTH as Qb,Builder as qm,createNoise4D as $P,Matrix4 as Xm,BatchedParticleRenderer as HP,ParticleSystem as GP,RenderMode as Lo,ConstantColor as qP,Vector4 as XP,ConstantValue as QP,TrailParticle as Yb,WorkerBase as YP,MeshBVH as ZP}from"./vendor-DDo_PRrS.min.js";import{__webpack_exports__default as Pe,__webpack_exports__Text as Zb,__webpack_exports__update as KP,__webpack_exports__Block as Kb,SimpleStateBehavior as JP,__webpack_exports__Inline as Qm,__webpack_exports__FontLibrary as Jb,ThreeMeshUI as e_}from"./three-mesh-ui-n3JU4M2W.min.js";import{EffectAttribute as eO}from"./postprocessing-B_9sKVU7.min.js";const t_=typeof window!==void 0?window.location.search.includes("debugcontext"):!1;var ue=(o=>(o.ContextRegistered="ContextRegistered",o.ContextCreationStart="ContextCreationStart",o.ContextCreated="ContextCreated",o.ContextFirstFrameRendered="ContextFirstFrameRendered",o.ContextDestroying="ContextDestroying",o.ContextDestroyed="ContextDestroyed",o.MissingCamera="MissingCamera",o.ContextClearing="ContextClearing",o.ContextCleared="ContextCleared",o))(ue||{});class pe{static get Current(){return globalThis["NeedleEngine.Context.Current"]}static set Current(e){globalThis["NeedleEngine.Context.Current"]=e}static get All(){return this.Registered}static Registered=[];static register(e){this.Registered.indexOf(e)===-1&&(t_&&console.warn("Registering context"),this.Registered.push(e),this.dispatchCallback("ContextRegistered",e))}static unregister(e){const t=this.Registered.indexOf(e);t!==-1&&(t_&&console.warn("Unregistering context"),this.Registered.splice(t,1))}static _callbacks={};static registerCallback(e,t){this._callbacks[e]||(this._callbacks[e]=[]),this._callbacks[e].push(t)}static unregisterCallback(e,t){if(!this._callbacks[e])return;const i=this._callbacks[e].indexOf(t);i!==-1&&this._callbacks[e].splice(i,1)}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 s=new Array;return this._callbacks[e].forEach(r=>{const a=r(n);a instanceof Promise&&s.push(a)}),Promise.all(s)}static addContextCreatedCallback(e){this.registerCallback("ContextCreated",e)}static addContextDestroyedCallback(e){this.registerCallback("ContextDestroyed",e)}}const Ym=new Map;function Ti(o=globalThis.location?.hostname){if(Ym.has(o))return Ym.get(o);const e=/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|localhost/.test(o);return Ym.set(o,e),e===!0}function i_(){return window.location.hostname.includes("glitch.me")}const n_=()=>o=>o;function tO(o){return n_()(o)}function iO(){return!!w("debug")}class Ai{_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 xr=!1;const Zm=new Array;typeof window<"u"&&setTimeout(()=>{if(xr){const o={},e=new URL(window.location.href),t=new URL(e);t.searchParams.append("console","");const i=t.toString().replace(/=$|=(?=&)/g,"");for(const s of Zm){const r=new URL(e);r.searchParams.append(s,""),o[s]=r.toString().replace(/=$|=(?=&)/g,"")}console.log(`\u{1F335} ?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=xr===!0?"":` (containing "${xr}")`;console.group("Available URL parameters:"+n);for(const s of Object.keys(o).sort())typeof xr=="string"&&!s.toLowerCase().includes(xr.toLowerCase())||(console.groupCollapsed(s),console.log("Reload with this flag enabled:"),console.log(o[s]),console.groupEnd());console.groupEnd()}},100);function pc(){return new URLSearchParams(globalThis.location?.search)}function w(o){xr&&!Zm.includes(o)&&Zm.push(o);const e=pc();if(e.has(o)){const t=e.get(o);if(t){const i=Number(t);return isNaN(i)?t:i}else return!0}return!1}xr=w("help");function nO(o,e){const t=pc();t.has(o)?t.set(o,e):t.append(o,e),document.location.search=t.toString()}function mc(o,e,t=!0){const i=pc();i.has(o)?e===null?i.delete(o):i.set(o,e):e!==null&&i.append(o,e),t?o_(o,i):Jm(o,i)}function Km(o,e,t){o.has(e)?o.set(e,t.toString()):o.append(e,t.toString())}function o_(o,e,t){window.history.pushState(t,o,"?"+e.toString())}function Jm(o,e,t){window.history.replaceState(t,o,"?"+e.toString())}function oO(o){for(var e="",t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",i=t.length,n=0;n<o;n++)e+=t.charAt(Math.floor(Math.random()*i));return e}function sO(o,e){return Math.floor(Math.random()*(e-o+1))+o}const s_=["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"],r_=["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 a_(){const o=s_[Math.floor(Math.random()*s_.length)],e=r_[Math.floor(Math.random()*r_.length)];return o+"_"+e}function l_(o){return o=o.replace(/[^a-z0-9áéíóúñü \.,_-]/gim,""),o.trim()}function Fa(o,e,t=!0,i=!1){if(e==null)return null;if(e.userData&&e.userData.guid===o||e.guid==o)return e;if(i&&e.userData?.components){for(const n of e.userData.components)if(n.guid===o)return n}if(t){if(e.scenes)for(const n in e.scenes){const s=e.scenes[n],r=Fa(o,s,t,i);if(r)return r}if(e.children)for(const n in e.children){const s=e.children[n],r=Fa(o,s,t,i);if(r)return r}}}function gc(o,e){if(o!=null&&typeof o=="object"){let t;Array.isArray(o)?t=[]:(t=Object.create(o),Object.assign(t,o));for(const i of Object.keys(o)){const n=o[i];e&&!e(o,i,n)?t[i]=n:n?.clone!==void 0&&typeof n.clone=="function"?t[i]=n.clone():t[i]=gc(n,e)}return t}return o}function Do(o){return new Promise((e,t)=>{setTimeout(e,o)})}function fc(o,e){if(o<=0)return Promise.resolve();if(e||(e=pe.Current),!e)return Promise.reject("No context");const t=e.time.frameCount+o;return new Promise((i,n)=>{if(!e)return n("No context");const s=()=>{e.time.frameCount>=t&&(e.pre_update_callbacks.splice(e.pre_update_callbacks.indexOf(s),1),i())};e.pre_update_callbacks.push(s)})}const Nd=w("debugresolveurl"),c_="rel:";function rO(o,e){return jo(o,e)}function jo(o,e){if(e===void 0)return Nd&&console.warn("getPath: uri is undefined, returning uri",e),e;if(e.startsWith("./"))return e;if(e.startsWith("http"))return Nd&&console.warn("getPath: uri is absolute, returning uri",e),e;if(o===void 0)return Nd&&console.warn("getPath: source is undefined, returning uri",e),e;e.startsWith(c_)&&(e=e.substring(4));const t=o.lastIndexOf("/");if(t>=0){const i=o.substring(0,t+1);for(;i.endsWith("/")&&e.startsWith("/");)e=e.substring(1);const n=i+e;return Nd&&console.log("source:",o,`changed uri from`,e,` to `,n,` basePath: `+i),n}return e}function h_(o){if(o)return o=o.trim(),o=o.split("?")[0]?.split("#")[0],o}class aO{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=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:n=>{e[this._wrapperProp]=n;for(const s of this.writeCallbacks)s(n,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 gs{_watches=[];constructor(e,t){if(Array.isArray(t))for(const i of t)this._watches.push(new gs(e,i));else this._watches.push(new aO(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 Ua=Symbol("needle:watches");function Wd(o,e){if(!o[Ua])if(o instanceof K)o[Ua]=new gs(o,["x","y"]);else if(o instanceof b)o[Ua]=new gs(o,["x","y","z"]);else if(o instanceof ye||o instanceof N)o[Ua]=new gs(o,["x","y","z","w"]);else return!1;return o[Ua].subscribeWrite(e),!0}function eg(o,e){if(!o)return;const t=o[Ua];t&&t.unsubscribeWrite(e)}var I;(o=>{let e;function t(){if(e!==void 0)return e;const te=window.navigator.userAgent,$e=/Windows|MacOS|Mac OS/.test(te),hi=/Windows NT/.test(te)&&/Edg/.test(te)&&!/Win64/.test(te);return e=$e&&!hi&&!k()}o.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)}o.isMobileDevice=n;function s(){return a()}o.isIPad=s;let r;function a(){if(r!==void 0)return r;const te=navigator.userAgent.toLowerCase();return r=/iPad/.test(navigator.userAgent)||te.includes("macintosh")&&"ontouchend"in document}o.isiPad=a;let l;function c(){return l!==void 0?l:l=/Android/.test(navigator.userAgent)}o.isAndroidDevice=c;let h;function d(){return h!==void 0?h:h=/WebXRViewer\//i.test(navigator.userAgent)}o.isMozillaXR=d;let p;function m(){return p!==void 0?p:p=/NeedleAppClip\//i.test(navigator.userAgent)}o.isNeedleAppClip=m;let f;function g(){if(f!==void 0)return f;if(k()||a())return f=!1;const te=navigator.userAgent.toLowerCase();return navigator.userAgentData?f=navigator.userAgentData.platform==="macOS":f=te.includes("mac os x")||te.includes("macintosh")}o.isMacOS=g;let y;function _(){return y!==void 0?y:y=a()&&"xr"in navigator&&G()}o.isVisionOS=_;let v;const P=["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"];function k(){return v!==void 0?v:v=P.includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"ontouchend"in document}o.isiOS=k;let O;function j(){return O!==void 0||(O=/^((?!chrome|android).)*safari/i.test(navigator.userAgent)),O}o.isSafari=j;let L;function V(){return L!==void 0?L:L=navigator.userAgent.includes("OculusBrowser")}o.isQuest=V;let W;function G(){return W!==void 0||(W=document.createElement("a").relList.supports("ar")),W}o.supportsQuickLookAR=G;async function X(){try{return(await navigator.permissions.query({name:"microphone"})).state!=="denied"}catch(te){return console.error("Error querying `microphone` permissions.",te),!1}}o.microphonePermissionsGranted=X;let E;function $(){if(E!==void 0)return E;const te=navigator.userAgent.match(/iPhone OS (\d+_\d+)/);if(te&&(E=te[1].replace("_",".")),!E){const $e=navigator.userAgent.match(/(?:\(Macintosh;|iPhone;|iPad;).*Version\/(\d+\.\d+)/);$e&&(E=$e[1])}return E||(E=null),E}o.getiOSVersion=$;let q;function he(){if(q!==void 0)return q;const te=navigator.userAgent.match(/(?:CriOS|Chrome)\/(\d+\.\d+\.\d+\.\d+)/);return te?q=te[1].replace("_","."):q=null,q}o.getChromeVersion=he;let re;function ge(){if(re!==void 0)return re;const te=navigator.userAgent.match(/Version\/(\d+\.\d+)/);return te&&j()?re=te[1]:re=null,re}o.getSafariVersion=ge})(I||(I={}));function lO(){return I.isDesktop()}function cO(){return I.isMobileDevice()}function hO(){return I.isiPad()}function dO(){return I.isiPad()}function uO(){return I.isAndroidDevice()}function pO(){return I.isMozillaXR()}function mO(){return I.isMacOS()}function gO(){return I.isiOS()}function fO(){return I.isSafari()}function yO(){return I.isQuest()}async function bO(){return I.microphonePermissionsGranted()}const Cs=new WeakMap;function tg(o,e,t){if(!Cs.get(o)){const n=new MutationObserver(s=>{_O(o,s)});Cs.set(o,{observer:n,attributeChangedListeners:new Map}),n.observe(o,{attributes:!0})}const i=Cs.get(o).attributeChangedListeners;return i.has(e)||i.set(e,[]),i.get(e).push(t),()=>{ig(o,e,t)}}function ig(o,e,t){if(!Cs.get(o))return;const i=Cs.get(o).attributeChangedListeners;if(!i.has(e))return;const n=i.get(e),s=n.indexOf(t);s!==-1&&(n.splice(s,1),n.length<=0&&(i.delete(e),Cs.get(o)?.observer.disconnect(),Cs.delete(o)))}function _O(o,e){const t=Cs.get(o).attributeChangedListeners;for(const i of e)if(i.type==="attributes"){const n=i.attributeName,s=o.getAttribute(n);if(t.has(n))for(const r of t.get(n))r(s)}}class ng{reason;constructor(e){this.reason=e}}async function og(o){const e=await Promise.allSettled(o).catch(n=>[new ng(n.message)]);let t=!1;const i=e.map(n=>"value"in n?n.value:(t=!0,new ng(n.reason)));return{anyFailed:t,results:i}}const vO=w("debugdebug");let sg=!1;(w("noerrors")||w("nooverlaymessages"))&&(sg=!0);const rg="needle_engine_global_error_container";var Ii=(o=>(o[o.Log=0]="Log",o[o.Warn=1]="Warn",o[o.Error=2]="Error",o))(Ii||{});function d_(){return m_}const ag=new Array;function wO(o){ag.push(o)}let lg=!1;function xO(...o){if(!lg){lg=!0;try{for(let e=0;e<ag.length;e++)ag[e](...o)}catch(e){console.error(e)}lg=!1}}const u_=console.error,SO=function(...o){u_.apply(console,o),OO(o),Sr(2,o,{}),PO(...o)};function p_(o){sg=!o,o?console.error=SO:console.error=u_}function CO(o){return p_(o)}let m_=0;function PO(...o){m_+=1,xO(...o)}function OO(o){if(Array.isArray(o))for(let e=0;e<o.length;e++){const t=o[e];typeof t=="string"&&t.startsWith("THREE.PropertyBinding: Trying to update node for track:")&&(o[e]="Some animated objects couldn't be found: see console for details")}}const g_=new Set;function Sr(o,e,t={},i,n){if(sg)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(g_.has(a))return;g_.add(a)}const s=pe.Current;let r=s?.domElement??document.querySelector("needle-engine");if(s?.isInAR&&(r=s.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||kO(o,r,e,t)}}const za=new Map,f_=.2;function kO(o,e,t,i={}){if(t==null)return;const n=EO(e);if(n.childElementCount>=20){const c=n.lastElementChild;b_(c)}t.length>400&&(t=t.substring(0,400)+"...");const s=i.key??t;if(za.has(s)){za.get(s)?.update(t,i);return}const r=TO(o,t);n.prepend(r);const a=()=>{za.delete(s),b_(r)};let l=setTimeout(a,Math.max(f_,i.duration??10)*1e3);za.set(s,{update:(c,h)=>{c.length>400&&(c=c.substring(0,400)+"..."),r.innerHTML=c,h.duration&&(clearTimeout(l),l=setTimeout(a,Math.max(f_,h.duration)*1e3))},removeFunction:a})}function MO(){vO&&console.log("Clearing messages");for(const o of za.values())o?.removeFunction.call(o);za.clear()}const RO=` @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 EO(o){globalThis[rg]||(globalThis[rg]=new Map);const e=globalThis[rg];if(e.has(o))return e.get(o);{const t=document.createElement("div");e.set(o,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; `,I.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"),o.shadowRoot?o.shadowRoot.appendChild(t):o.appendChild(t);const n=document.createElement("style");return n.innerHTML=RO,t.appendChild(n),t}}const y_=Symbol("logtype"),Vd=new Map;function b_(o){o.remove();const e=o[y_],t=Vd.get(e)??[];t.push(o),Vd.set(e,t)}function TO(o,e){if(Vd.has(o)){const i=Vd.get(o);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[y_]=o,o){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 AO=w("nodevlogs");let cg,hg;function A(){if(AO)return!1;if(cg!==void 0)return cg;if(hg!==void 0)return hg;let o=Ti();return o||(o=window.location.hostname.endsWith(".local-credentialless.webcontainer.io")),hg=o,o}function IO(o){cg=o}class LO{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()}randomVector3(e,t=0,i=1){e.x=this.random(t,i),e.y=this.random(t,i),e.z=this.random(t,i)}clamp(e,t,i){return e<t?t:e>i?i:e}clamp01(e){return this.clamp(e,0,1)}lerp(e,t,i){return i=i<0?0:i,i=i>1?1:i,e+(t-e)*i}inverseLerp(e,t,i){return(i-e)/(t-e)}remap(e,t,i,n,s){return n+(s-n)*(e-t)/(i-t)}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;toDegrees(e){return e*180/Math.PI}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)}approximately(e,t,i=Number.EPSILON){for(const n of DO){const s=e[n],r=t[n];if(s===void 0||r===void 0)break;if(Math.abs(s-r)>i)return!1}return!0}easeInOutCubic(e){return e<.5?4*e*e*e:1-Math.pow(-2*e+2,3)/2}}const DO=["x","y","z","w"],D=new LO;class __{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 $d{freq;minCutOff;beta;dCutOff;x;dx;lasttime;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 __(this.alpha(this.minCutOff)),this.dx=new __(this.alpha(this.dCutOff)),this.lasttime=null}alpha(e){const t=1/this.freq;return 1/(1+1/(2*Math.PI*e)/t)}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,s=this.dx.filter(n,this.alpha(this.dCutOff)),r=this.minCutOff+this.beta*Math.abs(s);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 dg{x;y;z;constructor(e,t=1,i=0,n=1){this.x=new $d(e,t,i,n),this.y=new $d(e,t,i,n),this.z=new $d(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 Hd="needle:cameraController";function v_(o){return o[Hd]}function ug(o,e,t){t?o[Hd]=e:o[Hd]===e&&(o[Hd]=null)}const pg="needle:autofit";function w_(o){return o[pg]===void 0?!0:o[pg]!==!1}function Gd(o,e){o[pg]=e}let Cn;const jO={x:0,y:0,width:0,height:0},BO=w("debugfocusrect");function FO(o,e,t,i,n){o instanceof Element&&(BO&&o instanceof HTMLElement&&(o.style.outline="2px dashed rgba(255, 150, 0, .8)"),o=o.getBoundingClientRect()),Cn=n.domElement.getBoundingClientRect();const s=jO;s.x=o.x,s.y=o.y,s.width=o.width,s.height=o.height,s.x-=Cn.x,s.y-=Cn.y;const r=Cn.width,a=Cn.height,l=i.view,c=e.zoom;let h=l?.offsetX||0,d=l?.offsetY||0,p=Cn.width,m=Cn.height;p/=c,m/=c,h=p*(c-1)*.5,d=m*(c-1)*.5;const f=s.x+s.width*.5,g=s.y+s.height*.5,y=Cn.width*.5,_=Cn.height*.5,v=f-y,P=g-_;h-=v/c,d-=P/c,e.offsetX!==void 0&&(h+=e.offsetX*(Cn.width*.5)),e.offsetY!==void 0&&(d-=e.offsetY*(Cn.height*.5));const k=l?.offsetX||h,O=l?.offsetY||d;h=D.lerp(k,h,t),d=D.lerp(O,d,t);const j=l?.width||r,L=l?.height||a;p=D.lerp(j,p,t),m=D.lerp(L,m,t),i.setViewOffset(r,a,h,d,p,m),i.updateProjectionMatrix(),e.damping>0&&(e.damping*=1-t,e.damping<.01&&(e.damping=0),e.damping=Math.max(0,e.damping))}function x_(o,e,t){const i=o.length(),n=e.length(),s=D.lerp(i,n,t);return o.lerp(e,t).normalize().multiplyScalar(s)}const mg=new N,S_=new N().setFromAxisAngle(new b(0,1,0),Math.PI);function UO(o,e){o.lookAt(e),o.quaternion.multiply(S_)}function yc(o,e,t=!0,i=!1){if(o===e)return;mg.copy(o.quaternion);const n=ee(e),s=ee(o);if(i){if(Pn(o,_e(e)),t){const r=s.y,a=s.sub(M_(o));a.y=r,o.lookAt(a),o.quaternion.multiply(S_)}Number.isNaN(o.quaternion.x)&&o.quaternion.copy(mg);return}t&&(n.y=s.y),o.lookAt(n),Number.isNaN(o.quaternion.x)&&o.quaternion.copy(mg)}function zO(o,e,t,i=1){if(t){const n=F(0,0,0),s=e.x/window.innerWidth*2-1,r=-(e.y/window.innerHeight)*2+1;n.set(s,r,0),n.unproject(t);const a=t.worldPosition,l=o.worldPosition.distanceTo(a),c=n.sub(a);c.multiplyScalar(i*3.6*l);const h=t.worldPosition.add(c);return o.lookAt(h),h}return null}const NO=new Ai(()=>new b,100);function F(o,e,t){const i=NO.get();return i.set(0,0,0),o instanceof b?i.copy(o):Array.isArray(o)?i.set(o[0],o[1],o[2]):o instanceof DOMPointReadOnly?i.set(o.x,o.y,o.z):typeof o=="number"?(i.x=o,i.y=e!==void 0?e:i.x,i.z=t!==void 0?t:i.x):typeof o=="object"&&(i.x=o.x,i.y=o.y,i.z=o.z),i}const WO=new Ai(()=>new oe,30);function C_(o){const e=WO.get();return o?e.copy(o):e.set(0,0,0),e}const VO=new Ai(()=>new N,100);function di(o,e,t,i){const n=VO.get();return n.identity(),o instanceof N?n.copy(o):o instanceof DOMPointReadOnly?n.set(o.x,o.y,o.z,o.w):typeof o=="number"&&e!==void 0&&t!==void 0&&i!==void 0?n.set(o,e,t,i):typeof o=="object"&&"x"in o&&"y"in o&&"z"in o&&"w"in o&&n.set(o.x,o.y,o.z,o.w),n}const gg=new Ai(()=>new b,100),P_=Symbol("lastMatrixWorldUpdateKey");function ee(o,e=null,t=!0){const i=e??gg.get();return o?o.parent?(t&&o.updateWorldMatrix(!0,!1),o.matrixWorldNeedsUpdate&&o[P_]!==Date.now()&&(o[P_]=Date.now(),o.updateMatrixWorld()),i.setFromMatrixPosition(o.matrixWorld),i):i.copy(o.position):i.set(0,0,0)}function bt(o,e){if(!o)return o;const t=gg.get();return e!==t&&t.copy(e),o.parent!==null&&o.parent.worldToLocal(t),o.position.set(t.x,t.y,t.z),o}function Cr(o,e,t,i){const n=gg.get();return n.set(e,t,i),bt(o,n),o}const qd=new Ai(()=>new N,100),Pr=new N,fg=new N;function _e(o,e=null){if(!o)return qd.get().identity();const t=e??qd.get();return o.parent?(o.getWorldQuaternion(t),t):t.copy(o.quaternion)}function Pn(o,e){if(!o)return;e!==Pr&&Pr.copy(e);const t=Pr;o?.parent?.getWorldQuaternion(fg),fg.invert();const i=fg.multiply(t);o.quaternion.set(i.x,i.y,i.z,i.w)}function yg(o,e,t,i,n){Pr.set(e,t,i,n),Pn(o,Pr)}const $O=new Ai(()=>new b,100),HO=new b;function Ge(o,e=null){return e||(e=$O.get()),o?o.parent?(o.getWorldScale(e),e):e.copy(o.scale):e.set(0,0,0)}function Na(o,e){if(!o)return;if(!o.parent){o.scale.copy(e);return}const t=HO;o.parent.getWorldScale(t),o.scale.copy(e),o.scale.divide(t)}const GO=new b,O_=new N;function qO(o){return _e(o,O_),GO.set(0,0,1).applyQuaternion(O_)}const XO=new Ai(()=>new b,100),k_=new N;function M_(o,e){return e||(e=XO.get().set(0,0,1)),_e(o,k_),e.applyQuaternion(k_)}const R_=new ct,E_=new ct,QO=new b;function bg(o){const e=qd.get();return o.getWorldQuaternion(e),E_.setFromQuaternion(e),E_}function _g(o,e){const t=qd.get();Pn(o,t.setFromEuler(e))}function Xd(o){const e=bg(o),t=QO;return t.set(e.x,e.y,e.z),t.x=D.toDegrees(t.x),t.y=D.toDegrees(t.y),t.z=D.toDegrees(t.z),t}function T_(o,e){bc(o,e.x,e.y,e.z,!0)}function bc(o,e,t,i,n=!0){n&&(e=D.toRadians(e),t=D.toRadians(t),i=D.toRadians(i)),R_.set(e,t,i),Pr.setFromEuler(R_),Pn(o,Pr)}function Qd(o,e=!0){o&&(e?function t(i){console.groupCollapsed((i.name?i.name:"(no name : "+i.type+")")+" %o",i),i.children.forEach(t),console.groupEnd()}(o):o.traverse(function(t){for(var i="|___",n=t;n.parent!==null;)i=" "+i,n=n.parent;console.log(i+t.name+" <"+t.type+">")}))}function YO(o){let e=o?.name||"";if(!o)return e;let t=o.parent;for(;t;)e=t.name+"/"+e,t=t.parent;return e}function A_(o){if(o){const e=o;return e.blendMode!==void 0&&e.clampWhenFinished!==void 0&&e.enabled!==void 0&&e.fadeIn!==void 0&&e.getClip!==void 0}return!1}class km extends Hn{static vertex=` varying vec2 vUv; void main(){ vUv = uv; gl_Position = vec4(position.xy, 0., 1.0); }`;constructor(){super({vertexShader:km.vertex,uniforms:{map:new Xi(null),flipY:new Xi(!0),writeDepth:new Xi(!1),depthTexture:new Xi(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 mr{static planeGeometry=new Sn(2,2,1,1);static renderer=new br({antialias:!1,alpha:!0});static perspectiveCam=new de;static orthographicCam=new Md;static scene=new qi;static blitMaterial=new km;static mesh=new H(mr.planeGeometry,mr.blitMaterial);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=km.vertex;const s=this.mesh;s.material=i,s.frustumCulled=!1,this.scene.children.length=0,this.scene.add(s),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:s=this.blitMaterial,flipY:r=!1,depthTexture:a=null,depthTest:l=!0,depthWrite:c=!0}=i||{};this.blitMaterial.reset(),s.uniforms.map&&(s.uniforms.map.value=e),s.uniforms.flipY&&(s.uniforms.flipY.value=r),a?(s.uniforms.writeDepth=new Xi(!0),s.uniforms.depthTexture.value=a):(s.uniforms.writeDepth=new Xi(!1),s.uniforms.depthTexture.value=null),s.needsUpdate=!0,s.uniformsNeedUpdate=!0;const h=this.mesh;h.material=s,h.frustumCulled=!1,this.scene.children.length=0,this.scene.add(h);const d=n.getRenderTarget(),p=n.getContext();l?p.enable(p.DEPTH_TEST):p.disable(p.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),p.enable(p.DEPTH_TEST),n.state.buffers.depth.setMask(!0)}static textureToCanvas(e,t=!1){if(!e)return null;(t===!0||e.isCompressedTexture===!0)&&(e=I_(e));const i=e.image;if(KO(i)){const n=document.createElement("canvas");n.width=i.width,n.height=i.height;const s=n.getContext("2d");return s?(s.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 I_(o){return mr.copyTexture(o)}function ZO(o,e=!1){return mr.textureToCanvas(o,e)}function KO(o){return typeof HTMLImageElement<"u"&&o instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&o instanceof HTMLCanvasElement||typeof OffscreenCanvas<"u"&&o instanceof OffscreenCanvas||typeof ImageBitmap<"u"&&o instanceof ImageBitmap}function JO(o){const e=o.type;return e==="Mesh"||e==="SkinnedMesh"}function vg(o,e){e?o["needle:rendercustomshadow"]=!0:o["needle:rendercustomshadow"]=!1}function L_(o){return!!(o&&(o["needle:rendercustomshadow"]===!0||o["needle:rendercustomshadow"]==null))}function ui(o,e=void 0,t=void 0,i=void 0){const n=i||new Nt;n.makeEmpty();const s=[];function r(l){let c=!0;if(l.visible&&w_(l)!==!1&&!(l.type==="TransformControlsGizmo"||l.type==="TransformControlsPlane")){if(l instanceof oC&&(c=!1),l instanceof Sb&&(c=!1),l instanceof Ba&&(c=!1),l.isGizmo===!0&&(c=!1),l.material instanceof xb&&(c=!1),JO(l)||(c=!1),t&&l.layers.test(t)===!1&&(c=!1),c&&(e&&Array.isArray(e)&&e?.includes(l)||typeof e=="function"&&e(l)===!0))return;if(l.isUI!==!0){if(c){const h=l.children;l.children=s;const d=l.position,p=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,p);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(o)||(o=[o]);for(const l of o)l&&(a=!0,l.updateMatrixWorld(),r(l));return a||console.warn("No objects to fit camera to..."),n}function D_(o,e,t){const i=ui([o],t?.ignore),n=new b;i.getSize(n);const s=new b;i.getCenter(s);const r=new b;e.getSize(r);const a=new b;e.getCenter(a);const l=new b;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&&Na(o,Ge(o).multiplyScalar(c)),t?.position!==!1){const d=new b;i.getCenter(d),d.y=i.min.y;const p=new b;e.getCenter(p),p.y=e.min.y;const m=p.clone().sub(d);h&&m.multiplyScalar(c),bt(o,ee(o).add(m))}return{boundsBefore:i,scale:l}}function j_(o,e){const t=ui([o]),i=new b;t.getCenter(i),i.y=t.min.y;const n=e.clone().sub(i),s=ee(o);return bt(o,s.add(n)),{offset:n,bounds:t}}function wg(o,e,t,i){if(Array.isArray(e)){let r=!0;for(let a=0;a<e.length;a++)wg(o,e[a],a,e)||(r=!1);return r}if(e.type==="MeshStandardMaterial"||e.type==="MeshBasicMaterial")return!1;if(e["material:fbx"]!=null)return!0;const n=new yt;n["material:fbx"]=e;const s=e;return s&&(s.map?n.color.set(1,1,1):n.color.copyLinearToSRGB(s.color),n.emissive.copyLinearToSRGB(s.emissive),n.emissiveIntensity=s.emissiveIntensity,n.opacity=s.opacity,n.displacementScale=s.displacementScale,n.transparent=s.transparent,n.bumpMap=s.bumpMap,n.aoMap=s.aoMap,n.map=s.map,n.displacementMap=s.displacementMap,n.emissiveMap=s.emissiveMap,n.normalMap=s.normalMap,n.envMap=s.envMap,n.alphaMap=s.alphaMap,n.metalness=s.reflectivity,n.vertexColors=s.vertexColors,s.shininess&&(n.roughness=1-Math.sqrt(s.shininess)/10),n.needsUpdate=!0),t===void 0?o.material=n:i[t]=n,!0}let Yd=!1;wO((...o)=>{A()&&pe.Current?.isInXR&&(Wa(!0),B_("error",...o))});function Wa(o){if(o){if(Yd)return;Yd=!0,tk()}else{if(!Yd)return;Yd=!1,ik()}}const _c={log:void 0,warn:void 0,error:void 0};class ek{familyName="needle-xr";root=null;context=null;defaultFontSize=.06;constructor(){this.ensureFont()}onEnable(){this.context=pe.Current||pe.All[0],this.context.pre_render_callbacks.push(this.onBeforeRender)}onDisable(){this.context?.pre_render_callbacks.splice(this.context?.pre_render_callbacks.indexOf(this.onBeforeRender),1),this.root?.removeFromParent()}targetObject=new M;userForwardViewPoint=new b;oneEuroFilter=new dg(90,.8);_lastElementRemoveTime=0;onBeforeRender=()=>{const e=this.context?.mainCamera;if(this.context&&e instanceof de){const t=this.getRoot();Number.isNaN(t.position.x)&&t.position.set(0,0,0),Number.isNaN(t.quaternion.x)&&t.quaternion.set(0,0,0,1),this.context.scene.add(this.targetObject);const i=this.context.xr?.rigScale??1,n=3.5*i,s=e.worldForward;s.y=0,s.normalize().multiplyScalar(n),this.userForwardViewPoint.copy(e.worldPosition).sub(s),this.targetObject.position.distanceTo(this.userForwardViewPoint)>2*i&&(this.targetObject.position.copy(this.userForwardViewPoint),yc(this.targetObject,e,!0,!0),this.targetObject.rotateY(Math.PI)),this.oneEuroFilter.filter(this.targetObject.position,t.position,this.context.time.time);const r=this.context.time.deltaTime;if(t.quaternion.slerp(this.targetObject.quaternion,r*5),t.scale.setScalar(i),this.targetObject.removeFromParent(),this.context.scene.add(t),this.context.time.time-this._lastElementRemoveTime>.1){this._lastElementRemoveTime=this.context.time.time;const a=Date.now();for(let l=0;l<this._activeTexts.length;l++){const c=this._activeTexts[l];if(c instanceof Pe.Text&&a-c._activatedTime>2e4){c.removeFromParent(),this._textBuffer.push(c),this._activeTexts.splice(l,1);break}}}}};addLog(e,t){const i=this.getRoot(),n=this.getText();let s=16777215,r=0;switch(e){case"log":s=16777215,r=0;break;case"warn":s=16772761,r=4465152;break;case"error":s=16755370,r=7798784;break}t.length>1e3&&(t=t.substring(0,1e3)+"...");const a=new Date().toISOString().split("T")[1].split(".")[0];n.textContent="["+a+"] "+t,n.visible=!0,n._activatedTime=Date.now(),i.add(n),this._activeTexts.push(n),this.context&&this.context.scene.add(i),n.set({backgroundColor:s,color:r}),Pe.update()}ensureFont(){let e=Pe.FontLibrary.getFontFamily(this.familyName);e||(e=Pe.FontLibrary.addFontFamily(this.familyName),e.addVariant("normal","normal","https://cdn.needle.tools/static/fonts/msdf/arial/arial-msdf.json","https://cdn.needle.tools/static/fonts/msdf/arial/arial.png")?.addEventListener("ready",()=>{Pe.update()}))}textOptions={fontSize:this.defaultFontSize,fontFamily:this.familyName,padding:.03,margin:.005,color:0,backgroundColor:16777215,backgroundOpacity:.4,borderRadius:.03,offset:.025};_textBuffer=[];_activeTexts=[];getText(){const e=this.getRoot();if(this._textBuffer.length>0){const i=this._textBuffer.pop();return i.visible=!0,setTimeout(()=>this.disableDepthTestRecursive(i),100),i}if(e.children.length>20&&this._activeTexts.length>0)return this._activeTexts.shift();const t=new Pe.Text(this.textOptions);return setTimeout(()=>this.disableDepthTestRecursive(t),500),setTimeout(()=>this.disableDepthTestRecursive(t),1500),t}disableDepthTestRecursive(e,t=0){for(let n=0;n<e.children.length;n++){const s=e.children[n];s instanceof M&&this.disableDepthTestRecursive(s,t+1)}e.renderOrder=10*t,e.layers.set(2);const i=e.material;i&&(i.depthWrite=!1,i.depthTest=!1,i.transparent=!0),t===0&&Pe.update()}getRoot(){if(this.root)return this.root;const e=this.defaultFontSize,t={boxSizing:"border-box",fontFamily:this.familyName,width:"2.6",fontSize:e,color:0,lineHeight:1,backgroundColor:16777215,backgroundOpacity:0,whiteSpace:"pre-wrap",flexDirection:"column-reverse"};return this.root=new Pe.Block(t),this.root}}let Or=null;function tk(){Or||(Or=new ek),Or.onEnable();for(const o in _c){_c[o]=console[o];let e=!1;console[o]=function(){if(_c[o]?.apply(console,arguments),!e)try{e=!0,B_(o,...arguments)}finally{e=!1}}}}function ik(){Or?.onDisable();for(const o in _c)console[o]=_c[o]}const vc=new Map;function B_(o,...e){try{switch(vc.clear(),o){case"log":Or?.addLog("log",t());break;case"warn":Or?.addLog("warn",t());break;case"error":Or?.addLog("error",t());break}}catch(s){console.error("Error in spatial console",s)}finally{vc.clear()}function t(){let s="";for(let r=0;r<e.length;r++){const a=e[r];s+=i(a),r<e.length-1&&(s+=", ")}return s}function i(s,r=0){if(typeof s=="string")return'"'+s+'"';if(typeof s=="number"){if(s%1!==0){const a=s.toFixed(5),l=a.indexOf(".");let c=a.length-1;for(;c>l&&a[c]==="0";)c--;return a.substring(0,c+1)}return s.toString()}else if(Array.isArray(s)){let a="[";for(let l=0;l<s.length;l++){const c=s[l];a+=i(c,r+1),l<s.length-1&&(a+=", ")}return a+="]",a}else{if(s===null)return"null";if(s===void 0)return"undefined";if(typeof s=="function")return s.name+"()"}if(s instanceof K)return`(${i(s.x)}, ${i(s.y)})`;if(s instanceof b)return`(${i(s.x)}, ${i(s.y)}, ${i(s.z)})`;if(s instanceof ye)return`(${i(s.x)}, ${i(s.y)}, ${i(s.z)}, ${i(s.w)})`;if(s instanceof N)return`(${i(s.x)}, ${i(s.y)}, ${i(s.z)}, ${i(s.w)})`;if(s instanceof we||s instanceof Se)return s.name;if(s instanceof Cb)return`[${s.elements.join(", ")}]`;if(s instanceof J)return`[${s.elements.join(", ")}]`;if(s instanceof ws)return s.mask.toString();if(typeof s=="object"){if(vc.has(s))return"*";let a=`{ `;a+=n(r);const l=Object.keys(s);let c="";for(let h=0;h<l.length;h++){const d=l[h],p=s[d];if(vc.has(p)){c+="";continue}vc.set(p,!0),c+=d+":"+i(p,r+1),h<l.length-1&&(c+=", "),c.length>=60&&(c+=` `,c+=n(r),a+=c,c="")}return a+=c,a+=` }`,a}return s}function n(s){let r="";for(let a=0;a<s;a++)r+=" ";return r}}function ke(o,e){Sr(e?.type??Ii.Log,o,e)}function be(o,e){ke(o,{...e,type:Ii.Warn})}function wc(o,e){ke(o,{...e,type:Ii.Error})}let pi,kr=null,qn=null,xc=!1,F_=null;const U_="terminal",nk=w("console");nk&&xg();const ok=Symbol("consoleParent");function xg(){if(pi){pi.showSwitch();return}ck()}function z_(){pi&&(pi.hide(),pi.hideSwitch())}function sk(){F_||(F_=setInterval(rk,500))}let N_=0;function rk(){const o=d_(),e=o!==N_;N_=o,e&&ak()}function ak(){xg(),qn&&(qn.setAttribute("error","true"),qn.innerText="\u{1F92C}")}function lk(){qn&&(qn.removeAttribute("error"),qn.innerText=U_)}function ck(o=!1){if(pi!==void 0||xc)return;xc=!0;const e=document.createElement("script");e.onload=()=>{if(!globalThis.VConsole){console.warn("\u{1F335} Debug console failed to load."),xc=!1,pi=null;return}xc=!1,sk(),pi=new VConsole({pluginOrder:["default","needle-console"]});const t=globalThis["needle:codegen_files"];if(t&&t.length>0&&pi.addPlugin(hk()),pi.addPlugin(mk()),pi.addPlugin(gk()),kr=Ok(),kr&&(kr[ok]=kr.parentElement,kr.style.position="absolute",kr.style.zIndex=Number.MAX_SAFE_INTEGER.toString()),pi.setSwitchPosition(20,30),qn=Pk(),qn){qn.innerText=U_,qn.addEventListener("click",lk);const i=document.createElement("style"),n=40;i.innerHTML=` #__vconsole .vc-switch { border: 1px solid rgba(255, 255, 255, .1); border-radius: 50%; width: ${n}px; height: ${n}px; padding: 0; line-height: ${n}px; font-size: ${n*.4}px; text-align: center; background: #ffffff5c; backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); user-select: none; pointer-events: auto; transition: transform .2s ease-in-out; box-shadow: 0px 7px 0.5rem 0px rgb(0 0 0 / 6%), inset 0px 0px 1.3rem rgba(0,0,0,.05); font-family: 'Material Symbols Outlined'; color: black; font-size: 2.3em; font-weight: 100; } #__vconsole .vc-switch:hover { cursor: pointer; transform: scale(1.1); transition: transform .1s ease-in-out, background .1s linear; background: rgba(245, 245, 245, .8); outline: rgba(0, 0, 0, .05) 1px solid; } #__vconsole .vc-switch[error] { background: rgba(255,0,0,.2); animation: vconsole-notify 1s ease-in-out; line-height: 35px; } @keyframes vconsole-notify { from { transform: scale(1, 1); } 10% { transform: scale(1.3, 1.3); } 70% { transform: scale(1.4, 1.4); } to { transform: scale(1, 1); } } #__vconsole .vc-panel { font-family: monospace; font-size: 11px; } #__vconsole .vc-plugin-box.vc-actived { height: 100%; } #__vconsole .vc-mask { overflow: hidden; } `,kr?.prepend(i),o===!0&&d_()<=0&&z_(),console.log("\u{1F335} Debug console has loaded")}},e.onerror=()=>{console.warn("\u{1F335} Debug console failed to load."+(window.crossOriginIsolated?"This page is using cross-origin isolation, so external scripts can't be loaded.":"")),xc=!1,pi=null},e.src="https://cdn.jsdelivr.net/npm/vconsole@3.15.1/dist/vconsole.min.js",document.body.appendChild(e)}function hk(){if(!globalThis.VConsole)return;const o=new VConsole.VConsolePlugin("needle-console","\u{1F335} Inspect glTF"),e=()=>document.querySelector("#__vc_plug_"+o._id+" iframe");return o.on("renderTab",function(t){const i=globalThis["needle:codegen_files"];if(!i||i.length===0)return;let n=globalThis["needle:codegen_files"][0];const s=n.indexOf("?");s>-1&&(n=n.substring(0,s));const r=location.protocol+"//"+location.host+location.pathname+"/"+n,a=encodeURIComponent(r);o.fullUrl="https://viewer.needle.tools?inspect&file="+a;var l='<iframe src="" style="width: 100%; height: 99%; border: none;"></iframe>';t(l)}),o.on("show",function(){const t=e();t&&t.src!==o.fullUrl&&(t.src=o.fullUrl)}),o.on("hide",function(){const t=e();t&&(t.src="")}),o.on("addTopBar",function(t){var i=new Array;i.push({name:"Open in new window \u2197",onClick:function(n){window.open(o.fullUrl,"_blank"),pi?.hide()}}),i.push({name:"Reload",onClick:function(n){const s=e();s&&(s.src=o.fullUrl)}}),i.push({name:"Fullscreen",onClick:function(n){const s=e();s.requestFullscreen?s.requestFullscreen():s.webkitRequestFullscreen instanceof Function&&s.webkitRequestFullscreen()}}),t(i)}),o}const Sg="padding: 10px; font-family: monospace;",W_="margin-bottom: 10px;",Mr="margin-bottom: 10px; margin-top: 15px;",dk="width: 100%; border-collapse: collapse; border: 1px solid rgba(0,0,0,0.1); table-layout: fixed;",V_="border: 1px solid rgba(0,0,0,0.1); padding: 5px;",uk=V_,pk=V_+" word-break: break-all;";function Xn(o,e=!1){e&&o.sort((i,n)=>(n.value?1:0)-(i.value?1:0));let t=`<table style='${dk}'>`;t+="<tbody>";for(const i of o){const n=typeof i.value=="boolean"?i.value?"\u2705":"\u274C":i.value;t+=`<tr><td style='${uk}'>${i.label}</td><td style='${pk}'>${n}</td></tr>`}return t+="</tbody></table>",t}function $_(){try{if(document.createElement("canvas").getContext("webgl2"))return"\u2705"}catch{}return"\u274C"}function mk(){if(!globalThis.VConsole)return;const o=new VConsole.VConsolePlugin("device-utilities","\u{1F4F1} Device Info");return o.on("renderTab",function(e){let t=`<div style='${Sg}'>`;const i=Ck();t+=`<h3 style='${W_}'>Device: ${i}</h3>`,t+=Xn([{label:"\u{1F4BB} Desktop",value:I.isDesktop()},{label:"\u{1F4F1} Mobile Device",value:I.isMobileDevice()},{label:"\u{1F34E} iOS",value:I.isiOS()},{label:"\u{1F4F1} iPad",value:I.isiPad()},{label:"\u{1F916} Android",value:I.isAndroidDevice()},{label:"\u{1F98A} Mozilla XR",value:I.isMozillaXR()},{label:"\u{1F335} Needle App Clip",value:I.isNeedleAppClip()},{label:"\u{1F34F} macOS",value:I.isMacOS()},{label:"\u{1F453} VisionOS",value:I.isVisionOS()},{label:"\u{1F9ED} Safari",value:I.isSafari()},{label:"\u{1F576}\uFE0F Meta Quest",value:I.isQuest()},{label:"\u{1F517} QuickLook AR Support",value:I.supportsQuickLookAR()}],!0);const n=[],s=I.getiOSVersion();s&&n.push({label:"\u{1F34E} iOS Version",value:s});const r=I.getChromeVersion();r&&n.push({label:"\u{1F310} Chrome Version",value:r});const a=I.getSafariVersion();a&&n.push({label:"\u{1F9ED} Safari Version",value:a}),n.length>0&&(t+=Xn(n,!1)),t+="</div>",t+=`<div style='${Sg} margin-top: 20px;'>`,t+=`<h3 style='${W_}'>User Agent Info</h3>`;const l=[{label:"User Agent",value:navigator.userAgent},{label:"Platform",value:navigator.platform},{label:"App Version",value:navigator.appVersion},{label:"User Agent Data",value:navigator.userAgentData?`Platform: ${navigator.userAgentData.platform}, Mobile: ${navigator.userAgentData.mobile}`:"Not supported"},{label:"WebXR",value:"xr"in navigator?"\u2705":"\u274C"},{label:"WebGPU",value:"gpu"in navigator?"\u2705":"\u274C"},{label:"WebGL 2",value:$_()}];t+=Xn(l,!1),t+="</div>",e(t)}),o}function gk(){if(!globalThis.VConsole)return;const o=new VConsole.VConsolePlugin("graphics-info","\u{1F3A8} Graphics Info");return o.on("renderTab",async function(e){let t=`<div style='${Sg}'>`;const i=fk();i.length>0&&(t+=`<h3 style='${Mr}'>General GPU Info</h3>`,t+=Xn(i,!1));const n=bk();n.length>0&&(t+=`<h3 style='${Mr}'>WebGL</h3>`,t+=Xn(n,!1));const s=_k();s.lengt