incanto 0.25.4 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/2d.js +1 -1
- package/dist/3d.d.ts +140 -2
- package/dist/3d.js +5 -5
- package/dist/{create-game-iYptFr-q.js → create-game-C0bPoURs.js} +1 -1
- package/dist/{create-game-DyAPwm0j.js → create-game-DUAtTqID.js} +3 -3
- package/dist/env.d.ts +6 -0
- package/dist/env.js +8 -5
- package/dist/{gameplay-BFzBVqhr.js → gameplay-Ddk13pQ6.js} +229 -2
- package/dist/gameplay.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{physics-3d-ob23XE0Y.js → physics-3d-4mGzOZ2J.js} +2 -2
- package/dist/react.js +1 -1
- package/dist/{register-CmtGqGSS.js → register-DcHXS1MA.js} +426 -17
- package/dist/test.js +4 -4
- package/editor/assets/{agent8-DzaYTNiK.js → agent8-DElIPozC.js} +1 -1
- package/editor/assets/{index-BGtXxzJn.js → index-BrneVqN0.js} +145 -49
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +115 -0
- package/skills/incanto-environment.md +88 -9
- package/skills/incanto-node-reference.md +15 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
|
@@ -4784,6 +4784,12 @@ uniform float uReflectivityMax;
|
|
|
4784
4784
|
// Both cures are the same: filter the depth over its own texel footprint and
|
|
4785
4785
|
// estimate gradients from those taps instead of from fwidth().
|
|
4786
4786
|
uniform vec2 uScenePassTexel;
|
|
4787
|
+
// incanto CUTOUTS (a boat's inside, a diving bell, a well under a dock) are
|
|
4788
|
+
// NOT a fragment test — nothing here knows about them. A cutout stamps its
|
|
4789
|
+
// OWNER'S OWN geometry into the depth pre-pass at the near plane, so the
|
|
4790
|
+
// occlusion discard below removes the water for exactly the pixels that owner
|
|
4791
|
+
// already covers. That is what makes a hole in open sea impossible: this
|
|
4792
|
+
// shader can only ever hide water behind something the player is looking at.
|
|
4787
4793
|
/** Shoreline dissolve width, in DEPTH TEXELS (≈2 screen px each). */
|
|
4788
4794
|
const float SHORE_FADE_TEXELS = 11.0;
|
|
4789
4795
|
/** Deepest water that can still be a shoreline (m) — past this the fade is off. */
|
|
@@ -5161,6 +5167,7 @@ void main() {
|
|
|
5161
5167
|
depthMask = 1.0 - smoothstep(softDiscardStart, softDiscardEnd, depthDiff);
|
|
5162
5168
|
// At border: 0 (fully transparent) ~ 1 (fully opaque)
|
|
5163
5169
|
}
|
|
5170
|
+
|
|
5164
5171
|
}
|
|
5165
5172
|
|
|
5166
5173
|
// Calculate vector from camera to the vertex
|
|
@@ -5674,7 +5681,29 @@ void main() {
|
|
|
5674
5681
|
#include <colorspace_fragment>
|
|
5675
5682
|
#include <fog_fragment>
|
|
5676
5683
|
}
|
|
5677
|
-
`;function Sp(e,t,n,r,i=0){return t>=r.centerY?!1:Math.abs(e-r.centerX)<=r.halfW+i&&Math.abs(n-r.centerZ)<=r.halfD+i}var Cp=22,wp={enabled:!0,strength:.6},Tp={enabled:!0,color:`#cdeeff`,intensity:.55,scale:.32,speed:1};function Ep(e,t){if(e===!1)return{enabled:!1,color:kp(t),visibility:Cp,caustics:Tp,rays:{...wp,enabled:!1}};let n=e&&typeof e==`object`?e:{};return{enabled:!0,color:n.color??kp(t),visibility:n.visibility??Cp,caustics:Op(n.caustics),rays:Dp(n.rays)}}function Dp(e){return e===!1?{...wp,enabled:!1}:typeof e==`number`?{enabled:e>0,strength:e}:{...wp}}function Op(e){if(e===!1)return{...Tp,enabled:!1};let t=e&&typeof e==`object`?e:{};return{enabled:!0,color:typeof t.color==`string`?t.color:Tp.color,intensity:typeof t.intensity==`number`?t.intensity:Tp.intensity,scale:typeof t.scale==`number`?t.scale:Tp.scale,speed:typeof t.speed==`number`?t.speed:Tp.speed}}function kp(e){let{r:t,g:n,b:r}=Ap(e),i=(e,t,n)=>Math.round(e*(1-n)+t*n);return jp(Math.round(i(t,6,.45)*.7),Math.round(i(n,40,.4)*.78),Math.round(i(r,70,.35)*.82))}function Ap(e){let t=e.replace(`#`,``),n=t.length===3?t.split(``).map(e=>e+e).join(``):t;return{r:Number.parseInt(n.slice(0,2),16)||0,g:Number.parseInt(n.slice(2,4),16)||0,b:Number.parseInt(n.slice(4,6),16)||0}}function jp(e,t,n){let r=e=>Math.max(0,Math.min(255,e)).toString(16).padStart(2,`0`);return`#${r(e)}${r(t)}${r(n)}`}var Mp={frequency:6.7,persistence:.3,lacunarity:2.18,iterations:9,speed:.5},Np=.525,Pp=.08,Fp={freqX:.7,freqZ:.5,cross:.6};function Ip(e,t){return e-Math.floor(e/t)*t}function Lp(e){return e-Math.floor(e)}function Rp(e){return Ip((e*34+1)*e,289)}var zp=.211324865405187,Bp=.366025403784439,Vp=-.577350269189626,Hp=.024390243902439;function Up(e,t){let n=Math.floor(e+(e+t)*Bp),r=Math.floor(t+(e+t)*Bp),i=e-n+(n+r)*zp,a=t-r+(n+r)*zp,o=+(i>a),s=i>a?0:1,c=i+zp-o,l=a+zp-s,u=i+Vp,d=a+Vp;n=Ip(n,289),r=Ip(r,289);let f=Rp(Rp(r)+n),p=Rp(Rp(r+s)+n+o),m=Rp(Rp(r+1)+n+1),h=Math.max(.5-(i*i+a*a),0),g=Math.max(.5-(c*c+l*l),0),_=Math.max(.5-(u*u+d*d),0);h*=h,h*=h,g*=g,g*=g,_*=_,_*=_;let v=2*Lp(f*Hp)-1,y=2*Lp(p*Hp)-1,b=2*Lp(m*Hp)-1,x=Math.abs(v)-.5,S=Math.abs(y)-.5,C=Math.abs(b)-.5,w=v-Math.floor(v+.5),T=y-Math.floor(y+.5),E=b-Math.floor(b+.5);h*=1.79284291400159-.85373472095314*(w*w+x*x),g*=1.79284291400159-.85373472095314*(T*T+S*S),_*=1.79284291400159-.85373472095314*(E*E+C*C);let D=w*i+x*a,O=T*c+S*l,k=E*u+C*d;return 130*(h*D+g*O+_*k)}function Wp(e,t,n,r){let i=Math.max(r.scaleNorm,1e-6),a=e/i,o=t/i,s=0,c=1,l=r.frequency,u=n*r.speed;for(let e=0;e<r.iterations;e++)s+=c*Up(a*l+u,o*l+u),c*=r.persistence,l*=r.lacunarity;return s*r.amplitude}function Gp(e,t,n,r){return r*(Math.sin(e*Fp.freqX+n)+Fp.cross*Math.sin(t*Fp.freqZ+n*1.3))}function Kp(e,t){let n=e.shape;if(n!==void 0){if(n===`box`){let n=e.size;if(!Array.isArray(n)||n.length!==3||n.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${t}': box needs "size": [x, y, z].`);return}if(n===`sphere`){if(typeof e.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': sphere needs "radius".`);return}if(n===`capsule`){if(typeof e.radius!=`number`||typeof e.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': capsule needs "radius" and "height".`);return}if(n===`trimesh`){let n=e.vertices,r=e.indices;if(!Array.isArray(n)||n.length%3!=0||!Array.isArray(r)||r.length%3!=0)throw new y(`BAD_FORMAT`,`Collider on '${t}': trimesh needs "vertices" (flat xyz floats) and "indices" (triangle triplets).`);return}if(n!==`heightfield`)throw new y(`BAD_FORMAT`,`Collider on '${t}': "shape" must be 'box', 'sphere', 'capsule', 'trimesh', or 'heightfield', got ${JSON.stringify(n)}.`)}}var qp=class extends Pe{static typeName=`Node3D`;static props={position:{default:[0,0,0]},rotation:{default:[0,0,0]},static:{default:!1},scale:{default:[1,1,1]},visible:{default:!0},renderOrder:{default:0},orderGroup:{default:`default`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]}};position=[0,0,0];rotation=[0,0,0];static=!1;scale=[1,1,1];visible=!0;renderOrder=0;orderGroup=`default`;get effectiveRenderOrder(){return nt(this.orderGroup,this.renderOrder)}_object3D=null;_interpPrev=null;_interpCurr=null;_ensureObject3D(){return this._object3D||(this._object3D=this._createObject3D(),this._object3D.userData.incantoNode=this),this._object3D}_createObject3D(){return new Zi}_syncObject3D(e=1){let t=this._ensureObject3D(),n=this._interpPrev,r=this._interpCurr;n&&r?t.position.set((n[0]??0)+((r[0]??0)-(n[0]??0))*e,(n[1]??0)+((r[1]??0)-(n[1]??0))*e,(n[2]??0)+((r[2]??0)-(n[2]??0))*e):t.position.set(this.position[0]??0,this.position[1]??0,this.position[2]??0),t.rotation.set(ni.degToRad(this.rotation[0]??0),ni.degToRad(this.rotation[1]??0),ni.degToRad(this.rotation[2]??0)),t.scale.set(this.scale[0]??1,this.scale[1]??1,this.scale[2]??1),t.visible=this.visible,t.renderOrder=this.effectiveRenderOrder}free(){super.free(),this._object3D?.removeFromParent(),this._object3D=null,this._interpPrev=null,this._interpCurr=null}},Jp=class extends qp{static props={collider:{default:{}}};static signals=[`triggerEnter`,`triggerExit`];_collider={};_colliderChanged=!1;get collider(){return this._collider}set collider(e){this._collider=e,this._colliderChanged=!0}static validateJson(e){let t=e;if(Kp(t.collider,e.name),t.collider.shape===`heightfield`&&!(t instanceof Yp))throw new y(`BAD_FORMAT`,`Collider on '${e.name}': heightfield is static terrain — put it on a StaticBody3D (with a Terrain3D child), not a ${t.constructor.typeName}.`,{prop:`collider`})}_physics=null},Yp=class extends Jp{static typeName=`StaticBody3D`},Xp=class extends Jp{static typeName=`Area3D`},Zp=class extends Jp{static typeName=`RigidBody3D`;static props={mass:{default:1},gravityScale:{default:1},fixedRotation:{default:!1},friction:{default:.5},restitution:{default:0},linearVelocity:{default:[0,0,0]}};mass=1;gravityScale=1;fixedRotation=!1;friction=.5;restitution=0;linearVelocity=[0,0,0];_physics3d=null;applyImpulse(e){this._physics3d?.applyImpulse(this,e)}},Qp=class extends Jp{static typeName=`CharacterBody3D`;static props={velocity:{default:[0,0,0]},snapToGround:{default:!0},slopeLimitDeg:{default:45}};velocity=[0,0,0];snapToGround=!0;slopeLimitDeg=45;_grounded=!1;moveAndSlide(){if(!this._physics)throw new y(`TREE_VIOLATION`,this.collider.shape===void 0?`CharacterBody3D '${this.name}' has no collider — set a collider prop (physics skips collider-less bodies).`:`CharacterBody3D '${this.name}' has no physics world — await enablePhysics3D(engine) first.`);this._physics.moveAndSlide(this)}isOnFloor(){return this._grounded}},$p=[`fancy`,`simple`],em=[`trough`,`surface`,`peak`],tm=[`custom`,`ocean`,`pool`,`lake`,`pond`],nm={ocean:{waveHeight:.045,swell:.34,swellWavelength:52,whitecaps:.15,absorption:.17,opacity:.85,detailStrength:.17,sunIntensity:.85,colors:{trough:`#175360`,surface:`#2f8792`,peak:`#9bd8d2`},color:`#2f8792`,causticsAbove:.3,shoreWaves:.7,reflectionInterval:400,_look:{fresnelScale:1.15,reflectivityMax:.93,foamRangeScale:.35,foamIntensity:.55}},pool:{waveHeight:.006,swell:0,whitecaps:0,absorption:.3,opacity:.5,detailStrength:.16,sunIntensity:1.25,colors:{trough:`#1e8dbe`,surface:`#3fb6dc`,peak:`#bdeef7`},color:`#3fb6dc`,causticsAbove:1,reflectionInterval:600,_look:{fresnelScale:.85,reflectivityMax:.5,edgeFade:!1}},lake:{waveHeight:.028,swell:.14,swellWavelength:24,whitecaps:0,absorption:.5,opacity:.88,detailStrength:.3,colors:{trough:`#12343a`,surface:`#25565c`,peak:`#7fb2ab`},color:`#25565c`,causticsAbove:.15,reflectionInterval:300,_look:{fresnelScale:1.25,reflectivityMax:.78}},pond:{waveHeight:.012,swell:0,whitecaps:0,absorption:.55,opacity:.88,detailStrength:.2,sunIntensity:.9,colors:{trough:`#24402a`,surface:`#436b4d`,peak:`#8fae8e`},color:`#436b4d`,causticsAbove:0,reflectionInterval:800,_look:{fresnelScale:1.1,reflectivityMax:.68,edgeFade:!1}}},rm={trough:`#135a72`,surface:`#2a86a0`,peak:`#a5ddd6`},im={peakThreshold:.08,peakTransition:.05,troughThreshold:-.01,troughTransition:.15,fresnelScale:1,fresnelPower:5},am={color:`#dcebe8`,intensity:.32,rangeMin:.45,rangeMax:1.4,scale:.35,edgeColor:`#ffffff`,edgeIntensity:.6,edgeWidth:.5};function om(e,t){return Math.min(am.rangeMax,Math.max(am.rangeMin,Math.min(e,t)*.012))}var sm=128,cm=Np/Pp,lm=256,um=2e3,dm=3,fm=640,pm=.06,mm=1024,hm=.02,gm=1.5,_m=24,vm=160,ym=32,bm=.05,xm=.08,Sm=.02,Cm=.18,wm=.04,Tm=1.4,Em=.04,Dm=.45,Om=.08,km=.4,Am=.22,jm=.09,Mm=.85,Nm=class e extends qp{static typeName=`Water3D`;static signals=[`entered`,`exited`];static props={size:{default:[40,40]},color:{default:`#2a6fbe`},opacity:{default:.8},renderOrder:{default:1},waveHeight:{default:.04},waveSpeed:{default:1},quality:{default:`fancy`,options:$p},colors:{default:{}},reflection:{default:!0},reflectionInterval:{default:1e3},mirror:{default:!1},mirrorInterval:{default:33},swellSteepness:{default:.35},foam:{default:!0},interaction:{default:!0},splash:{default:!0},sunDirection:{default:[.5,.8,.3]},sunColor:{default:`#fff5d6`},sunIntensity:{default:1},detailStrength:{default:.26},absorption:{default:.15},refraction:{default:!0},underwater:{default:!0},swell:{default:0},swellDirectionDeg:{default:0},swellWavelength:{default:30},whitecaps:{default:0},preset:{default:`custom`,options:tm},causticsAbove:{default:0},shoreWaves:{default:0}};size=[40,40];color=`#2a6fbe`;opacity=.8;renderOrder=1;waveHeight=.04;waveSpeed=1;quality=`fancy`;colors={};reflection=!0;mirror=!1;mirrorInterval=33;reflectionInterval=1e3;foam=!0;interaction=!0;splash=!0;sunDirection=[.5,.8,.3];sunColor=`#fff5d6`;sunIntensity=1;detailStrength=.26;absorption=.15;refraction=!0;underwater=!0;swell=0;swellDirectionDeg=0;swellWavelength=30;swellSteepness=.35;whitecaps=0;preset=`custom`;causticsAbove=0;shoreWaves=0;rp(t){let n=nm[this.preset],r=this;if(n&&t in n){let i=e.props[t]?.default,a=r[t];if(typeof a==`object`&&a?JSON.stringify(a)===JSON.stringify(i):a===i)return n[t]}return r[t]}presetLook(){let e=nm[this.preset]?._look;return{fresnelScale:e?.fresnelScale??im.fresnelScale,reflectivityMax:e?.reflectivityMax??.6,edgeFade:e?.edgeFade??!0,foamRangeScale:e?.foamRangeScale??1,foamIntensity:e?.foamIntensity??am.intensity}}static validateJson(e){let t=e;if(!((t.size[0]??0)>0)||!((t.size[1]??0)>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' size must be positive [width, depth] meters, got ${JSON.stringify(t.size)}.`,{prop:`size`});if(!$p.includes(t.quality))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' quality must be one of [${$p.join(`, `)}], got '${t.quality}'.`,{prop:`quality`,validOptions:$p});for(let[n,r]of Object.entries(t.colors)){if(!em.includes(n))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' colors has unknown key '${n}'. Valid keys: [${em.join(`, `)}].`,{prop:`colors`,validOptions:em});if(typeof r!=`string`)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' colors.${n} must be a hex color string, got ${JSON.stringify(r)}.`,{prop:`colors`})}if(!(t.reflectionInterval>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' reflectionInterval must be > 0 ms, got ${t.reflectionInterval}.`,{prop:`reflectionInterval`});let n=t.sunDirection;if(!Array.isArray(n)||n.length!==3||!n.every(e=>Number.isFinite(e))||Math.hypot(n[0]??0,n[1]??0,n[2]??0)===0)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' sunDirection must be a non-zero [x, y, z] vector, got ${JSON.stringify(n)}.`,{prop:`sunDirection`});if(!(t.sunIntensity>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' sunIntensity must be >= 0, got ${t.sunIntensity}.`,{prop:`sunIntensity`});if(!(t.detailStrength>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' detailStrength must be >= 0, got ${t.detailStrength}.`,{prop:`detailStrength`});if(!(t.absorption>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' absorption must be >= 0 (per-meter Beer's-law constant), got ${t.absorption}.`,{prop:`absorption`});if(!(t.swell>=0)||!Number.isFinite(t.swell))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' swell must be >= 0 meters (0 = off), got ${JSON.stringify(t.swell)}.`,{prop:`swell`});if(!(t.swellWavelength>=2))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' swellWavelength must be >= 2 meters, got ${JSON.stringify(t.swellWavelength)}.`,{prop:`swellWavelength`});if(!(t.whitecaps>=0)||!(t.whitecaps<=1))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' whitecaps must be in [0, 1], got ${JSON.stringify(t.whitecaps)}.`,{prop:`whitecaps`});if(!tm.includes(t.preset))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' preset must be one of [${tm.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:tm});if(!(t.shoreWaves>=0)||!(t.shoreWaves<=1))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' shoreWaves must be in [0, 1] (0 = off), got ${JSON.stringify(t.shoreWaves)}.`,{prop:`shoreWaves`});if(!(t.causticsAbove>=0)||!(t.causticsAbove<=3))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' causticsAbove must be in [0, 3] (0 = off), got ${JSON.stringify(t.causticsAbove)}.`,{prop:`causticsAbove`});let r=t.underwater;if(typeof r!=`boolean`){if(typeof r!=`object`||!r||Array.isArray(r))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater must be true, false or an object ({ color?, visibility? }), got ${JSON.stringify(r)}.`,{prop:`underwater`});let t=r;if(t.color!==void 0&&typeof t.color!=`string`)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater.color must be a hex color string, got ${JSON.stringify(t.color)}.`,{prop:`underwater`});if(t.visibility!==void 0&&!(t.visibility>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater.visibility must be > 0 meters, got ${JSON.stringify(t.visibility)}.`,{prop:`underwater`})}}time=0;surfaceKey=``;_ripples=[];inWater=new Set;bobTimers=new Map;wadeAnchors=new Map;_scratchA={x:0,y:0,z:0};_scratchB={x:0,y:0,z:0};_bodies=[];_passHidden=[];cubeTarget=null;cubeCamera=null;reflectionNear=0;lastReflectionAt=0;scenePassTarget=null;mirrorTarget=null;mirrorCamera=new Yc;mirrorMatrix=new W;lastMirrorAt=0;_createObject3D(){return new jo}update(e){this.time+=e*this.waveSpeed,sp(this._ripples,e),this.interaction&&this.stepInteraction(e)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();this.rebuildSurfaceIfNeeded(e),this.quality===`simple`?this.syncSimple(e):this.syncFancy(e)}_onRender3D(e){let t=this._ensureObject3D(),n=t.material;if(e.camera.updateWorldMatrix(!0,!1),e.camera.getWorldPosition(Wm),this.underwaterAt(Wm.x,Wm.y,Wm.z)){if(n.isShaderMaterial){let e=n.uniforms;e.uUseSceneDepth&&(e.uUseSceneDepth.value=0),e.uUseRefraction&&(e.uUseRefraction.value=0),e.uUseMirror&&(e.uUseMirror.value=0),e.uCameraSubmerged&&(e.uCameraSubmerged.value=1)}return}if(this.quality!==`fancy`||!n.isShaderMaterial)return;let r=Math.hypot((this.size[0]??1)/2,(this.size[1]??1)/2);if(!np(e.camera,Fm(this),r+1))return;let i=n.uniforms;i.uCameraSubmerged&&(i.uCameraSubmerged.value=0);let a=Date.now();if(this.reflection){this.cubeTarget||=new fu(lm,{generateMipmaps:!0,minFilter:Wt,type:Qt});let n=Math.max((this.size[0]??1)/2,(this.size[1]??1)/2);(!this.cubeCamera||this.reflectionNear!==n)&&(this.reflectionNear=n,this.cubeCamera=new ll(n,1e3,this.cubeTarget),this.lastReflectionAt=0);let r=this.mirror?Math.max(this.rp(`reflectionInterval`),um):this.rp(`reflectionInterval`);if(this.lastReflectionAt===0||a-this.lastReflectionAt>=r){this.lastReflectionAt=a;let n=Fm(this),r=this.cubeCamera;r.position.set(n.x,n.y+.1,n.z);let i=t.visible;t.visible=!1,r.update(e.gl,e.scene),t.visible=i}i.uEnvironmentMap&&i.uUseEnvironmentMap&&(i.uEnvironmentMap.value=this.cubeTarget.texture,i.uUseEnvironmentMap.value=1)}if(this.mirror&&i.uMirrorMap&&i.uMirrorMatrix&&i.uUseMirror){e.gl.getDrawingBufferSize(Um);let n=Math.max(1,Math.min(Math.round(Um.x/dm),fm)),r=Math.max(1,Math.min(Math.round(Um.y/dm),fm));this.mirrorTarget&&(this.mirrorTarget.width!==n||this.mirrorTarget.height!==r)&&(this.mirrorTarget.dispose(),this.mirrorTarget=null),this.mirrorTarget||=new Si(n,r,{depthBuffer:!0,stencilBuffer:!1,type:Qt});let o=Fm(this).y,s=e.camera;s.getWorldPosition(Km),s.getWorldQuaternion(Ym),qm.set(0,0,-1).applyQuaternion(Ym).add(Km),Jm.set(0,1,0).applyQuaternion(Ym),Km.y=2*o-Km.y,qm.y=2*o-qm.y,Jm.y=-Jm.y;let c=this.mirrorCamera;if(c.fov=s.fov??50,c.aspect=s.aspect??n/r,c.near=s.near??.1,c.far=s.far??1e3,c.position.copy(Km),c.up.copy(Jm),c.lookAt(qm),c.updateMatrixWorld(!0),c.updateProjectionMatrix(),this.mirrorMatrix.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),this.mirrorMatrix.multiply(c.projectionMatrix),this.mirrorMatrix.multiply(c.matrixWorldInverse),this.lastMirrorAt===0||a-this.lastMirrorAt>=this.rp(`mirrorInterval`)){this.lastMirrorAt=a;let n=e.gl.getRenderTarget(),r=e.gl.clippingPlanes,i=t.visible;t.visible=!1,Xm.constant=-(o-hm),e.gl.clippingPlanes=Zm,e.gl.setRenderTarget(this.mirrorTarget),e.gl.clear(!0,!0,!1),mp(e.scene,this._passHidden),e.gl.render(e.scene,c),hp(this._passHidden),e.gl.setRenderTarget(n),e.gl.clippingPlanes=r,t.visible=i}i.uMirrorMap.value=this.mirrorTarget.texture,i.uMirrorMatrix.value.copy(this.mirrorMatrix),i.uUseMirror.value=1}else i.uUseMirror&&(i.uUseMirror.value=0);e.gl.getDrawingBufferSize(Um);let o=Math.max(1,Math.min(Math.round(Um.x/2),mm)),s=Math.max(1,Math.min(Math.round(Um.y/2),mm));if(this.scenePassTarget&&(this.scenePassTarget.width!==o||this.scenePassTarget.height!==s)&&(this.scenePassTarget.depthTexture?.dispose(),this.scenePassTarget.dispose(),this.scenePassTarget=null),!this.scenePassTarget){let e=new Fs(o,s);e.type=Zt,this.scenePassTarget=new Si(o,s,{depthTexture:e,depthBuffer:!0,stencilBuffer:!1,generateMipmaps:!0,minFilter:Wt})}let c=e.gl.getRenderTarget(),l=e.gl.autoClear,u=e.gl.clippingPlanes,d=t.visible;t.visible=!1;let f=Fm(this).y;Qm.constant=f+hm,e.gl.clippingPlanes=$m,e.gl.setRenderTarget(this.scenePassTarget),e.gl.autoClear=!0,e.gl.clear(!0,!0,!1),e.gl.render(e.scene,e.camera),eh.constant=-(f-hm),e.gl.clippingPlanes=th;let p=e.scene.overrideMaterial,m=e.scene.background;e.scene.overrideMaterial=nh,e.scene.background=null,e.gl.autoClear=!1,mp(e.scene,this._passHidden),e.gl.render(e.scene,e.camera),hp(this._passHidden),e.scene.overrideMaterial=p,e.scene.background=m,e.gl.setRenderTarget(c),e.gl.autoClear=l,e.gl.clippingPlanes=u,t.visible=d,i.uDepthTexture&&i.uSceneColor&&i.uCameraNear&&i.uCameraFar&&i.uUseSceneDepth&&(i.uDepthTexture.value=this.scenePassTarget.depthTexture,(i.uScenePassTexel?.value)?.set(1/o,1/s),i.uSceneColor.value=this.scenePassTarget.texture,i.uCameraNear.value=e.camera.near,i.uCameraFar.value=e.camera.far,i.uUseSceneDepth.value=1,i.uUseRefraction&&(i.uUseRefraction.value=+!!this.refraction),i.uEnableFoam&&(i.uEnableFoam.value=+!!this.foam))}underwaterAt(e,t,n){if(this.underwater===!1)return null;let r=Fm(this,this._scratchA);if(!Sp(e,t,n,{centerX:r.x,centerY:r.y,centerZ:r.z,halfW:(this.size[0]??1)/2,halfD:(this.size[1]??1)/2},Gm))return null;let i=Ep(this.underwater,this.rp(`color`));return i.enabled?{...i,surfaceY:r.y}:null}free(){let e=this._ensureObject3D();e.geometry?.dispose(),e.material?.dispose?.(),this.cubeTarget?.dispose(),this.cubeTarget=null,this.cubeCamera=null,this.scenePassTarget?.depthTexture?.dispose(),this.scenePassTarget?.dispose(),this.scenePassTarget=null,this.mirrorTarget?.dispose(),this.mirrorTarget=null,super.free()}rebuildSurfaceIfNeeded(e){let t=JSON.stringify([this.size,this.quality]);if(t===this.surfaceKey&&e.geometry.getAttribute(`position`))return;this.surfaceKey=t,e.geometry?.dispose(),e.material?.dispose?.();let n=this.size[0]??1,r=this.size[1]??1;this.quality===`simple`?(e.geometry=Rm(n,r,ym),e.material=this.buildLakeMaterial()):(e.geometry=Rm(n,r,Math.min(Math.max(Math.round(Math.max(n,r)*gm),_m),vm)),e.material=this.buildFancyMaterial())}buildFancyMaterial(){return new ec({vertexShader:bp,fragmentShader:xp,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uOpacity:{value:this.rp(`opacity`)},uEnvironmentMap:{value:null},uUseEnvironmentMap:{value:0},uMirrorMap:{value:null},uMirrorMatrix:{value:new W},uUseMirror:{value:0},uMirrorDistort:{value:pm},uWavesAmplitude:{value:this.rp(`waveHeight`)*cm},uWavesSpeed:{value:Mp.speed},uWavesFrequency:{value:Mp.frequency},uWavesPersistence:{value:Mp.persistence},uWavesLacunarity:{value:Mp.lacunarity},uWavesIterations:{value:Mp.iterations},uTroughColor:{value:new G(rm.trough)},uSurfaceColor:{value:new G(rm.surface)},uPeakColor:{value:new G(rm.peak)},uPeakThreshold:{value:im.peakThreshold},uPeakTransition:{value:im.peakTransition},uTroughThreshold:{value:im.troughThreshold},uTroughTransition:{value:im.troughTransition},uFresnelScale:{value:im.fresnelScale},uFresnelPower:{value:im.fresnelPower},uScale:{value:new H(1,1,1)},uWaterCenter:{value:new H},uRipples:{value:Array.from({length:8},()=>new bi)},uRippleFoam:{value:Array.from({length:8},()=>0)},uSplashFoam:{value:+!!this.splash},uSunDirection:{value:new H(.5,.8,.3)},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.rp(`sunIntensity`)},uDetailStrength:{value:this.rp(`detailStrength`)},uAbsorption:{value:this.rp(`absorption`)},uUseSceneDepth:{value:0},uUseRefraction:{value:0},uSceneColor:{value:null},uEnableFoam:{value:0},uFoamColor:{value:new G(am.color)},uFoamIntensity:{value:am.intensity},uFoamRange:{value:om(this.size[0]??1,this.size[1]??1)},uFoamScale:{value:am.scale},uDepthTexture:{value:null},uScenePassTexel:{value:new B(1/512,1/512)},uCameraNear:{value:.1},uCameraFar:{value:1e3},uEdgeColor:{value:new G(am.edgeColor)},uEdgeIntensity:{value:am.edgeIntensity},uEdgeWidth:{value:am.edgeWidth},uSwellAmplitude:{value:this.rp(`swell`)},uSwellDir:{value:new B(0,1)},uSwellWavelength:{value:this.rp(`swellWavelength`)},uSwellSteepness:{value:this.rp(`swellSteepness`)},uWhitecaps:{value:this.rp(`whitecaps`)},uWaveEnvelope:{value:0},uCausticsAbove:{value:this.rp(`causticsAbove`)},uShoreWaves:{value:this.rp(`shoreWaves`)},uReflectivityMax:{value:.6},uCameraSubmerged:{value:0},uEdgeFadeOn:{value:1}},transparent:!0,depthTest:!0,depthWrite:!0,side:2})}buildLakeMaterial(){return new ec({vertexShader:dp,fragmentShader:fp,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uOpacity:{value:this.rp(`opacity`)},uColor:{value:new G(this.rp(`color`))},uSurfaceColor:{value:new G(this.rp(`color`))},uSkyColor:{value:new G(this.rp(`color`))},uSunDirection:{value:new H(.5,.8,.3).normalize()},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.rp(`sunIntensity`)},uDetailStrength:{value:this.rp(`detailStrength`)},uFresnelPower:{value:im.fresnelPower},uScale:{value:new H(1,1,1)},uWaterCenter:{value:new H},uRipples:{value:Array.from({length:8},()=>new bi)},uRippleFoam:{value:Array.from({length:8},()=>0)},uSplashFoam:{value:+!!this.splash},uFoamColor:{value:new G(am.color)}},transparent:!0,depthTest:!0,depthWrite:!1,side:2})}syncFancy(e){let t=e.material.uniforms,n=this.size[0]??1,r=this.size[1]??1,i=Fm(this);t.uTime&&(t.uTime.value=this.time),t.uOpacity&&(t.uOpacity.value=this.rp(`opacity`)),t.uWavesAmplitude&&(t.uWavesAmplitude.value=this.rp(`waveHeight`)*cm),(t.uScale?.value)?.set(n/2,r/2,r/2),(t.uWaterCenter?.value)?.set(i.x,i.y,i.z);let a=this.resolvePalette();(t.uTroughColor?.value)?.copy(a.trough),(t.uSurfaceColor?.value)?.copy(a.surface),(t.uPeakColor?.value)?.copy(a.peak),(t.uSunDirection?.value)?.set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),(t.uSunColor?.value)?.set(this.sunColor),t.uSunIntensity&&(t.uSunIntensity.value=this.rp(`sunIntensity`)),t.uDetailStrength&&(t.uDetailStrength.value=this.rp(`detailStrength`)),t.uAbsorption&&(t.uAbsorption.value=this.rp(`absorption`)),t.uSwellAmplitude&&(t.uSwellAmplitude.value=this.rp(`swell`)),t.uSwellWavelength&&(t.uSwellWavelength.value=this.rp(`swellWavelength`)),t.uSwellSteepness&&(t.uSwellSteepness.value=this.rp(`swellSteepness`)),t.uWhitecaps&&(t.uWhitecaps.value=this.rp(`whitecaps`)),t.uCausticsAbove&&(t.uCausticsAbove.value=this.rp(`causticsAbove`)),t.uShoreWaves&&(t.uShoreWaves.value=this.rp(`shoreWaves`));let o=this.presetLook();t.uFresnelScale&&(t.uFresnelScale.value=o.fresnelScale),t.uReflectivityMax&&(t.uReflectivityMax.value=o.reflectivityMax),t.uEdgeFadeOn&&(t.uEdgeFadeOn.value=+!!o.edgeFade),t.uFoamRange&&(t.uFoamRange.value=om(n,r)*o.foamRangeScale),t.uFoamIntensity&&(t.uFoamIntensity.value=o.foamIntensity);let s=this.swellDirectionDeg*Math.PI/180;(t.uSwellDir?.value)?.set(Math.sin(s),Math.cos(s)),t.uWaveEnvelope&&(t.uWaveEnvelope.value=this.rp(`waveHeight`)*cm*1.5+this.rp(`swell`)*1.03),!this.reflection&&t.uUseEnvironmentMap&&(t.uUseEnvironmentMap.value=0),!this.foam&&t.uEnableFoam&&(t.uEnableFoam.value=0),!this.refraction&&t.uUseRefraction&&(t.uUseRefraction.value=0),t.uSplashFoam&&(t.uSplashFoam.value=+!!this.splash);let c=t.uRipples?.value,l=t.uRippleFoam?.value;if(c)for(let e=0;e<c.length;e++){let t=this._ripples[e];t?c[e].set(t.x,t.z,t.age,t.amp):c[e].set(0,0,0,0),l&&(l[e]=t?t.foam??0:0)}}_applySunDirection(t){let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this._ensureObject3D().material.uniforms?.uSunDirection?.value)?.set(t[0],t[1],t[2])}resolvePalette(){let t=this.rp(`colors`),n=this.rp(`color`),r=n===e.props.color?.default?null:n,i=t.surface??r??rm.surface;return Hm.surface.set(i),t.trough?Hm.trough.set(t.trough):r?Hm.trough.set(r).lerp(zm,.45):Hm.trough.set(rm.trough),t.peak?Hm.peak.set(t.peak):r?Hm.peak.set(r).lerp(Bm,.3):Hm.peak.set(rm.peak),Hm}syncSimple(e){let t=e.material;t.opacity=this.rp(`opacity`);let n=t.uniforms,r=this.size[0]??1,i=this.size[1]??1,a=Fm(this,this._scratchA);n.uTime&&(n.uTime.value=this.time),n.uOpacity&&(n.uOpacity.value=this.rp(`opacity`)),(n.uSurfaceColor?.value)?.set(this.rp(`color`)).lerp(Bm,.12),(n.uColor?.value)?.set(this.rp(`color`)).lerp(zm,.4),(n.uSkyColor?.value)?.set(this.rp(`color`)).lerp(Vm,.82),(n.uScale?.value)?.set(r/2,i/2,i/2),(n.uWaterCenter?.value)?.set(a.x,a.y,a.z),(n.uSunDirection?.value)?.set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),(n.uSunColor?.value)?.set(this.sunColor),n.uSunIntensity&&(n.uSunIntensity.value=this.rp(`sunIntensity`)),n.uDetailStrength&&(n.uDetailStrength.value=this.rp(`detailStrength`)),n.uSplashFoam&&(n.uSplashFoam.value=+!!this.splash);let o=n.uRipples?.value,s=n.uRippleFoam?.value;if(o)for(let e=0;e<o.length;e++){let t=this._ripples[e];t?o[e].set(t.x,t.z,t.age,t.amp):o[e].set(0,0,0,0),s&&(s[e]=t?t.foam??0:0)}let c=e.geometry,l=c.getAttribute(`position`),u=c.getAttribute(`normal`),d=this.time,f=this.rp(`waveHeight`),p=a.x,m=a.z,h=this._ripples,g=.5;for(let e=0;e<l.count;e++){let t=l.getX(e),n=l.getZ(e),r=Gp(t,n,d,f)+lp(t+p,n+m,h);l.setY(e,r);let i=Gp(t+g,n,d,f)+lp(t+p+g,n+m,h),a=Gp(t,n+g,d,f)+lp(t+p,n+m+g,h),o=(r-i)/g,s=(r-a)/g,c=1/Math.hypot(o,1,s);u.setXYZ(e,o*c,c,s*c)}l.needsUpdate=!0,u.needsUpdate=!0}stepInteraction(e){let t=this;for(;t.parent;)t=t.parent;let n=this._bodies;n.length=0,Pm(t,n);let r=Fm(this,this._scratchA),i=(this.size[0]??0)/2,a=(this.size[1]??0)/2,o=[];for(let e of n){let t=Fm(e,this._scratchB);if(Math.abs(t.x-r.x)>i||Math.abs(t.z-r.z)>a)continue;let n=rp(e.collider);o.push({id:e,x:t.x,y:t.y,z:t.z,waterline:r.y+this.waveOffsetAt(t.x,t.z,r)+n})}let{entered:s,exited:c,inWater:l}=ap(this.inWater,o,bm);this.inWater=l;let u=this.splash;for(let e of s){let t=Math.abs(Im(e.id)?.[1]??0);op(this._ripples,e.x,e.z,Lm(e.id),u?ip(t):0),this.emit(`entered`,e.id)}for(let e of c)op(this._ripples,e.x,e.z,wm,u?km:0),this.emit(`exited`,e.id);for(let t of up(this.bobTimers,l,e,Tm)){let e=Fm(t,this._scratchB);op(this._ripples,e.x,e.z,Em)}for(let e of l){let t=Fm(e,this._scratchB),n=this.wadeAnchors.get(e);if(!n){this.wadeAnchors.set(e,{x:t.x,z:t.z});continue}let r=t.x-n.x,i=t.z-n.z;if(r*r+i*i>=Dm*Dm){let r=Im(e),i=Math.hypot(r?.[0]??0,r?.[2]??0),a=u?Math.min(Am+jm*i,Mm):0;op(this._ripples,t.x,t.z,Om,a),n.x=t.x,n.z=t.z}}for(let e of this.wadeAnchors.keys())l.has(e)||this.wadeAnchors.delete(e)}heightAt(e,t){let n=Fm(this,this._scratchA);return n.y+this.waveOffsetAt(e,t,n)}waveOffsetAt(e,t,n){return this.quality===`simple`?Gp(e-n.x,t-n.z,this.time,this.rp(`waveHeight`)):Wp(e,t,this.time,{amplitude:this.rp(`waveHeight`)*cm,frequency:Mp.frequency,persistence:Mp.persistence,lacunarity:Mp.lacunarity,iterations:Mp.iterations,speed:Mp.speed,scaleNorm:sm})}};function Pm(e,t){(e instanceof Qp||e instanceof Zp)&&t.push(e);for(let n of e.children)Pm(n,t)}function Fm(e,t={x:0,y:0,z:0}){let n=0,r=0,i=0,a=e;for(;a;)a instanceof qp&&(n+=a.position[0]??0,r+=a.position[1]??0,i+=a.position[2]??0),a=a.parent;return t.x=n,t.y=r,t.z=i,t}function Im(e){return e.velocity??e.linearVelocity}function Lm(e){let t=Math.abs(Im(e)?.[1]??0);return Math.min(xm+Sm*t,Cm)}function Rm(e,t,n){let r=new Ws(e,t,n,n);return r.rotateX(-Math.PI/2),r}var zm=new G(`#000000`),Bm=new G(`#ffffff`),Vm=new G(`#cfe3f0`),Hm={trough:new G,surface:new G,peak:new G},Um=new B,Wm=new H,Gm=3,Km=new H,qm=new H,Jm=new H,Ym=new V,Xm=new ss(new H(0,1,0),0),Zm=[Xm],Qm=new ss(new H(0,-1,0),0),$m=[Qm],eh=new ss(new H(0,1,0),0),th=[eh],nh=new ic;nh.colorWrite=!1;function rh(e,t){let n=e.shape;if(n!==void 0){if(e.oneWay!==void 0&&typeof e.oneWay!=`boolean`)throw new y(`BAD_FORMAT`,`Collider on '${t}': "oneWay" must be a boolean (platforms you jump up through), got ${JSON.stringify(e.oneWay)}.`);if(n===`rect`){let n=e.size;if(!Array.isArray(n)||n.length!==2||n.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${t}': rect needs "size": [width, height].`);return}if(n===`circle`){if(typeof e.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': circle needs "radius".`);return}if(n===`capsule`){if(typeof e.radius!=`number`||typeof e.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': capsule needs "radius" and "height".`);return}throw new y(`BAD_FORMAT`,`Collider on '${t}': "shape" must be 'rect', 'circle', or 'capsule', got ${JSON.stringify(n)}.`)}}var ih=class extends Pe{static typeName=`Node2D`;static props={position:{default:[0,0]},rotation:{default:0},static:{default:!1},scale:{default:[1,1]},renderOrder:{default:0},orderGroup:{default:`default`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},visible:{default:!0}};static propAliases={zIndex:`renderOrder`};position=[0,0];rotation=0;static=!1;scale=[1,1];renderOrder=0;orderGroup=`default`;get effectiveRenderOrder(){return nt(this.orderGroup,this.renderOrder)}visible=!0;_object2D=null;_ensureObject2D(){return this._object2D||(this._object2D=this._createObject2D(),this._object2D.userData.incantoNode=this),this._object2D}_createObject2D(){return new Zi}_syncObject2D(e){let t=this._ensureObject2D();t.position.set(this.position[0]??0,-(this.position[1]??0),0),t.rotation.z=-ni.degToRad(this.rotation),t.scale.set(this.scale[0]??1,this.scale[1]??1,1),t.visible=this.visible}free(){super.free(),this._object2D?.removeFromParent(),this._object2D=null}},ah=class extends ih{static props={collider:{default:{}}};static signals=[`triggerEnter`,`triggerExit`];_collider={};_colliderChanged=!1;get collider(){return this._collider}set collider(e){this._collider=e,this._colliderChanged=!0}static validateJson(e){rh(e.collider,e.name)}_physics=null},oh=class extends ah{static typeName=`StaticBody2D`},sh=class extends ah{static typeName=`Area2D`},ch=class extends ah{static typeName=`RigidBody2D`;static props={mass:{default:1},gravityScale:{default:1},fixedRotation:{default:!1},friction:{default:.5},restitution:{default:0},linearVelocity:{default:[0,0]}};mass=1;gravityScale=1;fixedRotation=!1;friction=.5;restitution=0;linearVelocity=[0,0]},lh=class extends ah{static typeName=`CharacterBody2D`;static props={velocity:{default:[0,0]},snapToGround:{default:!0},slopeLimitDeg:{default:45}};velocity=[0,0];snapToGround=!0;slopeLimitDeg=45;_grounded=!1;moveAndSlide(){if(!this._physics)throw new y(`TREE_VIOLATION`,this.collider.shape===void 0?`CharacterBody2D '${this.name}' has no collider — set a collider prop (physics skips collider-less bodies).`:`CharacterBody2D '${this.name}' has no physics world — await enablePhysics2D(engine) first.`);this._physics.moveAndSlide(this)}isOnFloor(){return this._grounded}},uh=new Set;function dh(e){return uh.add(e),()=>uh.delete(e)}function fh(e){return[...uh].filter(t=>t.dimension===e)}var ph=class extends ih{static typeName=`Joint2D`;static props={type:{default:`revolute`,options:[`fixed`,`revolute`,`rope`,`spring`]},target:{default:``},anchor:{default:[0,0]},targetAnchor:{default:[0,0]},length:{default:0},stiffness:{default:50},damping:{default:5}};type=`revolute`;target=``;anchor=[0,0];targetAnchor=[0,0];length=0;stiffness=50;damping=5;onEnterTree(){if(!(this.parent instanceof ah))throw new y(`TREE_VIOLATION`,`Joint2D '${this.name}' must be a child of a physics body (its body A); parent is '${this.parent?.name??`none`}'.`);if(this.target===``)throw new y(`BAD_FORMAT`,`Joint2D '${this.name}' needs a "target" node path to the body it links to.`)}_resolveBodies(){let e=this.parent,t=this.getNodeOrNull(this.target);if(!(t instanceof ah))throw new y(`NODE_NOT_FOUND`,`Joint2D '${this.name}': target '${this.target}' is not a physics body.`);return{a:e,b:t}}},mh=`modulepreload`,hh=function(e,t){return new URL(e,t).href},gh={},_h=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=hh(t,n),t in gh)return;gh[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:mh,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},X=100,vh=Math.PI/180;async function yh(e,t){let n=await _h(()=>import(`./rapier-CEuLKeCu.js`),[],import.meta.url);return await n.init({}),new bh(n,e,t)}var bh=class{R;engine;debugDraw=!1;dimension=`2d`;unregisterDebug;warnedNoCollider=new WeakSet;entries=new Map;byColliderHandle=new Map;world;events;kcc;disconnect;lastDt=1/60;optsGravity;lastScene=null;constructor(e,t,n){this.R=e,this.engine=t,this.optsGravity=n?.gravity,this.lastScene=t.scene;let r=t.scene?.physics?.gravity,i=n?.gravity??r??[0,980];this.world=new e.World({x:(i[0]??0)/X,y:(i[1]??0)/X}),this.kcc=this.world.createCharacterController(.01),this.kcc.setUp({x:0,y:-1}),this.events=new e.EventQueue(!0),this.unregisterDebug=dh(this),this.disconnect=t.fixedUpdated.connect(e=>this.step(e)),this.syncBodies()}step(e){if(this.lastDt=e,this.engine.scene!==this.lastScene&&(this.lastScene=this.engine.scene,!this.optsGravity)){let e=this.engine.scene?.physics?.gravity??[0,980];this.world.gravity={x:(e[0]??0)/X,y:(e[1]??0)/X}}this.syncBodies(),this.world.timestep=e,this.world.step(this.events);for(let[e,t]of this.entries){let n=t.body.translation();if(!t.body.isFixed()){let[t,r]=Dh(e);e.position=[n.x*X-t,n.y*X-r]}if(e instanceof ch){e.fixedRotation||(e.rotation=t.body.rotation()/vh);let n=t.body.linvel();e.linearVelocity=[n.x*X,n.y*X],t.lastVX=e.linearVelocity[0]??0,t.lastVY=e.linearVelocity[1]??0}let[r,i]=Eh(e);t.lastX=r,t.lastY=i}this.events.drainCollisionEvents((e,t,n)=>{let r=this.byColliderHandle.get(e),i=this.byColliderHandle.get(t);if(!r||!i)return;let a=n?`triggerEnter`:`triggerExit`;try{r.emit(a,i),i.emit(a,r)}catch(e){console.error(`incanto: error in a '${a}' handler (${r.name} ↔ ${i.name}):`,e)}})}moveAndSlide(e){let t=this.ensureEntry(e),n=e.velocity[1]??0;e.snapToGround&&n>=0?this.kcc.enableSnapToGround(.05):this.kcc.disableSnapToGround(),this.kcc.setMaxSlopeClimbAngle(e.slopeLimitDeg*vh);let r=0,i=0;if(t.ground&&t.ground._physics===this){let[e,n]=Eh(t.ground);r=e-(t.groundX??e),i=n-(t.groundY??n)}else t.ground=null;let a={x:((e.velocity[0]??0)*this.lastDt+r)/X*1,y:(n*this.lastDt+i)/X*1},o=t.body.translation().y*X+wh(e);this.kcc.computeColliderMovement(t.collider,a,this.R.QueryFilterFlags.EXCLUDE_SENSORS,void 0,t=>{let r=this.byColliderHandle.get(t.handle);return!(r&&r!==e&&r.collider.oneWay===!0&&(n<0||o>Th(r)+Ch))});let s=this.kcc.computedMovement(),c=t.body.translation();if(t.body.setNextKinematicTranslation({x:c.x+s.x,y:c.y+s.y}),e._grounded=this.kcc.computedGrounded(),e._grounded){let n=(c.x+s.x)*X,r=(c.y+s.y)*X+wh(e)-2,i=this.castRay([n,r],[0,1],8,e);if(i?.node&&!(i.node instanceof lh)){t.ground=i.node;let[e,n]=Eh(i.node);t.groundX=e,t.groundY=n}else t.ground=null}else t.ground=null}debugLines(){if(!this.debugDraw)return null;let e=this.world.debugRender().vertices,t=new Float32Array(e.length);for(let n=0;n<e.length;n++)t[n]=e[n]*X;return t}syncJoints(e){let t=this.R;if(e)for(let[e,t]of this.joints)this.jointSet.has(e)||(this.world.removeImpulseJoint(t,!0),this.joints.delete(e));for(let e of this.jointSet){if(this.joints.has(e))continue;let{a:n,b:r}=e._resolveBodies(),i=this.entries.get(n),a=this.entries.get(r);if(!i||!a)continue;let o={x:(e.anchor[0]??0)/X,y:(e.anchor[1]??0)/X},s={x:(e.targetAnchor[0]??0)/X,y:(e.targetAnchor[1]??0)/X},c=e.length/X;if(e.length===0&&(e.type===`rope`||e.type===`spring`)){let e=i.body.translation(),t=a.body.translation();c=Math.hypot(t.x-e.x,t.y-e.y)}let l;l=e.type===`fixed`?t.JointData.fixed(o,0,s,0):e.type===`rope`?t.JointData.rope(c,o,s):e.type===`spring`?t.JointData.spring(c,e.stiffness,e.damping,o,s):t.JointData.revolute(o,s),this.joints.set(e,this.world.createImpulseJoint(l,i.body,a.body,!0))}}castRay(e,t,n,r,i){let a=Math.hypot(t[0],t[1])||1,o=new this.R.Ray({x:e[0]/X,y:e[1]/X},{x:t[0]/a,y:t[1]/a}),s=r?this.entries.get(r)?.collider:void 0,c=i?.staticOnly?this.R.QueryFilterFlags.EXCLUDE_DYNAMIC|this.R.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,l=this.world.castRayAndGetNormal(o,n/X,!0,c,void 0,s,void 0,e=>!e.isSensor());return l?{distance:l.timeOfImpact*X,normal:[l.normal.x,l.normal.y],node:this.byColliderHandle.get(l.collider.handle)??null}:null}dispose(){this.disconnect(),this.unregisterDebug(),this.world.free()}lastStructure=-1;lastRoot=null;jointSet=new Set;joints=new Map;bodySet=new Set;syncBodies(){let e=this.engine.scene;if(!e)return;let t=e.tree._structureVersion,n=t!==this.lastStructure||e.root!==this.lastRoot;n&&(this.lastStructure=t,this.lastRoot=e.root,this.bodySet.clear(),Sh(e.root,this.bodySet)),n&&(this.jointSet.clear(),xh(e.root,this.jointSet));let r=this.bodySet;for(let e of r){if(e.collider.shape===void 0){let t=this.entries.get(e);t&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null),this.warnedNoCollider.has(e)||(this.warnedNoCollider.add(e),console.warn(`[incanto] '${e.name}' has no collider — physics skips it.`));continue}let t=this.entries.get(e);t&&e._colliderChanged&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null),this.ensureEntry(e)}if(this.syncJoints(n),n)for(let[e,t]of this.entries)r.has(e)||(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null)}ensureEntry(e){let t=this.entries.get(e),n=this.R;if(!t){let[r,i]=Eh(e),a=r/X,o=i/X,s;s=e instanceof ch?n.RigidBodyDesc.dynamic():e instanceof lh||e instanceof sh?n.RigidBodyDesc.kinematicPositionBased():n.RigidBodyDesc.fixed(),s.setTranslation(a,o).setRotation(e.rotation*vh),e instanceof ch&&(s.setGravityScale(e.gravityScale),s.setLinvel((e.linearVelocity[0]??0)/X,(e.linearVelocity[1]??0)/X),e.fixedRotation&&s.lockRotations());let c=this.world.createRigidBody(s),l=Oh(n,e.collider,e.name);l.setActiveEvents(n.ActiveEvents.COLLISION_EVENTS),l.setActiveCollisionTypes(n.ActiveCollisionTypes.ALL),e instanceof sh&&l.setSensor(!0),e instanceof ch&&l.setMass(e.mass).setFriction(e.friction).setRestitution(e.restitution);let u=this.world.createCollider(l,c);return t={body:c,collider:u,lastX:r,lastY:i,lastVX:0,lastVY:0},this.entries.set(e,t),this.byColliderHandle.set(u.handle,e),e._colliderChanged=!1,e._physics=this,t}let[r,i]=Eh(e);if((r!==t.lastX||i!==t.lastY)&&(t.body.setTranslation({x:r/X,y:i/X},!0),t.lastX=r,t.lastY=i),e instanceof ch){let n=e.linearVelocity[0]??0,r=e.linearVelocity[1]??0;(n!==t.lastVX||r!==t.lastVY)&&(t.body.setLinvel({x:n/X,y:r/X},!0),t.lastVX=n,t.lastVY=r)}return t}};function xh(e,t){e instanceof ph&&t.add(e);for(let n of e.children)xh(n,t)}function Sh(e,t){e instanceof ah&&t.add(e);for(let n of e.children)Sh(n,t)}var Ch=4;function wh(e){let t=e.collider;return t.shape===`rect`?(t.size?.[1]??32)/2:t.shape===`capsule`?(t.height??32)/2+(t.radius??8):t.radius??16}function Th(e){let[,t]=Eh(e),n=e.collider;return t-(n.shape===`rect`?(n.size?.[1]??32)/2:n.shape===`capsule`?(n.height??32)/2+(n.radius??8):n.radius??16)}function Eh(e){let t=0,n=0;for(let r=e;r;r=r.parent)r instanceof ih&&(t+=r.position[0]??0,n+=r.position[1]??0);return[t,n]}function Dh(e){let t=0,n=0;for(let r=e.parent;r;r=r.parent)r instanceof ih&&(t+=r.position[0]??0,n+=r.position[1]??0);return[t,n]}function Oh(e,t,n){rh(t,n);let r=kh(e,t,n),i=t.offset;return Array.isArray(i)&&r.setTranslation((i[0]??0)/X,(i[1]??0)/X),r}function kh(e,t,n){let r=t.shape;if(r===`rect`){let r=t.size;if(!Array.isArray(r)||r.length!==2||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${n}': rect needs "size": [width, height].`);return e.ColliderDesc.cuboid(r[0]/2/X,r[1]/2/X)}if(r===`circle`){if(typeof t.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': circle needs "radius".`);return e.ColliderDesc.ball(t.radius/X)}if(r===`capsule`){if(typeof t.radius!=`number`||typeof t.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': capsule needs "radius" and "height".`);return e.ColliderDesc.capsule(t.height/2/X,t.radius/X)}throw new y(`BAD_FORMAT`,`Collider on '${n}': "shape" must be 'rect', 'circle', or 'capsule', got ${JSON.stringify(r)}.`)}var Ah=new Ws(1,1),jh=class extends ih{static typeName=`Sprite2D`;static props={texture:{default:``},anchor:{default:[.5,.5]},flipX:{default:!1},flipY:{default:!1},tint:{default:`#ffffff`},opacity:{default:1}};texture=``;anchor=[.5,.5];flipX=!1;flipY=!1;tint=`#ffffff`;opacity=1;quadMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(Ah,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_createObject2D(){return super._createObject2D()}resolveTexture(e){if(!this.texture||!e)return null;let t=e.getTexture(this.texture),n=t.image;return!n?.width||!n.height?null:{texture:t,width:n.width,height:n.height}}_syncObject2D(e){super._syncObject2D(e);let t=this._quad(),n=t.material,r=this.resolveTexture(e);if(!r){t.visible=!1;return}t.visible=!0,n.map!==r.texture&&(n.map=r.texture,n.needsUpdate=!0);let i=r.width,a=r.height;t.scale.set(this.flipX?-i:i,this.flipY?-a:a,1);let o=this.anchor[0]??.5,s=this.anchor[1]??.5;t.position.set((.5-o)*i,(s-.5)*a,0),t.renderOrder=this.effectiveRenderOrder,n.color.set(this.tint),n.opacity=this.opacity}},Mh=class extends jh{static typeName=`AnimatedSprite2D`;static signals=[`animationFinished`];static props={sheet:{default:``},animations:{default:{}},autoplay:{default:``}};sheet=``;animations={};autoplay=``;playing=!1;currentFrame=0;currentAnimation=``;frameList=[];frameIndex=0;frameTime=0;ownTexture=null;loadedSheetRef=``;play(e){let t=this.animations[e];if(!t)throw new y(`UNKNOWN_ANIMATION`,`No animation '${e}' on '${this.name}'. Available: [${Object.keys(this.animations).join(`, `)}].`);this.currentAnimation=e,this.frameList=Nh(t.frames,e),this.frameIndex=0,this.currentFrame=this.frameList[0]??0,this.frameTime=0,this.playing=!0}stop(){this.playing=!1}onReady(){this.autoplay&&this.play(this.autoplay)}update(e){if(!this.playing||this.currentAnimation===``)return;let t=this.animations[this.currentAnimation];if(!t||!Number.isFinite(t.fps)||t.fps<=0)return;let n=1/t.fps;for(this.frameTime+=e;this.frameTime>=n;)if(this.frameTime-=n,this.frameIndex+=1,this.frameIndex>=this.frameList.length)if(t.loop)this.frameIndex=0;else{this.frameIndex=this.frameList.length-1,this.playing=!1,this.emit(`animationFinished`,this.currentAnimation);break}this.currentFrame=this.frameList[this.frameIndex]??0}resolveTexture(e){if(!this.sheet||!e)return null;let t=e.getSheet(this.sheet);this.loadedSheetRef!==this.sheet&&(this.ownTexture=t.texture.clone(),this.ownTexture.needsUpdate=!0,this.loadedSheetRef=this.sheet);let n=this.ownTexture,r=t.texture.image;if(!r?.width||!r.height)return null;let i=Math.max(1,Math.floor(r.width/t.frameWidth)),a=this.currentFrame%i,o=Math.floor(this.currentFrame/i);return n.repeat.set(t.frameWidth/r.width,t.frameHeight/r.height),n.offset.set(a*t.frameWidth/r.width,1-(o+1)*t.frameHeight/r.height),{texture:n,width:t.frameWidth,height:t.frameHeight}}};function Nh(e,t){if(!Array.isArray(e)||e.length===0)throw new y(`BAD_FORMAT`,`Animation '${t}': "frames" must be a non-empty array.`);if(e.length===2){let[t,n]=e;if(n>=t){let e=[];for(let r=t;r<=n;r++)e.push(r);return e}}return[...e]}var Ph=class extends ih{static typeName=`Camera2D`;static props={follow:{default:``},smoothing:{default:0},zoom:{default:1},limits:{default:[]},current:{default:!1}};follow=``;smoothing=0;zoom=1;limits=[];current=!1;get effectiveZoom(){return Math.max(.01,this.zoom)}update(e){if(!this.follow)return;let t=this.getNodeOrNull(this.follow);if(!(t instanceof ih))return;let n=t.position[0]??0,r=t.position[1]??0,i=Math.min(Math.max(this.smoothing,0),.99),a=i<=0?1:1-i**(e*60),o=this.position[0]??0,s=this.position[1]??0;this.position=[o+(n-o)*a,s+(r-s)*a]}clampedCenter(e,t){let n=this.position[0]??0,r=this.position[1]??0;if(this.limits.length!==0&&this.limits.length!==4)throw new y(`BAD_FORMAT`,`Camera2D '${this.name}' limits must be [] or [minX,minY,maxX,maxY], got length ${this.limits.length}.`);if(this.limits.length===4){let[i,a,o,s]=this.limits,c=e/(2*this.effectiveZoom),l=t/(2*this.effectiveZoom);n=Fh(n,i+c,o-c),r=Fh(r,a+l,s-l)}return{x:n,y:r}}};function Fh(e,t,n){return t>n?(t+n)/2:Math.min(n,Math.max(t,e))}var Ih=class extends Pe{static typeName=`CharacterController2D`;static props={mode:{default:`platformer`,options:[`platformer`,`topDown`]},maxSpeed:{default:220},jumpHeight:{default:64},moveAction:{default:`move`},jumpAction:{default:`jump`}};mode=`platformer`;maxSpeed=220;jumpHeight=64;moveAction=`move`;jumpAction=`jump`;onReady(){if(!(this.parent instanceof lh))throw new y(`TREE_VIOLATION`,`CharacterController2D '${this.name}' must be a child of a CharacterBody2D (parent is '${this.parent?.name??`none`}').`);if(this.mode!==`platformer`&&this.mode!==`topDown`)throw new y(`PROP_TYPE_MISMATCH`,`CharacterController2D.mode must be 'platformer' or 'topDown', got '${this.mode}'.`)}fixedUpdate(e){let t=this.tree?.engine;if(!t?.scene)return;let n=this.parent;if(!(n instanceof lh))return;let r=t.input,i=r.getVector(this.moveAction);if(this.mode===`topDown`){n.velocity=[i.x*this.maxSpeed,i.y*this.maxSpeed],n.moveAndSlide();return}let a=t.scene.physics?.gravity?.[1]??980;if(n.velocity[0]=i.x*this.maxSpeed,n.isOnFloor()){let e=r.justPressed(this.jumpAction);n.velocity[1]=e?-Math.sqrt(2*a*this.jumpHeight):20}else n.velocity[1]=(n.velocity[1]??0)+a*e;n.moveAndSlide()}},Lh=new Ws(1,1),Rh=class extends ih{static typeName=`ColorRect2D`;static props={size:{default:[100,100]},color:{default:`#ffffff`},opacity:{default:1},anchor:{default:[.5,.5]}};size=[100,100];color=`#ffffff`;opacity=1;anchor=[.5,.5];quadMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(Lh,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._quad(),n=this.size[0]??0,r=this.size[1]??0;t.visible=n>0&&r>0&&this.opacity>0,t.scale.set(n,r,1);let i=this.anchor[0]??.5,a=this.anchor[1]??.5;t.position.set((.5-i)*n,(a-.5)*r,0),t.renderOrder=this.effectiveRenderOrder;let o=t.material;o.color.set(this.color),o.opacity=this.opacity}},zh=new Ws(1,1),Bh=class extends ih{static typeName=`Label`;static props={text:{default:``},fontSize:{default:16},color:{default:`#ffffff`},font:{default:`monospace`},align:{default:`left`}};text=``;fontSize=16;color=`#ffffff`;font=`monospace`;align=`left`;quadMesh=null;canvas=null;lastKey=``;_quad(){return this.quadMesh||(this.quadMesh=new jo(zh,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._quad();if(typeof document>`u`||this.text===``){t.visible=!1;return}let n=`${this.text}\0${this.fontSize}\0${this.color}\0${this.font}\0${this.align}`;n!==this.lastKey&&(this.lastKey=n,this.rasterize()),t.visible=!0,t.renderOrder=this.effectiveRenderOrder}rasterize(){let e=Math.min(globalThis.devicePixelRatio??1,2);this.canvas??=document.createElement(`canvas`);let t=this.canvas.getContext(`2d`);if(!t)return;let n=`${this.fontSize*e}px ${this.font}`;t.font=n;let r=t.measureText(this.text),i=Math.max(1,Math.ceil(r.width)),a=Math.ceil(this.fontSize*e*1.4);this.canvas.width=i,this.canvas.height=a,t.font=n,t.fillStyle=this.color,t.textBaseline=`middle`,t.fillText(this.text,0,a/2);let o=this._quad(),s=o.material;s.map?.dispose(),s.map=new Ps(this.canvas),s.needsUpdate=!0;let c=i/e,l=a/e;o.scale.set(c,l,1);let u=this.align===`center`?.5:+(this.align===`right`);o.position.set((.5-u)*c,0,0)}},Vh=new Ws(1,1),Hh=class e extends ih{orderGroup=`effects`;static typeName=`Particles2D`;static signals=[`finished`];static props={orderGroup:{default:`effects`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},preset:{default:`custom`,options:[`custom`,...it]},emitting:{default:!0},rate:{default:40},burst:{default:0},lifetime:{default:[.6,1.2]},speed:{default:[40,120]},directionDeg:{default:-90},spreadDeg:{default:30},gravity:{default:[0,0]},drag:{default:0},sizeStart:{default:8},sizeEnd:{default:2},colorStart:{default:`#ffffff`},colorEnd:{default:`#ffffff`},paletteColors:{default:[]},alphaStart:{default:1},alphaEnd:{default:0},shimmer:{default:0},blend:{default:`add`,options:[`add`,`normal`]},maxParticles:{default:256}};preset=`custom`;emitting=!0;rate=40;burst=0;lifetime=[.6,1.2];speed=[40,120];directionDeg=-90;spreadDeg=30;gravity=[0,0];drag=0;sizeStart=8;sizeEnd=2;colorStart=`#ffffff`;colorEnd=`#ffffff`;paletteColors=[];alphaStart=1;alphaEnd=0;shimmer=0;blend=`add`;maxParticles=256;static validateJson(e){let t=e;if(t.preset!==`custom`&&!it.includes(t.preset))throw new y(`BAD_FORMAT`,`Particles2D '${e.name}' preset must be 'custom' or one of [${it.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:it});if(t.blend!==`add`&&t.blend!==`normal`)throw new y(`BAD_FORMAT`,`Particles2D '${e.name}' blend must be 'add' or 'normal', got '${t.blend}'.`,{prop:`blend`,validOptions:[`add`,`normal`]})}sim=null;bursted=!1;finishedEmitted=!1;_ensureSim(){if(!this.sim){at(this,this.preset,ge(e.typeName));let t=this.tree?.engine?.rng??new b(4660);this.sim=new st({rate:this.emitting?this.rate:0,lifetime:[this.lifetime[0]??1,this.lifetime[1]??1],speed:[this.speed[0]??0,this.speed[1]??0],directionDeg:this.directionDeg,spreadDeg:this.spreadDeg,gravity:[this.gravity[0]??0,this.gravity[1]??0,0],drag:this.drag,maxParticles:this.maxParticles},t)}return this.sim}update(e){let t=this._ensureSim();this.burst>0&&!this.bursted&&(this.bursted=!0,t.burst(this.burst)),t.update(e),(!this.emitting||this.rate===0)&&this.bursted&&t.done&&!this.finishedEmitted&&(this.finishedEmitted=!0,this.emit(`finished`))}replay(){this.bursted=!1,this.finishedEmitted=!1}mesh=null;paletteCache=[];paletteCacheKey=``;refreshPalette(){let e=this.paletteColors;if(e.length===0)return null;let t=e.join(`|`);if(t!==this.paletteCacheKey){this.paletteCacheKey=t;for(let t=0;t<e.length;t++){let n=this.paletteCache[t];n||(n=new G,this.paletteCache[t]=n),n.set(e[t])}this.paletteCache.length=e.length}return this.paletteCache}_syncObject2D(e){super._syncObject2D(e);let t=this._ensureSim();if(!this.mesh||this.mesh.count!==this.maxParticles){this.mesh&&this.mesh.removeFromParent();let e=new yo({transparent:!0,depthWrite:!1,blending:this.blend===`add`?2:1});this.mesh=new rs(Vh,e,this.maxParticles),this.mesh.instanceMatrix.setUsage(_r),this.mesh.frustumCulled=!1,this._ensureObject2D().add(this.mesh)}let n=this.mesh,r=this.refreshPalette(),i=r?null:Wh.set(this.colorStart),a=Gh.set(this.colorEnd),o=this.shimmer,s=0;t.forEach(e=>{let t=this.sizeStart+(this.sizeEnd-this.sizeStart)*e.t;Uh.makeScale(t,t,1),Uh.setPosition(e.x,-e.y,0),n.setMatrixAt(s,Uh);let c=r?r[Math.floor(e.seed*r.length)]:i,l=Math.max(0,this.alphaStart+(this.alphaEnd-this.alphaStart)*e.t);o>0&&(l*=.5+.5*Math.sin(2*Math.PI*(e.age*o+e.seed))),Kh.copy(c).lerp(a,e.t).multiplyScalar(l),n.setColorAt(s,Kh),s+=1}),n.count=s,n.instanceMatrix.needsUpdate=!0,n.instanceColor&&(n.instanceColor.needsUpdate=!0),n.renderOrder=this.effectiveRenderOrder}},Uh=new W,Wh=new G,Gh=new G,Kh=new G;function qh(e,t){let n=[],r=0;for(let i of e){let e=[];if(typeof i==`string`)for(let n of i){let r=t[n];if(r!==void 0)e.push(r);else if(n===`.`||n===` `)e.push(-1);else if(n>=`0`&&n<=`9`)e.push(n.charCodeAt(0)-48);else throw new y(`BAD_FORMAT`,`TileMap2D: unknown tile char '${n}' — add it to "legend" (char → tile index), or use '.'/' ' for empty and digits 0-9.`)}else for(let t of i)e.push(t);r=Math.max(r,e.length),n.push(e)}for(let e of n)for(;e.length<r;)e.push(-1);return n}function Jh(e,t){let n=e.length,r=n>0?e[0].length:0,i=e.map(e=>e.map(()=>!1)),a=(n,r)=>t.has(e[r][n]),o=[];for(let e=0;e<n;e++)for(let t=0;t<r;t++){if(!a(t,e)||i[e][t])continue;let s=1;for(;t+s<r&&a(t+s,e)&&!i[e][t+s];)s++;let c=1;grow:for(;e+c<n;){for(let n=0;n<s;n++)if(!a(t+n,e+c)||i[e+c][t+n])break grow;c++}for(let n=0;n<c;n++)for(let r=0;r<s;r++)i[e+n][t+r]=!0;o.push({x:t,y:e,w:s,h:c})}return o}var Yh=class extends ih{static typeName=`TileMap2D`;static props={texture:{default:``},tileSize:{default:32},columns:{default:0},cells:{default:[]},legend:{default:{}},solid:{default:[]},opacity:{default:1}};texture=``;tileSize=32;columns=0;_cells=[];_legend={};_solid=[];geometryDirty=!0;collidersDirty=!0;get cells(){return this._cells}set cells(e){this._cells=e,this.geometryDirty=!0,this.collidersDirty=!0}get legend(){return this._legend}set legend(e){this._legend=e,this.geometryDirty=!0,this.collidersDirty=!0}get solid(){return this._solid}set solid(e){this._solid=e,this.collidersDirty=!0}opacity=1;tileMesh=null;builtColumns=0;builtRows=0;static validateJson(e){let t=e;qh(t._cells,t._legend)}grid(){return qh(this._cells,this._legend)}onReady(){this.rebuildColliders()}update(e){this.collidersDirty&&this.rebuildColliders()}rebuildColliders(){this.collidersDirty=!1;for(let e of[...this.children])e.name.startsWith(`__tileSolid`)&&e.free();if(this._solid.length===0)return;let e=this.tileSize;Jh(this.grid(),new Set(this._solid)).forEach((t,n)=>{let r=new oh(`__tileSolid${n}`);r.position=[(t.x+t.w/2)*e,(t.y+t.h/2)*e],r.collider={shape:`rect`,size:[t.w*e,t.h*e]},this.addChild(r)})}_mesh(){return this.tileMesh||(this.tileMesh=new jo(new q,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.tileMesh)),this.tileMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._mesh(),n=t.material;if(!this.texture||!e){t.visible=!1;return}let r=e.getTexture(this.texture),i=r.image;if(!i?.width||!i.height){t.visible=!1;return}t.visible=this.opacity>0,t.renderOrder=this.effectiveRenderOrder,n.opacity=this.opacity,n.map!==r&&(r.magFilter=zt,n.map=r,n.needsUpdate=!0,this.geometryDirty=!0);let a=this.columns>0?this.columns:Math.max(1,Math.floor(i.width/this.tileSize)),o=Math.max(1,Math.floor(i.height/this.tileSize));(a!==this.builtColumns||o!==this.builtRows)&&(this.geometryDirty=!0),this.geometryDirty&&(this.geometryDirty=!1,this.builtColumns=a,this.builtRows=o,this.buildGeometry(t.geometry,a,o))}buildGeometry(e,t,n){let r=this.grid(),i=this.tileSize,a=[],o=[],s=[];for(let e=0;e<r.length;e++){let c=r[e];for(let r=0;r<c.length;r++){let l=c[r];if(l<0)continue;let u=r*i,d=u+i,f=-(e*i),p=-((e+1)*i),m=a.length/3;a.push(u,f,0,d,f,0,d,p,0,u,p,0);let h=l%t,g=Math.floor(l/t),_=h/t,v=(h+1)/t,y=1-g/n,b=1-(g+1)/n;o.push(_,y,v,y,v,b,_,b),s.push(m,m+2,m+1,m,m+3,m+2)}}e.setAttribute(`position`,new K(new Float32Array(a),3)),e.setAttribute(`uv`,new K(new Float32Array(o),2)),e.setIndex(s),e.computeBoundingSphere()}get renderedTileCount(){let e=this.tileMesh?.geometry.getAttribute(`position`);return e?e.count/4:0}free(){this.tileMesh?.geometry.dispose(),super.free()}},Xh=[`top-left`,`top`,`top-right`,`left`,`center`,`right`,`bottom-left`,`bottom`,`bottom-right`],Zh=class extends Pe{static typeName=`UILayer`;static props={anchor:{default:`top-left`,options:Xh}};anchor=`top-left`;group=null;_ensureGroup(){return this.group||(this.group=new Qi,this.group.userData.incantoNode=this),this.group}static validateJson(e){let t=e.anchor;if(!Xh.includes(t))throw new y(`BAD_FORMAT`,`UILayer '${e.name}' anchor must be one of [${Xh.join(`, `)}], got '${t}'.`,{prop:`anchor`,validOptions:Xh})}_anchorOrigin(e,t){let n=this.anchor;return{x:n.includes(`right`)?e:n===`top`||n===`center`||n===`bottom`?e/2:0,y:n.includes(`bottom`)?t:n===`left`||n===`center`||n===`right`?t/2:0}}};function Qh(){ct(),M(ih),M(jh),M(Rh),M(Hh),M(Mh),M(Ph),M(Bh),M(Zh),M(oh),M(ch),M(sh),M(lh),M(Ih),M(ph),M(Yh)}function $h(e,t,n){return{x:(t-e.cx)*e.zoom+e.w/2,y:(n-e.cy)*e.zoom+e.h/2}}function eg(e,t,n){return{x:(t-e.w/2)/e.zoom+e.cx,y:(n-e.h/2)/e.zoom+e.cy}}var tg=new Sa,ng=new H,rg=12,ig=new Float32Array(16);function ag(e){if(!(e instanceof ih))return null;let t=e._ensureObject2D();t.updateWorldMatrix(!0,!0),tg.setFromObject(t),tg.getSize(ng);let n,r,i,a;if(!Number.isFinite(ng.x)||ng.x===0&&ng.y===0){let e=new H().setFromMatrixPosition(t.matrixWorld);n=e.x-rg,i=e.x+rg,r=e.y-rg,a=e.y+rg}else n=tg.min.x-2,i=tg.max.x+2,r=tg.min.y-2,a=tg.max.y+2;let o=[n,r,i,r,i,r,i,a,i,a,n,a,n,a,n,r];return ig.set(o),ig}function og(){return{visited:new Set,cameras:[]}}function sg(e,t,n,r,i,a,o){let s=a??og();s.visited.clear(),s.cameras.length=0,cg(e,t,n,!1,s.visited,s.cameras,r,i,o?.ignoreStatic===!0),lg(t,s.visited),lg(n,s.visited);let c=null;for(let e=0;e<s.cameras.length;e++){let t=s.cameras[e];if(t.current){c=t;break}}return c||=s.cameras[0]??null,{activeCamera:c}}function cg(e,t,n,r,i,a,o,s,c){let l=t,u=r;if(e instanceof ih&&!(e instanceof Zh)){let t=e._ensureObject2D();if(e.static&&!c&&t.userData.incantoStaticSynced===!0){t.userData.incantoStatic=!0,i.add(t);return}}if(e instanceof Zh){let t=e._ensureGroup();t.parent!==n&&n.add(t);let r=s?e._anchorOrigin(s.width,s.height):{x:0,y:0};t.position.set(r.x,-r.y,0),i.add(t),u=!0,l=t}else if(e instanceof ih){let n=e._ensureObject2D();n.parent!==t&&t.add(n),e._syncObject2D(o),i.add(n),e instanceof Ph&&!r&&a.push(e),l=n}for(let t of e.children)cg(t,l,n,u,i,a,o,s,c);if(e instanceof ih&&!(e instanceof Zh)){let t=e._ensureObject2D();e.static&&!c?(t.userData.incantoStaticSynced=!0,t.userData.incantoStatic=!0):t.userData.incantoStaticSynced===!0&&(t.userData.incantoStaticSynced=!1,t.userData.incantoStatic=!1)}}function lg(e,t){let n=e.children;for(let r=n.length-1;r>=0;r--){let i=n[r];i.userData.incantoNode&&!t.has(i)?e.remove(i):i.userData.incantoStatic!==!0&&lg(i,t)}}var ug=class{viewOverride=null;webgl;worldScene=new sa;syncScratch=og();ignoreStatic=!1;uiScene=new sa;worldCam=new el(-1,1,1,-1,-1e3,1e3);uiCam=new el(-1,1,1,-1,-1e3,1e3);engine;assets;loadedAssetScenes=new WeakSet;disconnect;canvas;constructor(e){this.canvas=e.canvas,this.engine=e.engine,this.assets=e.assets??new Qf;let t=lt(e.engine.scene?.environment,{antialias:!0,pixelRatio:1},globalThis.devicePixelRatio??1,e);this.webgl=new Zf({canvas:e.canvas,antialias:t.antialias}),this.webgl.setPixelRatio(t.pixelRatio),this.webgl.info.autoReset=!1,this.debugLines=new ws(new q,new fs({color:`#00ff6e`,transparent:!0,depthTest:!1})),this.debugLines.frustumCulled=!1,this.debugLines.renderOrder=9999,this.debugLines.visible=!1,this.worldScene.add(this.debugLines),this.selectionLines=new ws(new q,new fs({color:`#ffb020`,transparent:!0,depthTest:!1})),this.selectionLines.frustumCulled=!1,this.selectionLines.renderOrder=1e4,this.selectionLines.visible=!1,this.worldScene.add(this.selectionLines),this.disconnect=this.engine.updated.connect(()=>this.render())}debugLines;selectionLines;syncSelectionOutline(){let e=this.engine.debugSelection;e&&e.tree!==this.engine.scene?.tree&&(this.engine.debugSelection=null);let t=this.engine.debugSelection,n=t?ag(t):null;if(this.selectionLines.visible=n!==null,!n)return;let r=new Float32Array(n.length/2*3);for(let e=0,t=0;e<n.length;e+=2,t+=3)r[t]=n[e],r[t+1]=n[e+1],r[t+2]=0;this.selectionLines.geometry.setAttribute(`position`,new K(r,3)),this.selectionLines.geometry.getAttribute(`position`).needsUpdate=!0}syncDebugLines(){let e=null;for(let t of fh(`2d`))if(e=t.debugLines(),e)break;if(this.debugLines.visible=e!==null,!e)return;let t=new Float32Array(e.length/2*3);for(let n=0,r=0;n<e.length;n+=2,r+=3)t[r]=e[n],t[r+1]=e[n+1],t[r+2]=0;this.debugLines.geometry.setAttribute(`position`,new K(t,3))}render(){let e=this.engine.scene;if(!e)return;this.webgl.info.reset(),this.syncDebugLines(),this.syncSelectionOutline(),e.assets&&!this.loadedAssetScenes.has(e)&&(this.assets.load(e.assets),this.loadedAssetScenes.add(e));let t=e.environment?.background;this.worldScene.background=typeof t==`string`?new G(t):null;let n=this.canvas.clientWidth||this.canvas.width,r=this.canvas.clientHeight||this.canvas.height,i=this.webgl.getSize(fg);(i.x!==n||i.y!==r)&&this.webgl.setSize(n,r,!1);let a=this.viewOverride?null:gt(e.viewport),o=a?_t(n,r,a):null,s=o?o.viewW:n,c=o?o.viewH:r,{activeCamera:l}=sg(e.root,this.worldScene,this.uiScene,this.assets,{width:s,height:c},this.syncScratch),u=a?{x:a.design[0]/2,y:a.design[1]/2}:{x:n/2,y:r/2},d=1;this.viewOverride?(u={x:this.viewOverride.cx,y:this.viewOverride.cy},d=this.viewOverride.zoom):l&&(u=l.clampedCenter(s,c),d=l.effectiveZoom);let f=o?.scale??1;this.lastView={cx:u.x,cy:u.y,zoom:d*f,w:n,h:r},this.lastViewport=o,o&&(o.offsetX>.5||o.offsetY>.5)?(this.webgl.setScissorTest(!1),this.webgl.setViewport(0,0,n,r),this.webgl.clear(),this.webgl.setViewport(o.offsetX,o.offsetY,o.contentW,o.contentH),this.webgl.setScissor(o.offsetX,o.offsetY,o.contentW,o.contentH),this.webgl.setScissorTest(!0)):(this.webgl.setScissorTest(!1),this.webgl.setViewport(0,0,n,r)),dg(this.worldCam,u.x,u.y,s/d,c/d),dg(this.uiCam,s/2,c/2,s,c),this.webgl.autoClear=!0,this.webgl.render(this.worldScene,this.worldCam),this.webgl.autoClear=!1,this.webgl.render(this.uiScene,this.uiCam),this.webgl.autoClear=!0}lastViewport=null;lastView={cx:0,cy:0,zoom:1,w:1,h:1};view(){return{...this.lastView}}stats(){let e=this.webgl.info;return{triangles:e.render.triangles,drawCalls:e.render.calls,geometries:e.memory.geometries,textures:e.memory.textures}}worldFromScreen(e,t){return eg(this.lastView,e,t)}screenFromWorld(e,t){return $h(this.lastView,e,t)}pick(e,t){let{w:n,h:r}=this.lastView,i=this.lastViewport?.offsetX??0,a=this.lastViewport?.offsetY??0,o=this.lastViewport?.contentW??n,s=this.lastViewport?.contentH??r;mg.set((e-i)/o*2-1,-((t-a)/s*2-1)),hg.setFromCamera(mg,this.worldCam);let c=hg.intersectObjects(this.worldScene.children,!0),l=null;for(let e of c){let t=e.object;for(;t&&!t.userData.incantoNode;)t=t.parent;let n=t?.userData.incantoNode;if(!n)continue;let r=e.object.renderOrder??0;(!l||r>=l.order)&&(l={node:n,order:r})}return l?.node??null}boundsOf(e){let t=e._object2D;if(!t||(gg.makeEmpty(),gg.expandByObject(t),gg.isEmpty())||(gg.getSize(pg),pg.x===0&&pg.y===0))return null;let n=this.screenFromWorld(gg.min.x,-gg.max.y),r=this.screenFromWorld(gg.max.x,-gg.min.y);return{x:n.x,y:n.y,w:r.x-n.x,h:r.y-n.y}}dispose(){this.disconnect();for(let e of[this.worldScene,this.uiScene])e.traverse(e=>{let t=e;if(!t.isMesh)return;let n=Array.isArray(t.material)?t.material:[t.material];for(let e of n)e?.map?.dispose(),e?.dispose()});this.webgl.dispose()}};function dg(e,t,n,r,i){e.position.set(t,-n,10),e.left=-r/2,e.right=r/2,e.top=i/2,e.bottom=-i/2,e.updateProjectionMatrix()}var fg=new B,pg=new H,mg=new B,hg=new kl,gg=new Sa,_g=e({enablePhysics2D:()=>yh}),vg=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),yg=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),bg=class extends Zi{constructor(e){super(),this.weight=0,this.isBinary=!1,this.overrideBlink=`none`,this.overrideLookAt=`none`,this.overrideMouth=`none`,this._binds=[],this.name=`VRMExpression_${e}`,this.expressionName=e,this.type=`VRMExpression`,this.visible=!1}get binds(){return this._binds}get overrideBlinkAmount(){return this.overrideBlink===`block`?+(0<this.outputWeight):this.overrideBlink===`blend`?this.outputWeight:0}get overrideLookAtAmount(){return this.overrideLookAt===`block`?+(0<this.outputWeight):this.overrideLookAt===`blend`?this.outputWeight:0}get overrideMouthAmount(){return this.overrideMouth===`block`?+(0<this.outputWeight):this.overrideMouth===`blend`?this.outputWeight:0}get outputWeight(){return this.isBinary?+(this.weight>.5):this.weight}addBind(e){this._binds.push(e)}deleteBind(e){let t=this._binds.indexOf(e);t>=0&&this._binds.splice(t,1)}applyWeight(e){let t=this.outputWeight;t*=e?.multiplier??1,this.isBinary&&t<1&&(t=0),this._binds.forEach(e=>e.applyWeight(t))}clearAppliedWeight(){this._binds.forEach(e=>e.clearAppliedWeight())}};function xg(e,t,n){let r=e.parser.json,i=r.nodes?.[t];if(i==null)return console.warn(`extractPrimitivesInternal: Attempt to use nodes[${t}] of glTF but the node doesn't exist`),null;let a=i.mesh;if(a==null)return null;let o=r.meshes?.[a];if(o==null)return console.warn(`extractPrimitivesInternal: Attempt to use meshes[${a}] of glTF but the mesh doesn't exist`),null;let s=o.primitives.length,c=[];return n.traverse(e=>{c.length<s&&e.isMesh&&c.push(e)}),c}function Sg(e,t){return yg(this,null,function*(){return xg(e,t,yield e.parser.getDependency(`node`,t))})}function Cg(e){return yg(this,null,function*(){let t=yield e.parser.getDependencies(`node`),n=new Map;return t.forEach((t,r)=>{let i=xg(e,r,t);i!=null&&n.set(r,i)}),n})}var wg={Aa:`aa`,Ih:`ih`,Ou:`ou`,Ee:`ee`,Oh:`oh`,Blink:`blink`,Happy:`happy`,Angry:`angry`,Sad:`sad`,Relaxed:`relaxed`,LookUp:`lookUp`,Surprised:`surprised`,LookDown:`lookDown`,LookLeft:`lookLeft`,LookRight:`lookRight`,BlinkLeft:`blinkLeft`,BlinkRight:`blinkRight`,Neutral:`neutral`};function Tg(e){return Math.max(Math.min(e,1),0)}var Eg=class e{constructor(){this.blinkExpressionNames=[`blink`,`blinkLeft`,`blinkRight`],this.lookAtExpressionNames=[`lookLeft`,`lookRight`,`lookUp`,`lookDown`],this.mouthExpressionNames=[`aa`,`ee`,`ih`,`oh`,`ou`],this._expressions=[],this._expressionMap={}}get expressions(){return this._expressions.concat()}get expressionMap(){return Object.assign({},this._expressionMap)}get presetExpressionMap(){let e={},t=new Set(Object.values(wg));return Object.entries(this._expressionMap).forEach(([n,r])=>{t.has(n)&&(e[n]=r)}),e}get customExpressionMap(){let e={},t=new Set(Object.values(wg));return Object.entries(this._expressionMap).forEach(([n,r])=>{t.has(n)||(e[n]=r)}),e}copy(e){return this._expressions.concat().forEach(e=>{this.unregisterExpression(e)}),e._expressions.forEach(e=>{this.registerExpression(e)}),this.blinkExpressionNames=e.blinkExpressionNames.concat(),this.lookAtExpressionNames=e.lookAtExpressionNames.concat(),this.mouthExpressionNames=e.mouthExpressionNames.concat(),this}clone(){return new e().copy(this)}getExpression(e){return this._expressionMap[e]??null}registerExpression(e){this._expressions.push(e),this._expressionMap[e.expressionName]=e}unregisterExpression(e){let t=this._expressions.indexOf(e);t===-1&&console.warn(`VRMExpressionManager: The specified expressions is not registered`),this._expressions.splice(t,1),delete this._expressionMap[e.expressionName]}getValue(e){return this.getExpression(e)?.weight??null}setValue(e,t){let n=this.getExpression(e);n&&(n.weight=Tg(t))}resetValues(){this._expressions.forEach(e=>{e.weight=0})}getExpressionTrackName(e){let t=this.getExpression(e);return t?`${t.name}.weight`:null}update(){let e=this._calculateWeightMultipliers();this._expressions.forEach(e=>{e.clearAppliedWeight()}),this._expressions.forEach(t=>{let n=1,r=t.expressionName;this.blinkExpressionNames.indexOf(r)!==-1&&(n*=e.blink),this.lookAtExpressionNames.indexOf(r)!==-1&&(n*=e.lookAt),this.mouthExpressionNames.indexOf(r)!==-1&&(n*=e.mouth),t.applyWeight({multiplier:n})})}_calculateWeightMultipliers(){let e=1,t=1,n=1;return this._expressions.forEach(r=>{e-=r.overrideBlinkAmount,t-=r.overrideLookAtAmount,n-=r.overrideMouthAmount}),e=Math.max(0,e),t=Math.max(0,t),n=Math.max(0,n),{blink:e,lookAt:t,mouth:n}}},Dg={Color:`color`,EmissionColor:`emissionColor`,ShadeColor:`shadeColor`,MatcapColor:`matcapColor`,RimColor:`rimColor`,OutlineColor:`outlineColor`},Og={_Color:Dg.Color,_EmissionColor:Dg.EmissionColor,_ShadeColor:Dg.ShadeColor,_RimColor:Dg.RimColor,_OutlineColor:Dg.OutlineColor},kg=new G,Ag=class e{constructor({material:e,type:t,targetValue:n,targetAlpha:r}){this.material=e,this.type=t,this.targetValue=n,this.targetAlpha=r??1;let i=this._initColorBindState(),a=this._initAlphaBindState();this._state={color:i,alpha:a}}applyWeight(e){let{color:t,alpha:n}=this._state;if(t!=null){let{propertyName:n,deltaValue:r}=t;this.material[n]?.add(kg.copy(r).multiplyScalar(e))}if(n!=null){let{propertyName:t,deltaValue:r}=n;this.material[t]!=null&&(this.material[t]+=r*e)}}clearAppliedWeight(){let{color:e,alpha:t}=this._state;if(e!=null){let{propertyName:t,initialValue:n}=e;this.material[t]?.copy(n)}if(t!=null){let{propertyName:e,initialValue:n}=t;this.material[e]!=null&&(this.material[e]=n)}}_initColorBindState(){let{material:e,type:t,targetValue:n}=this,r=this._getPropertyNameMap()?.[t]?.[0]??null;if(r==null)return console.warn(`Tried to add a material color bind to the material ${e.name??`(no name)`}, the type ${t} but the material or the type is not supported.`),null;let i=e[r].clone();return{propertyName:r,initialValue:i,deltaValue:new G(n.r-i.r,n.g-i.g,n.b-i.b)}}_initAlphaBindState(){let{material:e,type:t,targetAlpha:n}=this,r=this._getPropertyNameMap()?.[t]?.[1]??null;if(r==null&&n!==1)return console.warn(`Tried to add a material alpha bind to the material ${e.name??`(no name)`}, the type ${t} but the material or the type does not support alpha.`),null;if(r==null)return null;let i=e[r];return{propertyName:r,initialValue:i,deltaValue:n-i}}_getPropertyNameMap(){return Object.entries(e._propertyNameMapMap).find(([e])=>this.material[e]===!0)?.[1]??null}};Ag._propertyNameMapMap={isMeshStandardMaterial:{color:[`color`,`opacity`],emissionColor:[`emissive`,null]},isMeshBasicMaterial:{color:[`color`,`opacity`]},isMToonMaterial:{color:[`color`,`opacity`],emissionColor:[`emissive`,null],outlineColor:[`outlineColorFactor`,null],matcapColor:[`matcapFactor`,null],rimColor:[`parametricRimColorFactor`,null],shadeColor:[`shadeColorFactor`,null]}};var jg=Ag,Mg=class{constructor({primitives:e,index:t,weight:n}){this.primitives=e,this.index=t,this.weight=n}applyWeight(e){this.primitives.forEach(t=>{t.morphTargetInfluences?.[this.index]!=null&&(t.morphTargetInfluences[this.index]+=this.weight*e)})}clearAppliedWeight(){this.primitives.forEach(e=>{e.morphTargetInfluences?.[this.index]!=null&&(e.morphTargetInfluences[this.index]=0)})}},Ng=new B,Pg=class e{constructor({material:t,scale:n,offset:r}){this.material=t,this.scale=n,this.offset=r;let i=Object.entries(e._propertyNamesMap).find(([e])=>t[e]===!0)?.[1];i==null?(console.warn(`Tried to add a texture transform bind to the material ${t.name??`(no name)`} but the material is not supported.`),this._properties=[]):(this._properties=[],i.forEach(e=>{let i=t[e]?.clone();if(!i)return null;t[e]=i;let a=i.offset.clone(),o=i.repeat.clone(),s=r.clone().sub(a),c=n.clone().sub(o);this._properties.push({name:e,initialOffset:a,deltaOffset:s,initialScale:o,deltaScale:c})}))}applyWeight(e){this._properties.forEach(t=>{let n=this.material[t.name];n!==void 0&&(n.offset.add(Ng.copy(t.deltaOffset).multiplyScalar(e)),n.repeat.add(Ng.copy(t.deltaScale).multiplyScalar(e)))})}clearAppliedWeight(){this._properties.forEach(e=>{let t=this.material[e.name];t!==void 0&&(t.offset.copy(e.initialOffset),t.repeat.copy(e.initialScale))})}};Pg._propertyNamesMap={isMeshStandardMaterial:[`map`,`emissiveMap`,`bumpMap`,`normalMap`,`displacementMap`,`roughnessMap`,`metalnessMap`,`alphaMap`],isMeshBasicMaterial:[`map`,`specularMap`,`alphaMap`],isMToonMaterial:[`map`,`normalMap`,`emissiveMap`,`shadeMultiplyTexture`,`rimMultiplyTexture`,`outlineWidthMultiplyTexture`,`uvAnimationMaskTexture`]};var Fg=Pg,Ig=new Set([`1.0`,`1.0-beta`]),Lg=class e{get name(){return`VRMExpressionLoaderPlugin`}constructor(e){this.parser=e}afterRoot(e){return yg(this,null,function*(){e.userData.vrmExpressionManager=yield this._import(e)})}_import(e){return yg(this,null,function*(){return(yield this._v1Import(e))||(yield this._v0Import(e))||null})}_v1Import(e){return yg(this,null,function*(){let t=this.parser.json;if(t.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let n=t.extensions?.VRMC_vrm;if(!n)return null;let r=n.specVersion;if(!Ig.has(r))return console.warn(`VRMExpressionLoaderPlugin: Unknown VRMC_vrm specVersion "${r}"`),null;let i=n.expressions;if(!i)return null;let a=new Set(Object.values(wg)),o=new Map;i.preset!=null&&Object.entries(i.preset).forEach(([e,t])=>{if(t!=null){if(!a.has(e)){console.warn(`VRMExpressionLoaderPlugin: Unknown preset name "${e}" detected. Ignoring the expression`);return}o.set(e,t)}}),i.custom!=null&&Object.entries(i.custom).forEach(([e,t])=>{if(a.has(e)){console.warn(`VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${e}". Ignoring the expression`);return}o.set(e,t)});let s=new Eg;return yield Promise.all(Array.from(o.entries()).map(t=>yg(this,[t],function*([t,n]){var r,i,a;let o=new bg(t);if(e.scene.add(o),o.isBinary=n.isBinary??!1,o.overrideBlink=n.overrideBlink??`none`,o.overrideLookAt=n.overrideLookAt??`none`,o.overrideMouth=n.overrideMouth??`none`,(r=n.morphTargetBinds)==null||r.forEach(t=>yg(this,null,function*(){if(t.node===void 0||t.index===void 0)return;let r=yield Sg(e,t.node),i=t.index;if(!r.every(e=>Array.isArray(e.morphTargetInfluences)&&i<e.morphTargetInfluences.length)){console.warn(`VRMExpressionLoaderPlugin: ${n.name} attempts to index morph #${i} but not found.`);return}o.addBind(new Mg({primitives:r,index:i,weight:t.weight??1}))})),n.materialColorBinds||n.textureTransformBinds){let t=[];e.scene.traverse(e=>{let n=e.material;n&&(Array.isArray(n)?t.push(...n):t.push(n))}),(i=n.materialColorBinds)==null||i.forEach(e=>yg(this,null,function*(){t.filter(t=>{let n=this.parser.associations.get(t)?.materials;return e.material===n}).forEach(t=>{o.addBind(new jg({material:t,type:e.type,targetValue:new G().fromArray(e.targetValue),targetAlpha:e.targetValue[3]}))})})),(a=n.textureTransformBinds)==null||a.forEach(e=>yg(this,null,function*(){t.filter(t=>{let n=this.parser.associations.get(t)?.materials;return e.material===n}).forEach(t=>{o.addBind(new Fg({material:t,offset:new B().fromArray(e.offset??[0,0]),scale:new B().fromArray(e.scale??[1,1])}))})}))}s.registerExpression(o)}))),s})}_v0Import(t){return yg(this,null,function*(){let n=this.parser.json,r=n.extensions?.VRM;if(!r)return null;let i=r.blendShapeMaster;if(!i)return null;let a=new Eg,o=i.blendShapeGroups;if(!o)return a;let s=new Set;return yield Promise.all(o.map(r=>yg(this,null,function*(){let i=r.presetName,o=(i!=null&&e.v0v1PresetNameMap[i]||null)??r.name;if(o==null){console.warn(`VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression`);return}if(s.has(o)){console.warn(`VRMExpressionLoaderPlugin: An expression preset ${i} has duplicated entries. Ignoring the expression`);return}s.add(o);let c=new bg(o);t.scene.add(c),c.isBinary=r.isBinary??!1,r.binds&&r.binds.forEach(e=>yg(this,null,function*(){var i;if(e.mesh===void 0||e.index===void 0)return;let a=[];(i=n.nodes)==null||i.forEach((t,n)=>{t.mesh===e.mesh&&a.push(n)});let o=e.index;yield Promise.all(a.map(n=>yg(this,null,function*(){let i=yield Sg(t,n);if(!i.every(e=>Array.isArray(e.morphTargetInfluences)&&o<e.morphTargetInfluences.length)){console.warn(`VRMExpressionLoaderPlugin: ${r.name} attempts to index ${o}th morph but not found.`);return}c.addBind(new Mg({primitives:i,index:o,weight:.01*(e.weight??100)}))})))}));let l=r.materialValues;l&&l.length!==0&&l.forEach(e=>{if(e.materialName===void 0||e.propertyName===void 0||e.targetValue===void 0)return;let n=[];t.scene.traverse(t=>{if(t.material){let r=t.material;Array.isArray(r)?n.push(...r.filter(t=>(t.name===e.materialName||t.name===e.materialName+` (Outline)`)&&n.indexOf(t)===-1)):r.name===e.materialName&&n.indexOf(r)===-1&&n.push(r)}});let r=e.propertyName;n.forEach(t=>{if(r===`_MainTex_ST`){let n=new B(e.targetValue[0],e.targetValue[1]),r=new B(e.targetValue[2],e.targetValue[3]);r.y=1-r.y-n.y,c.addBind(new Fg({material:t,scale:n,offset:r}));return}let n=Og[r];if(n){c.addBind(new jg({material:t,type:n,targetValue:new G().fromArray(e.targetValue),targetAlpha:e.targetValue[3]}));return}console.warn(r+` is not supported`)})}),a.registerExpression(c)}))),a})}};Lg.v0v1PresetNameMap={a:`aa`,e:`ee`,i:`ih`,o:`oh`,u:`ou`,blink:`blink`,joy:`happy`,angry:`angry`,sorrow:`sad`,fun:`relaxed`,lookup:`lookUp`,lookdown:`lookDown`,lookleft:`lookLeft`,lookright:`lookRight`,blink_l:`blinkLeft`,blink_r:`blinkRight`,neutral:`neutral`};var Rg=Lg,zg=class e{constructor(t,n){this._firstPersonOnlyLayer=e.DEFAULT_FIRSTPERSON_ONLY_LAYER,this._thirdPersonOnlyLayer=e.DEFAULT_THIRDPERSON_ONLY_LAYER,this._initializedLayers=!1,this.humanoid=t,this.meshAnnotations=n}copy(e){if(this.humanoid!==e.humanoid)throw Error(`VRMFirstPerson: humanoid must be same in order to copy`);return this.meshAnnotations=e.meshAnnotations.map(e=>({meshes:e.meshes.concat(),type:e.type})),this}clone(){return new e(this.humanoid,this.meshAnnotations).copy(this)}get firstPersonOnlyLayer(){return this._firstPersonOnlyLayer}get thirdPersonOnlyLayer(){return this._thirdPersonOnlyLayer}setup({firstPersonOnlyLayer:t=e.DEFAULT_FIRSTPERSON_ONLY_LAYER,thirdPersonOnlyLayer:n=e.DEFAULT_THIRDPERSON_ONLY_LAYER}={}){this._initializedLayers||=(this._firstPersonOnlyLayer=t,this._thirdPersonOnlyLayer=n,this.meshAnnotations.forEach(e=>{e.meshes.forEach(t=>{e.type===`firstPersonOnly`?(t.layers.set(this._firstPersonOnlyLayer),t.traverse(e=>e.layers.set(this._firstPersonOnlyLayer))):e.type===`thirdPersonOnly`?(t.layers.set(this._thirdPersonOnlyLayer),t.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer))):e.type===`auto`&&this._createHeadlessModel(t)})}),!0)}_excludeTriangles(e,t,n,r){let i=0;if(t!=null&&t.length>0)for(let a=0;a<e.length;a+=3){let o=e[a],s=e[a+1],c=e[a+2],l=t[o],u=n[o];if(l[0]>0&&r.includes(u[0])||l[1]>0&&r.includes(u[1])||l[2]>0&&r.includes(u[2])||l[3]>0&&r.includes(u[3]))continue;let d=t[s],f=n[s];if(d[0]>0&&r.includes(f[0])||d[1]>0&&r.includes(f[1])||d[2]>0&&r.includes(f[2])||d[3]>0&&r.includes(f[3]))continue;let p=t[c],m=n[c];p[0]>0&&r.includes(m[0])||p[1]>0&&r.includes(m[1])||p[2]>0&&r.includes(m[2])||p[3]>0&&r.includes(m[3])||(e[i++]=o,e[i++]=s,e[i++]=c)}return i}_createErasedMesh(e,t){let n=new Uo(e.geometry.clone(),e.material);n.name=`${e.name}(erase)`,n.frustumCulled=e.frustumCulled,n.layers.set(this._firstPersonOnlyLayer);let r=n.geometry,i=r.getAttribute(`skinIndex`),a=i instanceof Dl?[]:i.array,o=[];for(let e=0;e<a.length;e+=4)o.push([a[e],a[e+1],a[e+2],a[e+3]]);let s=r.getAttribute(`skinWeight`),c=s instanceof Dl?[]:s.array,l=[];for(let e=0;e<c.length;e+=4)l.push([c[e],c[e+1],c[e+2],c[e+3]]);let u=r.getIndex();if(!u)throw Error(`The geometry doesn't have an index buffer`);let d=Array.from(u.array),f=this._excludeTriangles(d,l,o,t),p=[];for(let e=0;e<f;e++)p[e]=d[e];return r.setIndex(p),e.onBeforeRender&&(n.onBeforeRender=e.onBeforeRender),n.bind(new Jo(e.skeleton.bones,e.skeleton.boneInverses),new W),n}_createHeadlessModelForSkinnedMesh(e,t){let n=[];if(t.skeleton.bones.forEach((e,t)=>{this._isEraseTarget(e)&&n.push(t)}),!n.length){t.layers.enable(this._thirdPersonOnlyLayer),t.layers.enable(this._firstPersonOnlyLayer);return}t.layers.set(this._thirdPersonOnlyLayer);let r=this._createErasedMesh(t,n);e.add(r)}_createHeadlessModel(e){if(e.type===`Group`)if(e.layers.set(this._thirdPersonOnlyLayer),this._isEraseTarget(e))e.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer));else{let t=new Qi;t.name=`_headless_${e.name}`,t.layers.set(this._firstPersonOnlyLayer),e.parent.add(t),e.children.filter(e=>e.type===`SkinnedMesh`).forEach(e=>{let n=e;this._createHeadlessModelForSkinnedMesh(t,n)})}else if(e.type===`SkinnedMesh`){let t=e;this._createHeadlessModelForSkinnedMesh(e.parent,t)}else this._isEraseTarget(e)&&(e.layers.set(this._thirdPersonOnlyLayer),e.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer)))}_isEraseTarget(e){return e===this.humanoid.getRawBoneNode(`head`)?!0:e.parent?this._isEraseTarget(e.parent):!1}};zg.DEFAULT_FIRSTPERSON_ONLY_LAYER=9,zg.DEFAULT_THIRDPERSON_ONLY_LAYER=10;var Bg=zg,Vg=new Set([`1.0`,`1.0-beta`]),Hg=class{get name(){return`VRMFirstPersonLoaderPlugin`}constructor(e){this.parser=e}afterRoot(e){return yg(this,null,function*(){let t=e.userData.vrmHumanoid;if(t!==null){if(t===void 0)throw Error(`VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first`);e.userData.vrmFirstPerson=yield this._import(e,t)}})}_import(e,t){return yg(this,null,function*(){return t==null?null:(yield this._v1Import(e,t))||(yield this._v0Import(e,t))||null})}_v1Import(e,t){return yg(this,null,function*(){let n=this.parser.json;if(n.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let r=n.extensions?.VRMC_vrm;if(!r)return null;let i=r.specVersion;if(!Vg.has(i))return console.warn(`VRMFirstPersonLoaderPlugin: Unknown VRMC_vrm specVersion "${i}"`),null;let a=r.firstPerson,o=[],s=yield Cg(e);return Array.from(s.entries()).forEach(([e,t])=>{let n=(a?.meshAnnotations)?.find(t=>t.node===e);o.push({meshes:t,type:n?.type??`auto`})}),new Bg(t,o)})}_v0Import(e,t){return yg(this,null,function*(){let n=this.parser.json,r=n.extensions?.VRM;if(!r)return null;let i=r.firstPerson;if(!i)return null;let a=[],o=yield Cg(e);return Array.from(o.entries()).forEach(([e,t])=>{let r=n.nodes[e],o=i.meshAnnotations?i.meshAnnotations.find(e=>e.mesh===r.mesh):void 0;a.push({meshes:t,type:this._convertV0FlagToV1Type(o?.firstPersonFlag)})}),new Bg(t,a)})}_convertV0FlagToV1Type(e){return e===`FirstPersonOnly`?`firstPersonOnly`:e===`ThirdPersonOnly`?`thirdPersonOnly`:e===`Both`?`both`:`auto`}},Ug=new H,Wg=new H,Gg=new V,Kg=class extends Qi{constructor(e){super(),this.vrmHumanoid=e,this._boneAxesMap=new Map,Object.values(e.humanBones).forEach(e=>{let t=new Ml(1);t.matrixAutoUpdate=!1,t.material.depthTest=!1,t.material.depthWrite=!1,this.add(t),this._boneAxesMap.set(e,t)})}dispose(){Array.from(this._boneAxesMap.values()).forEach(e=>{e.geometry.dispose(),e.material.dispose()})}updateMatrixWorld(e){Array.from(this._boneAxesMap.entries()).forEach(([e,t])=>{e.node.updateWorldMatrix(!0,!1),e.node.matrixWorld.decompose(Ug,Gg,Wg);let n=Ug.set(.1,.1,.1).divide(Wg);t.matrix.copy(e.node.matrixWorld).scale(n)}),super.updateMatrixWorld(e)}},qg=`hips.spine.chest.upperChest.neck.head.leftEye.rightEye.jaw.leftUpperLeg.leftLowerLeg.leftFoot.leftToes.rightUpperLeg.rightLowerLeg.rightFoot.rightToes.leftShoulder.leftUpperArm.leftLowerArm.leftHand.rightShoulder.rightUpperArm.rightLowerArm.rightHand.leftThumbMetacarpal.leftThumbProximal.leftThumbDistal.leftIndexProximal.leftIndexIntermediate.leftIndexDistal.leftMiddleProximal.leftMiddleIntermediate.leftMiddleDistal.leftRingProximal.leftRingIntermediate.leftRingDistal.leftLittleProximal.leftLittleIntermediate.leftLittleDistal.rightThumbMetacarpal.rightThumbProximal.rightThumbDistal.rightIndexProximal.rightIndexIntermediate.rightIndexDistal.rightMiddleProximal.rightMiddleIntermediate.rightMiddleDistal.rightRingProximal.rightRingIntermediate.rightRingDistal.rightLittleProximal.rightLittleIntermediate.rightLittleDistal`.split(`.`),Jg={hips:null,spine:`hips`,chest:`spine`,upperChest:`chest`,neck:`upperChest`,head:`neck`,leftEye:`head`,rightEye:`head`,jaw:`head`,leftUpperLeg:`hips`,leftLowerLeg:`leftUpperLeg`,leftFoot:`leftLowerLeg`,leftToes:`leftFoot`,rightUpperLeg:`hips`,rightLowerLeg:`rightUpperLeg`,rightFoot:`rightLowerLeg`,rightToes:`rightFoot`,leftShoulder:`upperChest`,leftUpperArm:`leftShoulder`,leftLowerArm:`leftUpperArm`,leftHand:`leftLowerArm`,rightShoulder:`upperChest`,rightUpperArm:`rightShoulder`,rightLowerArm:`rightUpperArm`,rightHand:`rightLowerArm`,leftThumbMetacarpal:`leftHand`,leftThumbProximal:`leftThumbMetacarpal`,leftThumbDistal:`leftThumbProximal`,leftIndexProximal:`leftHand`,leftIndexIntermediate:`leftIndexProximal`,leftIndexDistal:`leftIndexIntermediate`,leftMiddleProximal:`leftHand`,leftMiddleIntermediate:`leftMiddleProximal`,leftMiddleDistal:`leftMiddleIntermediate`,leftRingProximal:`leftHand`,leftRingIntermediate:`leftRingProximal`,leftRingDistal:`leftRingIntermediate`,leftLittleProximal:`leftHand`,leftLittleIntermediate:`leftLittleProximal`,leftLittleDistal:`leftLittleIntermediate`,rightThumbMetacarpal:`rightHand`,rightThumbProximal:`rightThumbMetacarpal`,rightThumbDistal:`rightThumbProximal`,rightIndexProximal:`rightHand`,rightIndexIntermediate:`rightIndexProximal`,rightIndexDistal:`rightIndexIntermediate`,rightMiddleProximal:`rightHand`,rightMiddleIntermediate:`rightMiddleProximal`,rightMiddleDistal:`rightMiddleIntermediate`,rightRingProximal:`rightHand`,rightRingIntermediate:`rightRingProximal`,rightRingDistal:`rightRingIntermediate`,rightLittleProximal:`rightHand`,rightLittleIntermediate:`rightLittleProximal`,rightLittleDistal:`rightLittleIntermediate`};function Yg(e){return e.invert?e.invert():e.inverse(),e}var Xg=new H,Zg=new V,Qg=class{constructor(e){this.humanBones=e,this.restPose=this.getAbsolutePose()}getAbsolutePose(){let e={};return Object.keys(this.humanBones).forEach(t=>{let n=t,r=this.getBoneNode(n);r&&(Xg.copy(r.position),Zg.copy(r.quaternion),e[n]={position:Xg.toArray(),rotation:Zg.toArray()})}),e}getPose(){let e={};return Object.keys(this.humanBones).forEach(t=>{let n=t,r=this.getBoneNode(n);if(!r)return;Xg.set(0,0,0),Zg.identity();let i=this.restPose[n];i?.position&&Xg.fromArray(i.position).negate(),i?.rotation&&Yg(Zg.fromArray(i.rotation)),Xg.add(r.position),Zg.premultiply(r.quaternion),e[n]={position:Xg.toArray(),rotation:Zg.toArray()}}),e}setPose(e){Object.entries(e).forEach(([e,t])=>{let n=e,r=this.getBoneNode(n);if(!r)return;let i=this.restPose[n];i&&(t?.position&&(r.position.fromArray(t.position),i.position&&r.position.add(Xg.fromArray(i.position))),t?.rotation&&(r.quaternion.fromArray(t.rotation),i.rotation&&r.quaternion.multiply(Zg.fromArray(i.rotation))))})}resetPose(){Object.entries(this.restPose).forEach(([e,t])=>{let n=this.getBoneNode(e);n&&(t?.position&&n.position.fromArray(t.position),t?.rotation&&n.quaternion.fromArray(t.rotation))})}getBone(e){return this.humanBones[e]??void 0}getBoneNode(e){return this.humanBones[e]?.node??null}},$g=new H,e_=new V,t_=new H,n_=class e extends Qg{static _setupTransforms(e){let t=new Zi;t.name=`VRMHumanoidRig`;let n={},r={},i={},a={};qg.forEach(t=>{var o;let s=e.getBoneNode(t);if(s){let e=new H,c=new V;s.updateWorldMatrix(!0,!1),s.matrixWorld.decompose(e,c,$g),n[t]=e,r[t]=c,i[t]=s.quaternion.clone();let l=new V;(o=s.parent)==null||o.matrixWorld.decompose($g,l,$g),a[t]=l}});let o={};return qg.forEach(r=>{let i=e.getBoneNode(r);if(i){let e=n[r],a=r,s;for(;s==null&&(a=Jg[a],a!=null);)s=n[a];let c=new Zi;c.name=`Normalized_`+i.name,(a?o[a]?.node:t).add(c),c.position.copy(e),s&&c.position.sub(s),o[r]={node:c}}}),{rigBones:o,root:t,parentWorldRotations:a,boneRotations:i}}constructor(t){let{rigBones:n,root:r,parentWorldRotations:i,boneRotations:a}=e._setupTransforms(t);super(n),this.original=t,this.root=r,this._parentWorldRotations=i,this._boneRotations=a}update(){qg.forEach(e=>{let t=this.original.getBoneNode(e);if(t!=null){let n=this.getBoneNode(e),r=this._parentWorldRotations[e],i=e_.copy(r).invert(),a=this._boneRotations[e];if(t.quaternion.copy(n.quaternion).multiply(r).premultiply(i).multiply(a),e===`hips`){let e=n.getWorldPosition(t_);t.parent.updateWorldMatrix(!0,!1);let r=t.parent.matrixWorld,i=e.applyMatrix4(r.invert());t.position.copy(i)}}})}},r_=class e{get restPose(){return console.warn(`VRMHumanoid: restPose is deprecated. Use either rawRestPose or normalizedRestPose instead.`),this.rawRestPose}get rawRestPose(){return this._rawHumanBones.restPose}get normalizedRestPose(){return this._normalizedHumanBones.restPose}get humanBones(){return this._rawHumanBones.humanBones}get rawHumanBones(){return this._rawHumanBones.humanBones}get normalizedHumanBones(){return this._normalizedHumanBones.humanBones}get normalizedHumanBonesRoot(){return this._normalizedHumanBones.root}constructor(e,t){this.autoUpdateHumanBones=t?.autoUpdateHumanBones??!0,this._rawHumanBones=new Qg(e),this._normalizedHumanBones=new n_(this._rawHumanBones)}copy(e){return this.autoUpdateHumanBones=e.autoUpdateHumanBones,this._rawHumanBones=new Qg(e.humanBones),this._normalizedHumanBones=new n_(this._rawHumanBones),this}clone(){return new e(this.humanBones,{autoUpdateHumanBones:this.autoUpdateHumanBones}).copy(this)}getAbsolutePose(){return console.warn(`VRMHumanoid: getAbsolutePose() is deprecated. Use either getRawAbsolutePose() or getNormalizedAbsolutePose() instead.`),this.getRawAbsolutePose()}getRawAbsolutePose(){return this._rawHumanBones.getAbsolutePose()}getNormalizedAbsolutePose(){return this._normalizedHumanBones.getAbsolutePose()}getPose(){return console.warn(`VRMHumanoid: getPose() is deprecated. Use either getRawPose() or getNormalizedPose() instead.`),this.getRawPose()}getRawPose(){return this._rawHumanBones.getPose()}getNormalizedPose(){return this._normalizedHumanBones.getPose()}setPose(e){return console.warn(`VRMHumanoid: setPose() is deprecated. Use either setRawPose() or setNormalizedPose() instead.`),this.setRawPose(e)}setRawPose(e){return this._rawHumanBones.setPose(e)}setNormalizedPose(e){return this._normalizedHumanBones.setPose(e)}resetPose(){return console.warn(`VRMHumanoid: resetPose() is deprecated. Use either resetRawPose() or resetNormalizedPose() instead.`),this.resetRawPose()}resetRawPose(){return this._rawHumanBones.resetPose()}resetNormalizedPose(){return this._normalizedHumanBones.resetPose()}getBone(e){return console.warn(`VRMHumanoid: getBone() is deprecated. Use either getRawBone() or getNormalizedBone() instead.`),this.getRawBone(e)}getRawBone(e){return this._rawHumanBones.getBone(e)}getNormalizedBone(e){return this._normalizedHumanBones.getBone(e)}getBoneNode(e){return console.warn(`VRMHumanoid: getBoneNode() is deprecated. Use either getRawBoneNode() or getNormalizedBoneNode() instead.`),this.getRawBoneNode(e)}getRawBoneNode(e){return this._rawHumanBones.getBoneNode(e)}getNormalizedBoneNode(e){return this._normalizedHumanBones.getBoneNode(e)}update(){this.autoUpdateHumanBones&&this._normalizedHumanBones.update()}},i_={Hips:`hips`,Spine:`spine`,Head:`head`,LeftUpperLeg:`leftUpperLeg`,LeftLowerLeg:`leftLowerLeg`,LeftFoot:`leftFoot`,RightUpperLeg:`rightUpperLeg`,RightLowerLeg:`rightLowerLeg`,RightFoot:`rightFoot`,LeftUpperArm:`leftUpperArm`,LeftLowerArm:`leftLowerArm`,LeftHand:`leftHand`,RightUpperArm:`rightUpperArm`,RightLowerArm:`rightLowerArm`,RightHand:`rightHand`},a_=new Set([`1.0`,`1.0-beta`]),o_={leftThumbProximal:`leftThumbMetacarpal`,leftThumbIntermediate:`leftThumbProximal`,rightThumbProximal:`rightThumbMetacarpal`,rightThumbIntermediate:`rightThumbProximal`},s_=class{get name(){return`VRMHumanoidLoaderPlugin`}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot,this.autoUpdateHumanBones=t?.autoUpdateHumanBones}afterRoot(e){return yg(this,null,function*(){e.userData.vrmHumanoid=yield this._import(e)})}_import(e){return yg(this,null,function*(){return(yield this._v1Import(e))||(yield this._v0Import(e))||null})}_v1Import(e){return yg(this,null,function*(){let t=this.parser.json;if(t.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let n=t.extensions?.VRMC_vrm;if(!n)return null;let r=n.specVersion;if(!a_.has(r))return console.warn(`VRMHumanoidLoaderPlugin: Unknown VRMC_vrm specVersion "${r}"`),null;let i=n.humanoid;if(!i)return null;let a=i.humanBones.leftThumbIntermediate!=null||i.humanBones.rightThumbIntermediate!=null,o={};i.humanBones!=null&&(yield Promise.all(Object.entries(i.humanBones).map(e=>yg(this,[e],function*([e,t]){let n=e,r=t.node;if(a){let e=o_[n];e!=null&&(n=e)}let i=yield this.parser.getDependency(`node`,r);if(i==null){console.warn(`A glTF node bound to the humanoid bone ${n} (index = ${r}) does not exist`);return}o[n]={node:i}}))));let s=new r_(this._ensureRequiredBonesExist(o),{autoUpdateHumanBones:this.autoUpdateHumanBones});if(e.scene.add(s.normalizedHumanBonesRoot),this.helperRoot){let e=new Kg(s);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return s})}_v0Import(e){return yg(this,null,function*(){let t=this.parser.json.extensions?.VRM;if(!t)return null;let n=t.humanoid;if(!n)return null;let r={};n.humanBones!=null&&(yield Promise.all(n.humanBones.map(e=>yg(this,null,function*(){let t=e.bone,n=e.node;if(t==null||n==null)return;let i=yield this.parser.getDependency(`node`,n);if(i==null){console.warn(`A glTF node bound to the humanoid bone ${t} (index = ${n}) does not exist`);return}let a=o_[t]??t;if(r[a]!=null){console.warn(`Multiple bone entries for ${a} detected (index = ${n}), ignoring duplicated entries.`);return}r[a]={node:i}}))));let i=new r_(this._ensureRequiredBonesExist(r),{autoUpdateHumanBones:this.autoUpdateHumanBones});if(e.scene.add(i.normalizedHumanBonesRoot),this.helperRoot){let e=new Kg(i);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return i})}_ensureRequiredBonesExist(e){let t=Object.values(i_).filter(t=>e[t]==null);if(t.length>0)throw Error(`VRMHumanoidLoaderPlugin: These humanoid bones are required but not exist: ${t.join(`, `)}`);return e}},c_=class extends q{constructor(){super(),this._currentTheta=0,this._currentRadius=0,this.theta=0,this.radius=0,this._currentTheta=0,this._currentRadius=0,this._attrPos=new K(new Float32Array(195),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(189),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentTheta!==this.theta&&(this._currentTheta=this.theta,e=!0),this._currentRadius!==this.radius&&(this._currentRadius=this.radius,e=!0),e&&this._buildPosition()}_buildPosition(){this._attrPos.setXYZ(0,0,0,0);for(let e=0;e<64;e++){let t=e/63*this._currentTheta;this._attrPos.setXYZ(e+1,this._currentRadius*Math.sin(t),0,this._currentRadius*Math.cos(t))}this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<63;e++)this._attrIndex.setXYZ(e*3,0,e+1,e+2);this._attrIndex.needsUpdate=!0}},l_=class extends q{constructor(){super(),this.radius=0,this._currentRadius=0,this.tail=new H,this._currentTail=new H,this._attrPos=new K(new Float32Array(294),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(194),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentRadius!==this.radius&&(this._currentRadius=this.radius,e=!0),this._currentTail.equals(this.tail)||(this._currentTail.copy(this.tail),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.setXYZ(96,0,0,0),this._attrPos.setXYZ(97,this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.setXY(192,96,97),this._attrIndex.needsUpdate=!0}},u_=new V,d_=new V,f_=new H,p_=new H,m_=Math.sqrt(2)/2,h_=new V(0,0,-m_,m_),g_=new H(0,1,0),__=class extends Qi{constructor(e){super(),this.matrixAutoUpdate=!1,this.vrmLookAt=e;{let e=new c_;e.radius=.5;let t=new yo({color:65280,transparent:!0,opacity:.5,side:2,depthTest:!1,depthWrite:!1});this._meshPitch=new jo(e,t),this.add(this._meshPitch)}{let e=new c_;e.radius=.5;let t=new yo({color:16711680,transparent:!0,opacity:.5,side:2,depthTest:!1,depthWrite:!1});this._meshYaw=new jo(e,t),this.add(this._meshYaw)}{let e=new l_;e.radius=.1;let t=new fs({color:16777215,depthTest:!1,depthWrite:!1});this._lineTarget=new ws(e,t),this._lineTarget.frustumCulled=!1,this.add(this._lineTarget)}}dispose(){this._meshYaw.geometry.dispose(),this._meshYaw.material.dispose(),this._meshPitch.geometry.dispose(),this._meshPitch.material.dispose(),this._lineTarget.geometry.dispose(),this._lineTarget.material.dispose()}updateMatrixWorld(e){let t=ni.DEG2RAD*this.vrmLookAt.yaw;this._meshYaw.geometry.theta=t,this._meshYaw.geometry.update();let n=ni.DEG2RAD*this.vrmLookAt.pitch;this._meshPitch.geometry.theta=n,this._meshPitch.geometry.update(),this.vrmLookAt.getLookAtWorldPosition(f_),this.vrmLookAt.getLookAtWorldQuaternion(u_),u_.multiply(this.vrmLookAt.getFaceFrontQuaternion(d_)),this._meshYaw.position.copy(f_),this._meshYaw.quaternion.copy(u_),this._meshPitch.position.copy(f_),this._meshPitch.quaternion.copy(u_),this._meshPitch.quaternion.multiply(d_.setFromAxisAngle(g_,t)),this._meshPitch.quaternion.multiply(h_);let{target:r,autoUpdate:i}=this.vrmLookAt;r!=null&&i&&(r.getWorldPosition(p_).sub(f_),this._lineTarget.geometry.tail.copy(p_),this._lineTarget.geometry.update(),this._lineTarget.position.copy(f_)),super.updateMatrixWorld(e)}},v_=new H,y_=new H;function b_(e,t){return e.matrixWorld.decompose(v_,t,y_),t}function x_(e){return[Math.atan2(-e.z,e.x),Math.atan2(e.y,Math.sqrt(e.x*e.x+e.z*e.z))]}function S_(e){let t=Math.round(e/2/Math.PI);return e-2*Math.PI*t}var C_=new H(0,0,1),w_=new H,T_=new H,E_=new H,D_=new V,O_=new V,k_=new V,A_=new V,j_=new Pi,M_=class e{constructor(e,t){this.offsetFromHeadBone=new H,this.autoUpdate=!0,this.faceFront=new H(0,0,1),this.humanoid=e,this.applier=t,this._yaw=0,this._pitch=0,this._needsUpdate=!0,this._restHeadWorldQuaternion=this.getLookAtWorldQuaternion(new V)}get yaw(){return this._yaw}set yaw(e){this._yaw=e,this._needsUpdate=!0}get pitch(){return this._pitch}set pitch(e){this._pitch=e,this._needsUpdate=!0}get euler(){return console.warn(`VRMLookAt: euler is deprecated. use getEuler() instead.`),this.getEuler(new Pi)}getEuler(e){return e.set(ni.DEG2RAD*this._pitch,ni.DEG2RAD*this._yaw,0,`YXZ`)}copy(e){if(this.humanoid!==e.humanoid)throw Error(`VRMLookAt: humanoid must be same in order to copy`);return this.offsetFromHeadBone.copy(e.offsetFromHeadBone),this.applier=e.applier,this.autoUpdate=e.autoUpdate,this.target=e.target,this.faceFront.copy(e.faceFront),this}clone(){return new e(this.humanoid,this.applier).copy(this)}reset(){this._yaw=0,this._pitch=0,this._needsUpdate=!0}getLookAtWorldPosition(e){let t=this.humanoid.getRawBoneNode(`head`);return e.copy(this.offsetFromHeadBone).applyMatrix4(t.matrixWorld)}getLookAtWorldQuaternion(e){return b_(this.humanoid.getRawBoneNode(`head`),e)}getFaceFrontQuaternion(e){if(this.faceFront.distanceToSquared(C_)<.01)return e.copy(this._restHeadWorldQuaternion).invert();let[t,n]=x_(this.faceFront);return j_.set(0,.5*Math.PI+t,n,`YZX`),e.setFromEuler(j_).premultiply(A_.copy(this._restHeadWorldQuaternion).invert())}getLookAtWorldDirection(e){return this.getLookAtWorldQuaternion(O_),this.getFaceFrontQuaternion(k_),e.copy(C_).applyQuaternion(O_).applyQuaternion(k_).applyEuler(this.getEuler(j_))}lookAt(e){let t=D_.copy(this._restHeadWorldQuaternion).multiply(Yg(this.getLookAtWorldQuaternion(O_))),n=this.getLookAtWorldPosition(T_),r=E_.copy(e).sub(n).applyQuaternion(t).normalize(),[i,a]=x_(this.faceFront),[o,s]=x_(r),c=S_(o-i),l=S_(a-s);this._yaw=ni.RAD2DEG*c,this._pitch=ni.RAD2DEG*l,this._needsUpdate=!0}update(e){this.target!=null&&this.autoUpdate&&this.lookAt(this.target.getWorldPosition(w_)),this._needsUpdate&&(this._needsUpdate=!1,this.applier.applyYawPitch(this._yaw,this._pitch))}};M_.EULER_ORDER=`YXZ`;var N_=M_,P_=new H(0,0,1),F_=new V,I_=new V,L_=new Pi(0,0,0,`YXZ`),R_=class{constructor(e,t,n,r,i){this.humanoid=e,this.rangeMapHorizontalInner=t,this.rangeMapHorizontalOuter=n,this.rangeMapVerticalDown=r,this.rangeMapVerticalUp=i,this.faceFront=new H(0,0,1),this._restQuatLeftEye=new V,this._restQuatRightEye=new V,this._restLeftEyeParentWorldQuat=new V,this._restRightEyeParentWorldQuat=new V;let a=this.humanoid.getRawBoneNode(`leftEye`),o=this.humanoid.getRawBoneNode(`rightEye`);a&&(this._restQuatLeftEye.copy(a.quaternion),b_(a.parent,this._restLeftEyeParentWorldQuat)),o&&(this._restQuatRightEye.copy(o.quaternion),b_(o.parent,this._restRightEyeParentWorldQuat))}applyYawPitch(e,t){let n=this.humanoid.getRawBoneNode(`leftEye`),r=this.humanoid.getRawBoneNode(`rightEye`),i=this.humanoid.getNormalizedBoneNode(`leftEye`),a=this.humanoid.getNormalizedBoneNode(`rightEye`);n&&(t<0?L_.x=-ni.DEG2RAD*this.rangeMapVerticalDown.map(-t):L_.x=ni.DEG2RAD*this.rangeMapVerticalUp.map(t),e<0?L_.y=-ni.DEG2RAD*this.rangeMapHorizontalInner.map(-e):L_.y=ni.DEG2RAD*this.rangeMapHorizontalOuter.map(e),F_.setFromEuler(L_),this._getWorldFaceFrontQuat(I_),i.quaternion.copy(I_).multiply(F_).multiply(I_.invert()),F_.copy(this._restLeftEyeParentWorldQuat),n.quaternion.copy(i.quaternion).multiply(F_).premultiply(F_.invert()).multiply(this._restQuatLeftEye)),r&&(t<0?L_.x=-ni.DEG2RAD*this.rangeMapVerticalDown.map(-t):L_.x=ni.DEG2RAD*this.rangeMapVerticalUp.map(t),e<0?L_.y=-ni.DEG2RAD*this.rangeMapHorizontalOuter.map(-e):L_.y=ni.DEG2RAD*this.rangeMapHorizontalInner.map(e),F_.setFromEuler(L_),this._getWorldFaceFrontQuat(I_),a.quaternion.copy(I_).multiply(F_).multiply(I_.invert()),F_.copy(this._restRightEyeParentWorldQuat),r.quaternion.copy(a.quaternion).multiply(F_).premultiply(F_.invert()).multiply(this._restQuatRightEye))}lookAt(e){console.warn(`VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.`);let t=ni.RAD2DEG*e.y,n=ni.RAD2DEG*e.x;this.applyYawPitch(t,n)}_getWorldFaceFrontQuat(e){if(this.faceFront.distanceToSquared(P_)<.01)return e.identity();let[t,n]=x_(this.faceFront);return L_.set(0,.5*Math.PI+t,n,`YZX`),e.setFromEuler(L_)}};R_.type=`bone`;var z_=class{constructor(e,t,n,r,i){this.expressions=e,this.rangeMapHorizontalInner=t,this.rangeMapHorizontalOuter=n,this.rangeMapVerticalDown=r,this.rangeMapVerticalUp=i}applyYawPitch(e,t){t<0?(this.expressions.setValue(`lookDown`,0),this.expressions.setValue(`lookUp`,this.rangeMapVerticalUp.map(-t))):(this.expressions.setValue(`lookUp`,0),this.expressions.setValue(`lookDown`,this.rangeMapVerticalDown.map(t))),e<0?(this.expressions.setValue(`lookLeft`,0),this.expressions.setValue(`lookRight`,this.rangeMapHorizontalOuter.map(-e))):(this.expressions.setValue(`lookRight`,0),this.expressions.setValue(`lookLeft`,this.rangeMapHorizontalOuter.map(e)))}lookAt(e){console.warn(`VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.`);let t=ni.RAD2DEG*e.y,n=ni.RAD2DEG*e.x;this.applyYawPitch(t,n)}};z_.type=`expression`;var B_=class{constructor(e,t){this.inputMaxValue=e,this.outputScale=t}map(e){return this.outputScale*Tg(e/this.inputMaxValue)}},V_=new Set([`1.0`,`1.0-beta`]),H_=.01,U_=class{get name(){return`VRMLookAtLoaderPlugin`}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot}afterRoot(e){return yg(this,null,function*(){let t=e.userData.vrmHumanoid;if(t===null)return;if(t===void 0)throw Error(`VRMLookAtLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first`);let n=e.userData.vrmExpressionManager;if(n!==null){if(n===void 0)throw Error(`VRMLookAtLoaderPlugin: vrmExpressionManager is undefined. VRMExpressionLoaderPlugin have to be used first`);e.userData.vrmLookAt=yield this._import(e,t,n)}})}_import(e,t,n){return yg(this,null,function*(){return t==null||n==null?null:(yield this._v1Import(e,t,n))||(yield this._v0Import(e,t,n))||null})}_v1Import(e,t,n){return yg(this,null,function*(){let e=this.parser.json;if(e.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let r=e.extensions?.VRMC_vrm;if(!r)return null;let i=r.specVersion;if(!V_.has(i))return console.warn(`VRMLookAtLoaderPlugin: Unknown VRMC_vrm specVersion "${i}"`),null;let a=r.lookAt;if(!a)return null;let o=a.type===`expression`?1:10,s=this._v1ImportRangeMap(a.rangeMapHorizontalInner,o),c=this._v1ImportRangeMap(a.rangeMapHorizontalOuter,o),l=this._v1ImportRangeMap(a.rangeMapVerticalDown,o),u=this._v1ImportRangeMap(a.rangeMapVerticalUp,o),d;d=a.type===`expression`?new z_(n,s,c,l,u):new R_(t,s,c,l,u);let f=this._importLookAt(t,d);return f.offsetFromHeadBone.fromArray(a.offsetFromHeadBone??[0,.06,0]),f})}_v1ImportRangeMap(e,t){let n=e?.inputMaxValue??90,r=e?.outputScale??t;return n<H_&&(console.warn(`VRMLookAtLoaderPlugin: inputMaxValue of a range map is too small. Consider reviewing the range map!`),n=H_),new B_(n,r)}_v0Import(e,t,n){return yg(this,null,function*(){let e=this.parser.json.extensions?.VRM;if(!e)return null;let r=e.firstPerson;if(!r)return null;let i=r.lookAtTypeName===`BlendShape`?1:10,a=this._v0ImportDegreeMap(r.lookAtHorizontalInner,i),o=this._v0ImportDegreeMap(r.lookAtHorizontalOuter,i),s=this._v0ImportDegreeMap(r.lookAtVerticalDown,i),c=this._v0ImportDegreeMap(r.lookAtVerticalUp,i),l;l=r.lookAtTypeName===`BlendShape`?new z_(n,a,o,s,c):new R_(t,a,o,s,c);let u=this._importLookAt(t,l);return r.firstPersonBoneOffset?u.offsetFromHeadBone.set(r.firstPersonBoneOffset.x??0,r.firstPersonBoneOffset.y??.06,-(r.firstPersonBoneOffset.z??0)):u.offsetFromHeadBone.set(0,.06,0),u.faceFront.set(0,0,-1),l instanceof R_&&l.faceFront.set(0,0,-1),u})}_v0ImportDegreeMap(e,t){let n=e?.curve;JSON.stringify(n)!==`[0,0,0,1,1,1,1,0]`&&console.warn(`Curves of LookAtDegreeMap defined in VRM 0.0 are not supported`);let r=e?.xRange??90,i=e?.yRange??t;return r<H_&&(console.warn(`VRMLookAtLoaderPlugin: xRange of a degree map is too small. Consider reviewing the degree map!`),r=H_),new B_(r,i)}_importLookAt(e,t){let n=new N_(e,t);if(this.helperRoot){let e=new __(n);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return n}};function W_(e,t){return typeof e!=`string`||e===``?``:(/^https?:\/\//i.test(t)&&/^\//.test(e)&&(t=t.replace(/(^https?:\/\/[^/]+).*/i,`$1`)),/^(https?:)?\/\//i.test(e)||/^data:.*,.*$/i.test(e)||/^blob:.*$/i.test(e)?e:t+e)}var G_=new Set([`1.0`,`1.0-beta`]),K_=class{get name(){return`VRMMetaLoaderPlugin`}constructor(e,t){this.parser=e,this.needThumbnailImage=t?.needThumbnailImage??!1,this.acceptLicenseUrls=t?.acceptLicenseUrls??[`https://vrm.dev/licenses/1.0/`],this.acceptV0Meta=t?.acceptV0Meta??!0}afterRoot(e){return yg(this,null,function*(){e.userData.vrmMeta=yield this._import(e)})}_import(e){return yg(this,null,function*(){return(yield this._v1Import(e))??(yield this._v0Import(e))??null})}_v1Import(e){return yg(this,null,function*(){let e=this.parser.json;if(e.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let t=e.extensions?.VRMC_vrm;if(t==null)return null;let n=t.specVersion;if(!G_.has(n))return console.warn(`VRMMetaLoaderPlugin: Unknown VRMC_vrm specVersion "${n}"`),null;let r=t.meta;if(!r)return null;let i=r.licenseUrl;if(!new Set(this.acceptLicenseUrls).has(i))throw Error(`VRMMetaLoaderPlugin: The license url "${i}" is not accepted`);let a;return this.needThumbnailImage&&r.thumbnailImage!=null&&(a=(yield this._extractGLTFImage(r.thumbnailImage))??void 0),{metaVersion:`1`,name:r.name,version:r.version,authors:r.authors,copyrightInformation:r.copyrightInformation,contactInformation:r.contactInformation,references:r.references,thirdPartyLicenses:r.thirdPartyLicenses,thumbnailImage:a,licenseUrl:r.licenseUrl,avatarPermission:r.avatarPermission,allowExcessivelyViolentUsage:r.allowExcessivelyViolentUsage,allowExcessivelySexualUsage:r.allowExcessivelySexualUsage,commercialUsage:r.commercialUsage,allowPoliticalOrReligiousUsage:r.allowPoliticalOrReligiousUsage,allowAntisocialOrHateUsage:r.allowAntisocialOrHateUsage,creditNotation:r.creditNotation,allowRedistribution:r.allowRedistribution,modification:r.modification,otherLicenseUrl:r.otherLicenseUrl}})}_v0Import(e){return yg(this,null,function*(){let e=this.parser.json.extensions?.VRM;if(!e)return null;let t=e.meta;if(!t)return null;if(!this.acceptV0Meta)throw Error(`VRMMetaLoaderPlugin: Attempted to load VRM0.0 meta but acceptV0Meta is false`);let n;return this.needThumbnailImage&&t.texture!=null&&t.texture!==-1&&(n=yield this.parser.getDependency(`texture`,t.texture)),{metaVersion:`0`,allowedUserName:t.allowedUserName,author:t.author,commercialUssageName:t.commercialUssageName,contactInformation:t.contactInformation,licenseName:t.licenseName,otherLicenseUrl:t.otherLicenseUrl,otherPermissionUrl:t.otherPermissionUrl,reference:t.reference,sexualUssageName:t.sexualUssageName,texture:n??void 0,title:t.title,version:t.version,violentUssageName:t.violentUssageName}})}_extractGLTFImage(e){return yg(this,null,function*(){let t=this.parser.json.images?.[e];if(t==null)return console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${e}] of glTF as a thumbnail but the image doesn't exist`),null;let n=t.uri;if(t.bufferView!=null){let e=yield this.parser.getDependency(`bufferView`,t.bufferView),r=new Blob([e],{type:t.mimeType});n=URL.createObjectURL(r)}return n==null?(console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${e}] of glTF as a thumbnail but the image couldn't load properly`),null):yield new Pc().loadAsync(W_(n,this.parser.options.path)).catch(e=>(console.error(e),console.warn(`VRMMetaLoaderPlugin: Failed to load a thumbnail image`),null))})}},q_=class{constructor(e){this.scene=e.scene,this.meta=e.meta,this.humanoid=e.humanoid,this.expressionManager=e.expressionManager,this.firstPerson=e.firstPerson,this.lookAt=e.lookAt}update(e){this.humanoid.update(),this.lookAt&&this.lookAt.update(e),this.expressionManager&&this.expressionManager.update()}},J_=class extends q_{constructor(e){super(e),this.materials=e.materials,this.springBoneManager=e.springBoneManager,this.nodeConstraintManager=e.nodeConstraintManager}update(e){super.update(e),this.nodeConstraintManager&&this.nodeConstraintManager.update(),this.springBoneManager&&this.springBoneManager.update(e),this.materials&&this.materials.forEach(t=>{t.update&&t.update(e)})}},Y_=Object.defineProperty,X_=Object.getOwnPropertySymbols,Z_=Object.prototype.hasOwnProperty,Q_=Object.prototype.propertyIsEnumerable,$_=(e,t,n)=>t in e?Y_(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,ev=(e,t)=>{for(var n in t||={})Z_.call(t,n)&&$_(e,n,t[n]);if(X_)for(var n of X_(t))Q_.call(t,n)&&$_(e,n,t[n]);return e},tv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())});function nv(e,t){e.colorSpace=t}var rv=class{get pending(){return Promise.all(this._pendings)}constructor(e,t){this._parser=e,this._materialParams=t,this._pendings=[]}assignPrimitive(e,t){t!=null&&(this._materialParams[e]=t)}assignColor(e,t,n){if(t!=null){let r=new G().fromArray(t);n&&r.convertSRGBToLinear(),this._materialParams[e]=r}}assignTexture(e,t,n){return tv(this,null,function*(){let r=tv(this,null,function*(){if(t!=null){let r=yield this._parser.assignTexture(this._materialParams,e,t);if(r==null){console.warn(`GLTFMToonMaterialParamsAssignHelper: Failed to load texture. The rendering result may be wrong`);return}n&&nv(r,`srgb`)}});return this._pendings.push(r),r})}assignTextureByIndex(e,t,n){return tv(this,null,function*(){return this.assignTexture(e,t==null?void 0:{index:t},n)})}},iv=`// #define PHONG
|
|
5684
|
+
`;function Sp(e,t,n,r,i=0){return t>=r.centerY?!1:Math.abs(e-r.centerX)<=r.halfW+i&&Math.abs(n-r.centerZ)<=r.halfD+i}var Cp=22,wp={enabled:!0,strength:.6},Tp={enabled:!0,color:`#cdeeff`,intensity:.55,scale:.32,speed:1};function Ep(e,t){if(e===!1)return{enabled:!1,color:kp(t),visibility:Cp,caustics:Tp,rays:{...wp,enabled:!1}};let n=e&&typeof e==`object`?e:{};return{enabled:!0,color:n.color??kp(t),visibility:n.visibility??Cp,caustics:Op(n.caustics),rays:Dp(n.rays)}}function Dp(e){return e===!1?{...wp,enabled:!1}:typeof e==`number`?{enabled:e>0,strength:e}:{...wp}}function Op(e){if(e===!1)return{...Tp,enabled:!1};let t=e&&typeof e==`object`?e:{};return{enabled:!0,color:typeof t.color==`string`?t.color:Tp.color,intensity:typeof t.intensity==`number`?t.intensity:Tp.intensity,scale:typeof t.scale==`number`?t.scale:Tp.scale,speed:typeof t.speed==`number`?t.speed:Tp.speed}}function kp(e){let{r:t,g:n,b:r}=Ap(e),i=(e,t,n)=>Math.round(e*(1-n)+t*n);return jp(Math.round(i(t,6,.45)*.7),Math.round(i(n,40,.4)*.78),Math.round(i(r,70,.35)*.82))}function Ap(e){let t=e.replace(`#`,``),n=t.length===3?t.split(``).map(e=>e+e).join(``):t;return{r:Number.parseInt(n.slice(0,2),16)||0,g:Number.parseInt(n.slice(2,4),16)||0,b:Number.parseInt(n.slice(4,6),16)||0}}function jp(e,t,n){let r=e=>Math.max(0,Math.min(255,e)).toString(16).padStart(2,`0`);return`#${r(e)}${r(t)}${r(n)}`}var Mp={frequency:6.7,persistence:.3,lacunarity:2.18,iterations:9,speed:.5},Np=.525,Pp=.08,Fp={freqX:.7,freqZ:.5,cross:.6};function Ip(e,t){return e-Math.floor(e/t)*t}function Lp(e){return e-Math.floor(e)}function Rp(e){return Ip((e*34+1)*e,289)}var zp=.211324865405187,Bp=.366025403784439,Vp=-.577350269189626,Hp=.024390243902439;function Up(e,t){let n=Math.floor(e+(e+t)*Bp),r=Math.floor(t+(e+t)*Bp),i=e-n+(n+r)*zp,a=t-r+(n+r)*zp,o=+(i>a),s=i>a?0:1,c=i+zp-o,l=a+zp-s,u=i+Vp,d=a+Vp;n=Ip(n,289),r=Ip(r,289);let f=Rp(Rp(r)+n),p=Rp(Rp(r+s)+n+o),m=Rp(Rp(r+1)+n+1),h=Math.max(.5-(i*i+a*a),0),g=Math.max(.5-(c*c+l*l),0),_=Math.max(.5-(u*u+d*d),0);h*=h,h*=h,g*=g,g*=g,_*=_,_*=_;let v=2*Lp(f*Hp)-1,y=2*Lp(p*Hp)-1,b=2*Lp(m*Hp)-1,x=Math.abs(v)-.5,S=Math.abs(y)-.5,C=Math.abs(b)-.5,w=v-Math.floor(v+.5),T=y-Math.floor(y+.5),E=b-Math.floor(b+.5);h*=1.79284291400159-.85373472095314*(w*w+x*x),g*=1.79284291400159-.85373472095314*(T*T+S*S),_*=1.79284291400159-.85373472095314*(E*E+C*C);let D=w*i+x*a,O=T*c+S*l,k=E*u+C*d;return 130*(h*D+g*O+_*k)}function Wp(e,t,n,r){let i=Math.max(r.scaleNorm,1e-6),a=e/i,o=t/i,s=0,c=1,l=r.frequency,u=n*r.speed;for(let e=0;e<r.iterations;e++)s+=c*Up(a*l+u,o*l+u),c*=r.persistence,l*=r.lacunarity;return s*r.amplitude}function Gp(e,t,n,r){return r*(Math.sin(e*Fp.freqX+n)+Fp.cross*Math.sin(t*Fp.freqZ+n*1.3))}function Kp(e,t){let n=e.shape;if(n!==void 0){if(n===`box`){let n=e.size;if(!Array.isArray(n)||n.length!==3||n.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${t}': box needs "size": [x, y, z].`);return}if(n===`sphere`){if(typeof e.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': sphere needs "radius".`);return}if(n===`capsule`){if(typeof e.radius!=`number`||typeof e.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': capsule needs "radius" and "height".`);return}if(n===`trimesh`){let n=e.vertices,r=e.indices;if(!Array.isArray(n)||n.length%3!=0||!Array.isArray(r)||r.length%3!=0)throw new y(`BAD_FORMAT`,`Collider on '${t}': trimesh needs "vertices" (flat xyz floats) and "indices" (triangle triplets).`);return}if(n!==`heightfield`)throw new y(`BAD_FORMAT`,`Collider on '${t}': "shape" must be 'box', 'sphere', 'capsule', 'trimesh', or 'heightfield', got ${JSON.stringify(n)}.`)}}var qp=class extends Pe{static typeName=`Node3D`;static props={position:{default:[0,0,0]},rotation:{default:[0,0,0]},static:{default:!1},scale:{default:[1,1,1]},visible:{default:!0},renderOrder:{default:0},orderGroup:{default:`default`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]}};position=[0,0,0];rotation=[0,0,0];static=!1;scale=[1,1,1];visible=!0;renderOrder=0;orderGroup=`default`;get effectiveRenderOrder(){return nt(this.orderGroup,this.renderOrder)}_object3D=null;_interpPrev=null;_interpCurr=null;_ensureObject3D(){return this._object3D||(this._object3D=this._createObject3D(),this._object3D.userData.incantoNode=this),this._object3D}_createObject3D(){return new Zi}_syncObject3D(e=1){let t=this._ensureObject3D(),n=this._interpPrev,r=this._interpCurr;n&&r?t.position.set((n[0]??0)+((r[0]??0)-(n[0]??0))*e,(n[1]??0)+((r[1]??0)-(n[1]??0))*e,(n[2]??0)+((r[2]??0)-(n[2]??0))*e):t.position.set(this.position[0]??0,this.position[1]??0,this.position[2]??0),t.rotation.set(ni.degToRad(this.rotation[0]??0),ni.degToRad(this.rotation[1]??0),ni.degToRad(this.rotation[2]??0)),t.scale.set(this.scale[0]??1,this.scale[1]??1,this.scale[2]??1),t.visible=this.visible,t.renderOrder=this.effectiveRenderOrder}free(){super.free(),this._object3D?.removeFromParent(),this._object3D=null,this._interpPrev=null,this._interpCurr=null}},Jp=class extends qp{static props={collider:{default:{}}};static signals=[`triggerEnter`,`triggerExit`];_collider={};_colliderChanged=!1;get collider(){return this._collider}set collider(e){this._collider=e,this._colliderChanged=!0}static validateJson(e){let t=e;if(Kp(t.collider,e.name),t.collider.shape===`heightfield`&&!(t instanceof Yp))throw new y(`BAD_FORMAT`,`Collider on '${e.name}': heightfield is static terrain — put it on a StaticBody3D (with a Terrain3D child), not a ${t.constructor.typeName}.`,{prop:`collider`})}_physics=null},Yp=class extends Jp{static typeName=`StaticBody3D`},Xp=class extends Jp{static typeName=`Area3D`},Zp=class extends Jp{static typeName=`RigidBody3D`;static props={mass:{default:1},gravityScale:{default:1},fixedRotation:{default:!1},friction:{default:.5},restitution:{default:0},linearVelocity:{default:[0,0,0]}};mass=1;gravityScale=1;fixedRotation=!1;friction=.5;restitution=0;linearVelocity=[0,0,0];_physics3d=null;applyImpulse(e){this._physics3d?.applyImpulse(this,e)}},Qp=class extends Jp{static typeName=`CharacterBody3D`;static props={velocity:{default:[0,0,0]},snapToGround:{default:!0},slopeLimitDeg:{default:45}};velocity=[0,0,0];snapToGround=!0;slopeLimitDeg=45;_grounded=!1;moveAndSlide(){if(!this._physics)throw new y(`TREE_VIOLATION`,this.collider.shape===void 0?`CharacterBody3D '${this.name}' has no collider — set a collider prop (physics skips collider-less bodies).`:`CharacterBody3D '${this.name}' has no physics world — await enablePhysics3D(engine) first.`);this._physics.moveAndSlide(this)}isOnFloor(){return this._grounded}},$p=class extends qp{static typeName=`WaterCutout3D`;static props={size:{default:[2,1,1]},enabled:{default:!0}};size=[2,1,1];enabled=!0;static validateJson(e){let t=e;if(!Array.isArray(t.size)||t.size.length!==3||t.size.some(e=>!(e>0)))throw new y(`BAD_FORMAT`,`WaterCutout3D '${e.name}' size must be three positive meters [x, y, z], got ${JSON.stringify(t.size)}.`,{prop:`size`})}onReady(){if(!this.parent?.parent)throw new y(`BAD_FORMAT`,`WaterCutout3D '${this.name}' must be a CHILD of the object that holds the water back (a hull, a diving bell, a dock's well) — it re-draws that object to keep water out of it, so at the scene root it has nothing to stand in for.`,{prop:`parent`})}},em=[`fancy`,`simple`],tm=[`trough`,`surface`,`peak`],nm=[`custom`,`ocean`,`pool`,`lake`,`pond`],rm={ocean:{waveHeight:.045,swell:.34,swellWavelength:52,whitecaps:.15,absorption:.17,opacity:.85,detailStrength:.17,sunIntensity:.85,colors:{trough:`#175360`,surface:`#2f8792`,peak:`#9bd8d2`},color:`#2f8792`,causticsAbove:.3,shoreWaves:.7,reflectionInterval:400,_look:{fresnelScale:1.15,reflectivityMax:.93,foamRangeScale:.35,foamIntensity:.55}},pool:{waveHeight:.006,swell:0,whitecaps:0,absorption:.3,opacity:.5,detailStrength:.16,sunIntensity:1.25,colors:{trough:`#1e8dbe`,surface:`#3fb6dc`,peak:`#bdeef7`},color:`#3fb6dc`,causticsAbove:1,reflectionInterval:600,_look:{fresnelScale:.85,reflectivityMax:.5,edgeFade:!1}},lake:{waveHeight:.028,swell:.14,swellWavelength:24,whitecaps:0,absorption:.5,opacity:.88,detailStrength:.3,colors:{trough:`#12343a`,surface:`#25565c`,peak:`#7fb2ab`},color:`#25565c`,causticsAbove:.15,reflectionInterval:300,_look:{fresnelScale:1.25,reflectivityMax:.78}},pond:{waveHeight:.012,swell:0,whitecaps:0,absorption:.55,opacity:.88,detailStrength:.2,sunIntensity:.9,colors:{trough:`#24402a`,surface:`#436b4d`,peak:`#8fae8e`},color:`#436b4d`,causticsAbove:0,reflectionInterval:800,_look:{fresnelScale:1.1,reflectivityMax:.68,edgeFade:!1}}},im={trough:`#135a72`,surface:`#2a86a0`,peak:`#a5ddd6`},am={peakThreshold:.08,peakTransition:.05,troughThreshold:-.01,troughTransition:.15,fresnelScale:1,fresnelPower:5},om={color:`#dcebe8`,intensity:.32,rangeMin:.45,rangeMax:1.4,scale:.35,edgeColor:`#ffffff`,edgeIntensity:.6,edgeWidth:.5};function sm(e,t){return Math.min(om.rangeMax,Math.max(om.rangeMin,Math.min(e,t)*.012))}var cm=128,lm=Np/Pp,um=256,dm=2e3,fm=3,pm=640,mm=.06,hm=1024,gm=.02,_m=1.5,vm=24,ym=160,bm=32,xm=.05,Sm=.08,Cm=.02,wm=.18,Tm=.04,Em=1.4,Dm=.04,Om=.45,km=.08,Am=.4,jm=.22,Mm=.09,Nm=.85,Pm=class e extends qp{static typeName=`Water3D`;static signals=[`entered`,`exited`];static props={size:{default:[40,40]},color:{default:`#2a6fbe`},opacity:{default:.8},renderOrder:{default:1},waveHeight:{default:.04},waveSpeed:{default:1},quality:{default:`fancy`,options:em},colors:{default:{}},reflection:{default:!0},reflectionInterval:{default:1e3},mirror:{default:!1},mirrorInterval:{default:33},swellSteepness:{default:.35},foam:{default:!0},interaction:{default:!0},splash:{default:!0},sunDirection:{default:[.5,.8,.3]},sunColor:{default:`#fff5d6`},sunIntensity:{default:1},detailStrength:{default:.26},absorption:{default:.15},refraction:{default:!0},underwater:{default:!0},swell:{default:0},swellDirectionDeg:{default:0},swellWavelength:{default:30},whitecaps:{default:0},preset:{default:`custom`,options:nm},causticsAbove:{default:0},shoreWaves:{default:0}};size=[40,40];color=`#2a6fbe`;opacity=.8;renderOrder=1;waveHeight=.04;waveSpeed=1;quality=`fancy`;colors={};reflection=!0;mirror=!1;mirrorInterval=33;reflectionInterval=1e3;foam=!0;interaction=!0;splash=!0;sunDirection=[.5,.8,.3];sunColor=`#fff5d6`;sunIntensity=1;detailStrength=.26;absorption=.15;refraction=!0;underwater=!0;swell=0;swellDirectionDeg=0;swellWavelength=30;swellSteepness=.35;whitecaps=0;preset=`custom`;causticsAbove=0;shoreWaves=0;rp(t){let n=rm[this.preset],r=this;if(n&&t in n){let i=e.props[t]?.default,a=r[t];if(typeof a==`object`&&a?JSON.stringify(a)===JSON.stringify(i):a===i)return n[t]}return r[t]}presetLook(){let e=rm[this.preset]?._look;return{fresnelScale:e?.fresnelScale??am.fresnelScale,reflectivityMax:e?.reflectivityMax??.6,edgeFade:e?.edgeFade??!0,foamRangeScale:e?.foamRangeScale??1,foamIntensity:e?.foamIntensity??om.intensity}}static validateJson(e){let t=e;if(!((t.size[0]??0)>0)||!((t.size[1]??0)>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' size must be positive [width, depth] meters, got ${JSON.stringify(t.size)}.`,{prop:`size`});if(!em.includes(t.quality))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' quality must be one of [${em.join(`, `)}], got '${t.quality}'.`,{prop:`quality`,validOptions:em});for(let[n,r]of Object.entries(t.colors)){if(!tm.includes(n))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' colors has unknown key '${n}'. Valid keys: [${tm.join(`, `)}].`,{prop:`colors`,validOptions:tm});if(typeof r!=`string`)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' colors.${n} must be a hex color string, got ${JSON.stringify(r)}.`,{prop:`colors`})}if(!(t.reflectionInterval>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' reflectionInterval must be > 0 ms, got ${t.reflectionInterval}.`,{prop:`reflectionInterval`});let n=t.sunDirection;if(!Array.isArray(n)||n.length!==3||!n.every(e=>Number.isFinite(e))||Math.hypot(n[0]??0,n[1]??0,n[2]??0)===0)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' sunDirection must be a non-zero [x, y, z] vector, got ${JSON.stringify(n)}.`,{prop:`sunDirection`});if(!(t.sunIntensity>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' sunIntensity must be >= 0, got ${t.sunIntensity}.`,{prop:`sunIntensity`});if(!(t.detailStrength>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' detailStrength must be >= 0, got ${t.detailStrength}.`,{prop:`detailStrength`});if(!(t.absorption>=0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' absorption must be >= 0 (per-meter Beer's-law constant), got ${t.absorption}.`,{prop:`absorption`});if(!(t.swell>=0)||!Number.isFinite(t.swell))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' swell must be >= 0 meters (0 = off), got ${JSON.stringify(t.swell)}.`,{prop:`swell`});if(!(t.swellWavelength>=2))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' swellWavelength must be >= 2 meters, got ${JSON.stringify(t.swellWavelength)}.`,{prop:`swellWavelength`});if(!(t.whitecaps>=0)||!(t.whitecaps<=1))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' whitecaps must be in [0, 1], got ${JSON.stringify(t.whitecaps)}.`,{prop:`whitecaps`});if(!nm.includes(t.preset))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' preset must be one of [${nm.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:nm});if(!(t.shoreWaves>=0)||!(t.shoreWaves<=1))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' shoreWaves must be in [0, 1] (0 = off), got ${JSON.stringify(t.shoreWaves)}.`,{prop:`shoreWaves`});if(!(t.causticsAbove>=0)||!(t.causticsAbove<=3))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' causticsAbove must be in [0, 3] (0 = off), got ${JSON.stringify(t.causticsAbove)}.`,{prop:`causticsAbove`});let r=t.underwater;if(typeof r!=`boolean`){if(typeof r!=`object`||!r||Array.isArray(r))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater must be true, false or an object ({ color?, visibility? }), got ${JSON.stringify(r)}.`,{prop:`underwater`});let t=r;if(t.color!==void 0&&typeof t.color!=`string`)throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater.color must be a hex color string, got ${JSON.stringify(t.color)}.`,{prop:`underwater`});if(t.visibility!==void 0&&!(t.visibility>0))throw new y(`BAD_FORMAT`,`Water3D '${e.name}' underwater.visibility must be > 0 meters, got ${JSON.stringify(t.visibility)}.`,{prop:`underwater`})}}time=0;surfaceKey=``;_ripples=[];inWater=new Set;bobTimers=new Map;wadeAnchors=new Map;_scratchA={x:0,y:0,z:0};_scratchB={x:0,y:0,z:0};_bodies=[];_cutouts=[];_maskMeshes=[];_maskSaved=[];_passHidden=[];cubeTarget=null;cubeCamera=null;reflectionNear=0;lastReflectionAt=0;scenePassTarget=null;mirrorTarget=null;mirrorCamera=new Yc;mirrorMatrix=new W;lastMirrorAt=0;_createObject3D(){return new jo}update(e){this.time+=e*this.waveSpeed,sp(this._ripples,e),this.interaction&&this.stepInteraction(e)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();this.rebuildSurfaceIfNeeded(e),this.quality===`simple`?this.syncSimple(e):this.syncFancy(e)}_onRender3D(e){let t=this._ensureObject3D(),n=t.material;if(e.camera.updateWorldMatrix(!0,!1),e.camera.getWorldPosition(Qm),this.underwaterAt(Qm.x,Qm.y,Qm.z)){if(n.isShaderMaterial){let e=n.uniforms;e.uUseSceneDepth&&(e.uUseSceneDepth.value=0),e.uUseRefraction&&(e.uUseRefraction.value=0),e.uUseMirror&&(e.uUseMirror.value=0),e.uCameraSubmerged&&(e.uCameraSubmerged.value=1)}return}if(this.quality!==`fancy`||!n.isShaderMaterial)return;let r=Math.hypot((this.size[0]??1)/2,(this.size[1]??1)/2);if(!np(e.camera,Um(this),r+1))return;let i=n.uniforms;i.uCameraSubmerged&&(i.uCameraSubmerged.value=0);let a=Date.now();if(this.reflection){this.cubeTarget||=new fu(um,{generateMipmaps:!0,minFilter:Wt,type:Qt});let n=Math.max((this.size[0]??1)/2,(this.size[1]??1)/2);(!this.cubeCamera||this.reflectionNear!==n)&&(this.reflectionNear=n,this.cubeCamera=new ll(n,1e3,this.cubeTarget),this.lastReflectionAt=0);let r=this.mirror?Math.max(this.rp(`reflectionInterval`),dm):this.rp(`reflectionInterval`);if(this.lastReflectionAt===0||a-this.lastReflectionAt>=r){this.lastReflectionAt=a;let n=Um(this),r=this.cubeCamera;r.position.set(n.x,n.y+.1,n.z);let i=t.visible;t.visible=!1,r.update(e.gl,e.scene),t.visible=i}i.uEnvironmentMap&&i.uUseEnvironmentMap&&(i.uEnvironmentMap.value=this.cubeTarget.texture,i.uUseEnvironmentMap.value=1)}if(this.mirror&&i.uMirrorMap&&i.uMirrorMatrix&&i.uUseMirror){e.gl.getDrawingBufferSize(Zm);let n=Math.max(1,Math.min(Math.round(Zm.x/fm),pm)),r=Math.max(1,Math.min(Math.round(Zm.y/fm),pm));this.mirrorTarget&&(this.mirrorTarget.width!==n||this.mirrorTarget.height!==r)&&(this.mirrorTarget.dispose(),this.mirrorTarget=null),this.mirrorTarget||=new Si(n,r,{depthBuffer:!0,stencilBuffer:!1,type:Qt});let o=Um(this).y,s=e.camera;s.getWorldPosition(eh),s.getWorldQuaternion(rh),th.set(0,0,-1).applyQuaternion(rh).add(eh),nh.set(0,1,0).applyQuaternion(rh),eh.y=2*o-eh.y,th.y=2*o-th.y,nh.y=-nh.y;let c=this.mirrorCamera;if(c.fov=s.fov??50,c.aspect=s.aspect??n/r,c.near=s.near??.1,c.far=s.far??1e3,c.position.copy(eh),c.up.copy(nh),c.lookAt(th),c.updateMatrixWorld(!0),c.updateProjectionMatrix(),this.mirrorMatrix.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),this.mirrorMatrix.multiply(c.projectionMatrix),this.mirrorMatrix.multiply(c.matrixWorldInverse),this.lastMirrorAt===0||a-this.lastMirrorAt>=this.rp(`mirrorInterval`)){this.lastMirrorAt=a;let n=e.gl.getRenderTarget(),r=e.gl.clippingPlanes,i=t.visible;t.visible=!1,ih.constant=-(o-gm),e.gl.clippingPlanes=ah,e.gl.setRenderTarget(this.mirrorTarget),e.gl.clear(!0,!0,!1),mp(e.scene,this._passHidden),e.gl.render(e.scene,c),hp(this._passHidden),e.gl.setRenderTarget(n),e.gl.clippingPlanes=r,t.visible=i}i.uMirrorMap.value=this.mirrorTarget.texture,i.uMirrorMatrix.value.copy(this.mirrorMatrix),i.uUseMirror.value=1}else i.uUseMirror&&(i.uUseMirror.value=0);e.gl.getDrawingBufferSize(Zm);let o=Math.max(1,Math.min(Math.round(Zm.x/2),hm)),s=Math.max(1,Math.min(Math.round(Zm.y/2),hm));if(this.scenePassTarget&&(this.scenePassTarget.width!==o||this.scenePassTarget.height!==s)&&(this.scenePassTarget.depthTexture?.dispose(),this.scenePassTarget.dispose(),this.scenePassTarget=null),!this.scenePassTarget){let e=new Fs(o,s);e.type=Zt,this.scenePassTarget=new Si(o,s,{depthTexture:e,depthBuffer:!0,stencilBuffer:!1,generateMipmaps:!0,minFilter:Wt})}let c=e.gl.getRenderTarget(),l=e.gl.autoClear,u=e.gl.clippingPlanes,d=t.visible;t.visible=!1;let f=Um(this).y;oh.constant=f+gm,e.gl.clippingPlanes=sh,e.gl.setRenderTarget(this.scenePassTarget),e.gl.autoClear=!0,e.gl.clear(!0,!0,!1),e.gl.render(e.scene,e.camera),lh.constant=-(f-gm),e.gl.clippingPlanes=uh;let p=e.scene.overrideMaterial,m=e.scene.background;e.scene.overrideMaterial=dh,e.scene.background=null,e.gl.autoClear=!1,mp(e.scene,this._passHidden),e.gl.render(e.scene,e.camera),hp(this._passHidden),e.scene.overrideMaterial=p,e.scene.background=m,this.renderCutoutMasks(e),e.gl.setRenderTarget(c),e.gl.autoClear=l,e.gl.clippingPlanes=u,t.visible=d,i.uDepthTexture&&i.uSceneColor&&i.uCameraNear&&i.uCameraFar&&i.uUseSceneDepth&&(i.uDepthTexture.value=this.scenePassTarget.depthTexture,(i.uScenePassTexel?.value)?.set(1/o,1/s),i.uSceneColor.value=this.scenePassTarget.texture,i.uCameraNear.value=e.camera.near,i.uCameraFar.value=e.camera.far,i.uUseSceneDepth.value=1,i.uUseRefraction&&(i.uUseRefraction.value=+!!this.refraction),i.uEnableFoam&&(i.uEnableFoam.value=+!!this.foam))}underwaterAt(e,t,n){if(this.underwater===!1)return null;let r=Um(this,this._scratchA);if(!Sp(e,t,n,{centerX:r.x,centerY:r.y,centerZ:r.z,halfW:(this.size[0]??1)/2,halfD:(this.size[1]??1)/2},$m))return null;let i=Ep(this.underwater,this.rp(`color`));return i.enabled?{...i,surfaceY:r.y}:null}free(){let e=this._ensureObject3D();e.geometry?.dispose(),e.material?.dispose?.(),this.cubeTarget?.dispose(),this.cubeTarget=null,this.cubeCamera=null,this.scenePassTarget?.depthTexture?.dispose(),this.scenePassTarget?.dispose(),this.scenePassTarget=null,this.mirrorTarget?.dispose(),this.mirrorTarget=null,super.free()}rebuildSurfaceIfNeeded(e){let t=JSON.stringify([this.size,this.quality]);if(t===this.surfaceKey&&e.geometry.getAttribute(`position`))return;this.surfaceKey=t,e.geometry?.dispose(),e.material?.dispose?.();let n=this.size[0]??1,r=this.size[1]??1;this.quality===`simple`?(e.geometry=Km(n,r,bm),e.material=this.buildLakeMaterial()):(e.geometry=Km(n,r,Math.min(Math.max(Math.round(Math.max(n,r)*_m),vm),ym)),e.material=this.buildFancyMaterial())}buildFancyMaterial(){return new ec({vertexShader:bp,fragmentShader:xp,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uOpacity:{value:this.rp(`opacity`)},uEnvironmentMap:{value:null},uUseEnvironmentMap:{value:0},uMirrorMap:{value:null},uMirrorMatrix:{value:new W},uUseMirror:{value:0},uMirrorDistort:{value:mm},uWavesAmplitude:{value:this.rp(`waveHeight`)*lm},uWavesSpeed:{value:Mp.speed},uWavesFrequency:{value:Mp.frequency},uWavesPersistence:{value:Mp.persistence},uWavesLacunarity:{value:Mp.lacunarity},uWavesIterations:{value:Mp.iterations},uTroughColor:{value:new G(im.trough)},uSurfaceColor:{value:new G(im.surface)},uPeakColor:{value:new G(im.peak)},uPeakThreshold:{value:am.peakThreshold},uPeakTransition:{value:am.peakTransition},uTroughThreshold:{value:am.troughThreshold},uTroughTransition:{value:am.troughTransition},uFresnelScale:{value:am.fresnelScale},uFresnelPower:{value:am.fresnelPower},uScale:{value:new H(1,1,1)},uWaterCenter:{value:new H},uRipples:{value:Array.from({length:8},()=>new bi)},uRippleFoam:{value:Array.from({length:8},()=>0)},uSplashFoam:{value:+!!this.splash},uSunDirection:{value:new H(.5,.8,.3)},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.rp(`sunIntensity`)},uDetailStrength:{value:this.rp(`detailStrength`)},uAbsorption:{value:this.rp(`absorption`)},uUseSceneDepth:{value:0},uUseRefraction:{value:0},uSceneColor:{value:null},uEnableFoam:{value:0},uFoamColor:{value:new G(om.color)},uFoamIntensity:{value:om.intensity},uFoamRange:{value:sm(this.size[0]??1,this.size[1]??1)},uFoamScale:{value:om.scale},uDepthTexture:{value:null},uScenePassTexel:{value:new B(1/512,1/512)},uCameraNear:{value:.1},uCameraFar:{value:1e3},uEdgeColor:{value:new G(om.edgeColor)},uEdgeIntensity:{value:om.edgeIntensity},uEdgeWidth:{value:om.edgeWidth},uSwellAmplitude:{value:this.rp(`swell`)},uSwellDir:{value:new B(0,1)},uSwellWavelength:{value:this.rp(`swellWavelength`)},uSwellSteepness:{value:this.rp(`swellSteepness`)},uWhitecaps:{value:this.rp(`whitecaps`)},uWaveEnvelope:{value:0},uCausticsAbove:{value:this.rp(`causticsAbove`)},uShoreWaves:{value:this.rp(`shoreWaves`)},uReflectivityMax:{value:.6},uCameraSubmerged:{value:0},uEdgeFadeOn:{value:1}},transparent:!0,depthTest:!0,depthWrite:!0,side:2})}buildLakeMaterial(){return new ec({vertexShader:dp,fragmentShader:fp,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uOpacity:{value:this.rp(`opacity`)},uColor:{value:new G(this.rp(`color`))},uSurfaceColor:{value:new G(this.rp(`color`))},uSkyColor:{value:new G(this.rp(`color`))},uSunDirection:{value:new H(.5,.8,.3).normalize()},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.rp(`sunIntensity`)},uDetailStrength:{value:this.rp(`detailStrength`)},uFresnelPower:{value:am.fresnelPower},uScale:{value:new H(1,1,1)},uWaterCenter:{value:new H},uRipples:{value:Array.from({length:8},()=>new bi)},uRippleFoam:{value:Array.from({length:8},()=>0)},uSplashFoam:{value:+!!this.splash},uFoamColor:{value:new G(om.color)}},transparent:!0,depthTest:!0,depthWrite:!1,side:2})}renderCutoutMasks(e){let t=this._cutouts;t.length=0;let n=this;for(;n.parent;)n=n.parent;if(Rm(n,t),t.length===0)return;let r=fh.uniforms,i=this._maskSaved,a=this._maskMeshes,o=e.gl.clippingPlanes;e.gl.clippingPlanes=ch;let s=0;for(let n of t){if(s>=4)break;let t=zm(n);if(!t)continue;n._syncObject3D();let o=n._ensureObject3D();if(o.updateWorldMatrix(!0,!1),o.getWorldPosition(Fm),o.getWorldQuaternion(Im),(r.uCenter?.value)?.copy(Fm),(r.uHalf?.value)?.set((n.size[0]??1)/2,(n.size[1]??1)/2,(n.size[2]??1)/2),Lm.setFromQuaternion(Im,`YXZ`),(r.uYaw?.value)?.set(Math.cos(Lm.y),Math.sin(Lm.y)),a.length=0,i.length=0,Vm(t,a),a.length!==0){for(let e of a)i.push(e.material),e.material=fh;e.gl.render(t,e.camera);for(let e=0;e<a.length;e++){let t=a[e],n=i[e];t&&n&&(t.material=n)}s++}}a.length=0,i.length=0,e.gl.clippingPlanes=o}syncFancy(e){let t=e.material.uniforms,n=this.size[0]??1,r=this.size[1]??1,i=Um(this);t.uTime&&(t.uTime.value=this.time),t.uOpacity&&(t.uOpacity.value=this.rp(`opacity`)),t.uWavesAmplitude&&(t.uWavesAmplitude.value=this.rp(`waveHeight`)*lm),(t.uScale?.value)?.set(n/2,r/2,r/2),(t.uWaterCenter?.value)?.set(i.x,i.y,i.z);let a=this.resolvePalette();(t.uTroughColor?.value)?.copy(a.trough),(t.uSurfaceColor?.value)?.copy(a.surface),(t.uPeakColor?.value)?.copy(a.peak),(t.uSunDirection?.value)?.set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),(t.uSunColor?.value)?.set(this.sunColor),t.uSunIntensity&&(t.uSunIntensity.value=this.rp(`sunIntensity`)),t.uDetailStrength&&(t.uDetailStrength.value=this.rp(`detailStrength`)),t.uAbsorption&&(t.uAbsorption.value=this.rp(`absorption`)),t.uSwellAmplitude&&(t.uSwellAmplitude.value=this.rp(`swell`)),t.uSwellWavelength&&(t.uSwellWavelength.value=this.rp(`swellWavelength`)),t.uSwellSteepness&&(t.uSwellSteepness.value=this.rp(`swellSteepness`)),t.uWhitecaps&&(t.uWhitecaps.value=this.rp(`whitecaps`)),t.uCausticsAbove&&(t.uCausticsAbove.value=this.rp(`causticsAbove`)),t.uShoreWaves&&(t.uShoreWaves.value=this.rp(`shoreWaves`));let o=this.presetLook();t.uFresnelScale&&(t.uFresnelScale.value=o.fresnelScale),t.uReflectivityMax&&(t.uReflectivityMax.value=o.reflectivityMax),t.uEdgeFadeOn&&(t.uEdgeFadeOn.value=+!!o.edgeFade),t.uFoamRange&&(t.uFoamRange.value=sm(n,r)*o.foamRangeScale),t.uFoamIntensity&&(t.uFoamIntensity.value=o.foamIntensity);let s=this.swellDirectionDeg*Math.PI/180;(t.uSwellDir?.value)?.set(Math.sin(s),Math.cos(s)),t.uWaveEnvelope&&(t.uWaveEnvelope.value=this.rp(`waveHeight`)*lm*1.5+this.rp(`swell`)*1.03),!this.reflection&&t.uUseEnvironmentMap&&(t.uUseEnvironmentMap.value=0),!this.foam&&t.uEnableFoam&&(t.uEnableFoam.value=0),!this.refraction&&t.uUseRefraction&&(t.uUseRefraction.value=0),t.uSplashFoam&&(t.uSplashFoam.value=+!!this.splash);let c=t.uRipples?.value,l=t.uRippleFoam?.value;if(c)for(let e=0;e<c.length;e++){let t=this._ripples[e];t?c[e].set(t.x,t.z,t.age,t.amp):c[e].set(0,0,0,0),l&&(l[e]=t?t.foam??0:0)}}_applySunDirection(t){let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this._ensureObject3D().material.uniforms?.uSunDirection?.value)?.set(t[0],t[1],t[2])}resolvePalette(){let t=this.rp(`colors`),n=this.rp(`color`),r=n===e.props.color?.default?null:n,i=t.surface??r??im.surface;return Xm.surface.set(i),t.trough?Xm.trough.set(t.trough):r?Xm.trough.set(r).lerp(qm,.45):Xm.trough.set(im.trough),t.peak?Xm.peak.set(t.peak):r?Xm.peak.set(r).lerp(Jm,.3):Xm.peak.set(im.peak),Xm}syncSimple(e){let t=e.material;t.opacity=this.rp(`opacity`);let n=t.uniforms,r=this.size[0]??1,i=this.size[1]??1,a=Um(this,this._scratchA);n.uTime&&(n.uTime.value=this.time),n.uOpacity&&(n.uOpacity.value=this.rp(`opacity`)),(n.uSurfaceColor?.value)?.set(this.rp(`color`)).lerp(Jm,.12),(n.uColor?.value)?.set(this.rp(`color`)).lerp(qm,.4),(n.uSkyColor?.value)?.set(this.rp(`color`)).lerp(Ym,.82),(n.uScale?.value)?.set(r/2,i/2,i/2),(n.uWaterCenter?.value)?.set(a.x,a.y,a.z),(n.uSunDirection?.value)?.set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),(n.uSunColor?.value)?.set(this.sunColor),n.uSunIntensity&&(n.uSunIntensity.value=this.rp(`sunIntensity`)),n.uDetailStrength&&(n.uDetailStrength.value=this.rp(`detailStrength`)),n.uSplashFoam&&(n.uSplashFoam.value=+!!this.splash);let o=n.uRipples?.value,s=n.uRippleFoam?.value;if(o)for(let e=0;e<o.length;e++){let t=this._ripples[e];t?o[e].set(t.x,t.z,t.age,t.amp):o[e].set(0,0,0,0),s&&(s[e]=t?t.foam??0:0)}let c=e.geometry,l=c.getAttribute(`position`),u=c.getAttribute(`normal`),d=this.time,f=this.rp(`waveHeight`),p=a.x,m=a.z,h=this._ripples,g=.5;for(let e=0;e<l.count;e++){let t=l.getX(e),n=l.getZ(e),r=Gp(t,n,d,f)+lp(t+p,n+m,h);l.setY(e,r);let i=Gp(t+g,n,d,f)+lp(t+p+g,n+m,h),a=Gp(t,n+g,d,f)+lp(t+p,n+m+g,h),o=(r-i)/g,s=(r-a)/g,c=1/Math.hypot(o,1,s);u.setXYZ(e,o*c,c,s*c)}l.needsUpdate=!0,u.needsUpdate=!0}stepInteraction(e){let t=this;for(;t.parent;)t=t.parent;let n=this._bodies;n.length=0,Hm(t,n);let r=Um(this,this._scratchA),i=(this.size[0]??0)/2,a=(this.size[1]??0)/2,o=[];for(let e of n){let t=Um(e,this._scratchB);if(Math.abs(t.x-r.x)>i||Math.abs(t.z-r.z)>a)continue;let n=rp(e.collider);o.push({id:e,x:t.x,y:t.y,z:t.z,waterline:r.y+this.waveOffsetAt(t.x,t.z,r)+n})}let{entered:s,exited:c,inWater:l}=ap(this.inWater,o,xm);this.inWater=l;let u=this.splash;for(let e of s){let t=Math.abs(Wm(e.id)?.[1]??0);op(this._ripples,e.x,e.z,Gm(e.id),u?ip(t):0),this.emit(`entered`,e.id)}for(let e of c)op(this._ripples,e.x,e.z,Tm,u?Am:0),this.emit(`exited`,e.id);for(let t of up(this.bobTimers,l,e,Em)){let e=Um(t,this._scratchB);op(this._ripples,e.x,e.z,Dm)}for(let e of l){let t=Um(e,this._scratchB),n=this.wadeAnchors.get(e);if(!n){this.wadeAnchors.set(e,{x:t.x,z:t.z});continue}let r=t.x-n.x,i=t.z-n.z;if(r*r+i*i>=Om*Om){let r=Wm(e),i=Math.hypot(r?.[0]??0,r?.[2]??0),a=u?Math.min(jm+Mm*i,Nm):0;op(this._ripples,t.x,t.z,km,a),n.x=t.x,n.z=t.z}}for(let e of this.wadeAnchors.keys())l.has(e)||this.wadeAnchors.delete(e)}heightAt(e,t){let n=Um(this,this._scratchA);return n.y+this.waveOffsetAt(e,t,n)}waveOffsetAt(e,t,n){return this.quality===`simple`?Gp(e-n.x,t-n.z,this.time,this.rp(`waveHeight`)):Wp(e,t,this.time,{amplitude:this.rp(`waveHeight`)*lm,frequency:Mp.frequency,persistence:Mp.persistence,lacunarity:Mp.lacunarity,iterations:Mp.iterations,speed:Mp.speed,scaleNorm:cm})}},Fm=new H,Im=new V,Lm=new Pi;function Rm(e,t){e instanceof $p&&e.enabled&&e.visible&&t.push(e);for(let n of e.children)Rm(n,t)}function zm(e){let t=e.parent;if(!(t instanceof qp)||!t.parent)return null;let n=t._ensureObject3D();return typeof n?.traverse==`function`?n:null}var Bm=new Set([`Terrain3D`,`Water3D`,`River3D`]);function Vm(e,t){return e.traverse(e=>{let n=e;if(!n.isMesh||!n.visible||!n.material)return;let r=(e.userData?.incantoNode)?.constructor?.typeName;r&&Bm.has(r)||t.push(n)}),t}function Hm(e,t){(e instanceof Qp||e instanceof Zp)&&t.push(e);for(let n of e.children)Hm(n,t)}function Um(e,t={x:0,y:0,z:0}){let n=0,r=0,i=0,a=e;for(;a;)a instanceof qp&&(n+=a.position[0]??0,r+=a.position[1]??0,i+=a.position[2]??0),a=a.parent;return t.x=n,t.y=r,t.z=i,t}function Wm(e){return e.velocity??e.linearVelocity}function Gm(e){let t=Math.abs(Wm(e)?.[1]??0);return Math.min(Sm+Cm*t,wm)}function Km(e,t,n){let r=new Ws(e,t,n,n);return r.rotateX(-Math.PI/2),r}var qm=new G(`#000000`),Jm=new G(`#ffffff`),Ym=new G(`#cfe3f0`),Xm={trough:new G,surface:new G,peak:new G},Zm=new B,Qm=new H,$m=3,eh=new H,th=new H,nh=new H,rh=new V,ih=new ss(new H(0,1,0),0),ah=[ih],oh=new ss(new H(0,-1,0),0),sh=[oh],ch=[],lh=new ss(new H(0,1,0),0),uh=[lh],dh=new ic;dh.colorWrite=!1;var fh=new ec({uniforms:{uCenter:{value:new H},uHalf:{value:new H(1,1,1)},uYaw:{value:new B(1,0)}},vertexShader:`
|
|
5685
|
+
uniform vec3 uCenter;
|
|
5686
|
+
uniform vec2 uYaw;
|
|
5687
|
+
varying vec3 vCutLocal;
|
|
5688
|
+
void main() {
|
|
5689
|
+
vec3 world = (modelMatrix * vec4(position, 1.0)).xyz;
|
|
5690
|
+
vec3 rel = world - uCenter;
|
|
5691
|
+
vCutLocal = vec3(rel.x * uYaw.x + rel.z * uYaw.y, rel.y, -rel.x * uYaw.y + rel.z * uYaw.x);
|
|
5692
|
+
vec4 clip = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
5693
|
+
// pull the DEPTH to the near plane and nothing else — scaling the view
|
|
5694
|
+
// position would slide the silhouette under perspective, and a silhouette
|
|
5695
|
+
// that grows past its owner is exactly the hole this design forbids
|
|
5696
|
+
clip.z = -clip.w * 0.99;
|
|
5697
|
+
gl_Position = clip;
|
|
5698
|
+
}
|
|
5699
|
+
`,fragmentShader:`
|
|
5700
|
+
uniform vec3 uHalf;
|
|
5701
|
+
varying vec3 vCutLocal;
|
|
5702
|
+
void main() {
|
|
5703
|
+
if (any(greaterThan(abs(vCutLocal), uHalf))) discard;
|
|
5704
|
+
gl_FragColor = vec4(0.0);
|
|
5705
|
+
}
|
|
5706
|
+
`,colorWrite:!1,depthWrite:!0,depthTest:!1,side:2});function ph(e,t){let n=e.shape;if(n!==void 0){if(e.oneWay!==void 0&&typeof e.oneWay!=`boolean`)throw new y(`BAD_FORMAT`,`Collider on '${t}': "oneWay" must be a boolean (platforms you jump up through), got ${JSON.stringify(e.oneWay)}.`);if(n===`rect`){let n=e.size;if(!Array.isArray(n)||n.length!==2||n.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${t}': rect needs "size": [width, height].`);return}if(n===`circle`){if(typeof e.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': circle needs "radius".`);return}if(n===`capsule`){if(typeof e.radius!=`number`||typeof e.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${t}': capsule needs "radius" and "height".`);return}throw new y(`BAD_FORMAT`,`Collider on '${t}': "shape" must be 'rect', 'circle', or 'capsule', got ${JSON.stringify(n)}.`)}}var mh=class extends Pe{static typeName=`Node2D`;static props={position:{default:[0,0]},rotation:{default:0},static:{default:!1},scale:{default:[1,1]},renderOrder:{default:0},orderGroup:{default:`default`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},visible:{default:!0}};static propAliases={zIndex:`renderOrder`};position=[0,0];rotation=0;static=!1;scale=[1,1];renderOrder=0;orderGroup=`default`;get effectiveRenderOrder(){return nt(this.orderGroup,this.renderOrder)}visible=!0;_object2D=null;_ensureObject2D(){return this._object2D||(this._object2D=this._createObject2D(),this._object2D.userData.incantoNode=this),this._object2D}_createObject2D(){return new Zi}_syncObject2D(e){let t=this._ensureObject2D();t.position.set(this.position[0]??0,-(this.position[1]??0),0),t.rotation.z=-ni.degToRad(this.rotation),t.scale.set(this.scale[0]??1,this.scale[1]??1,1),t.visible=this.visible}free(){super.free(),this._object2D?.removeFromParent(),this._object2D=null}},hh=class extends mh{static props={collider:{default:{}}};static signals=[`triggerEnter`,`triggerExit`];_collider={};_colliderChanged=!1;get collider(){return this._collider}set collider(e){this._collider=e,this._colliderChanged=!0}static validateJson(e){ph(e.collider,e.name)}_physics=null},gh=class extends hh{static typeName=`StaticBody2D`},_h=class extends hh{static typeName=`Area2D`},vh=class extends hh{static typeName=`RigidBody2D`;static props={mass:{default:1},gravityScale:{default:1},fixedRotation:{default:!1},friction:{default:.5},restitution:{default:0},linearVelocity:{default:[0,0]}};mass=1;gravityScale=1;fixedRotation=!1;friction=.5;restitution=0;linearVelocity=[0,0]},yh=class extends hh{static typeName=`CharacterBody2D`;static props={velocity:{default:[0,0]},snapToGround:{default:!0},slopeLimitDeg:{default:45}};velocity=[0,0];snapToGround=!0;slopeLimitDeg=45;_grounded=!1;moveAndSlide(){if(!this._physics)throw new y(`TREE_VIOLATION`,this.collider.shape===void 0?`CharacterBody2D '${this.name}' has no collider — set a collider prop (physics skips collider-less bodies).`:`CharacterBody2D '${this.name}' has no physics world — await enablePhysics2D(engine) first.`);this._physics.moveAndSlide(this)}isOnFloor(){return this._grounded}},bh=new Set;function xh(e){return bh.add(e),()=>bh.delete(e)}function Sh(e){return[...bh].filter(t=>t.dimension===e)}var Ch=class extends mh{static typeName=`Joint2D`;static props={type:{default:`revolute`,options:[`fixed`,`revolute`,`rope`,`spring`]},target:{default:``},anchor:{default:[0,0]},targetAnchor:{default:[0,0]},length:{default:0},stiffness:{default:50},damping:{default:5}};type=`revolute`;target=``;anchor=[0,0];targetAnchor=[0,0];length=0;stiffness=50;damping=5;onEnterTree(){if(!(this.parent instanceof hh))throw new y(`TREE_VIOLATION`,`Joint2D '${this.name}' must be a child of a physics body (its body A); parent is '${this.parent?.name??`none`}'.`);if(this.target===``)throw new y(`BAD_FORMAT`,`Joint2D '${this.name}' needs a "target" node path to the body it links to.`)}_resolveBodies(){let e=this.parent,t=this.getNodeOrNull(this.target);if(!(t instanceof hh))throw new y(`NODE_NOT_FOUND`,`Joint2D '${this.name}': target '${this.target}' is not a physics body.`);return{a:e,b:t}}},wh=`modulepreload`,Th=function(e,t){return new URL(e,t).href},Eh={},Dh=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=Th(t,n),t in Eh)return;Eh[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:wh,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},X=100,Oh=Math.PI/180;async function kh(e,t){let n=await Dh(()=>import(`./rapier-CEuLKeCu.js`),[],import.meta.url);return await n.init({}),new Ah(n,e,t)}var Ah=class{R;engine;debugDraw=!1;dimension=`2d`;unregisterDebug;warnedNoCollider=new WeakSet;entries=new Map;byColliderHandle=new Map;world;events;kcc;disconnect;lastDt=1/60;optsGravity;lastScene=null;constructor(e,t,n){this.R=e,this.engine=t,this.optsGravity=n?.gravity,this.lastScene=t.scene;let r=t.scene?.physics?.gravity,i=n?.gravity??r??[0,980];this.world=new e.World({x:(i[0]??0)/X,y:(i[1]??0)/X}),this.kcc=this.world.createCharacterController(.01),this.kcc.setUp({x:0,y:-1}),this.events=new e.EventQueue(!0),this.unregisterDebug=xh(this),this.disconnect=t.fixedUpdated.connect(e=>this.step(e)),this.syncBodies()}step(e){if(this.lastDt=e,this.engine.scene!==this.lastScene&&(this.lastScene=this.engine.scene,!this.optsGravity)){let e=this.engine.scene?.physics?.gravity??[0,980];this.world.gravity={x:(e[0]??0)/X,y:(e[1]??0)/X}}this.syncBodies(),this.world.timestep=e,this.world.step(this.events);for(let[e,t]of this.entries){let n=t.body.translation();if(!t.body.isFixed()){let[t,r]=Lh(e);e.position=[n.x*X-t,n.y*X-r]}if(e instanceof vh){e.fixedRotation||(e.rotation=t.body.rotation()/Oh);let n=t.body.linvel();e.linearVelocity=[n.x*X,n.y*X],t.lastVX=e.linearVelocity[0]??0,t.lastVY=e.linearVelocity[1]??0}let[r,i]=Ih(e);t.lastX=r,t.lastY=i}this.events.drainCollisionEvents((e,t,n)=>{let r=this.byColliderHandle.get(e),i=this.byColliderHandle.get(t);if(!r||!i)return;let a=n?`triggerEnter`:`triggerExit`;try{r.emit(a,i),i.emit(a,r)}catch(e){console.error(`incanto: error in a '${a}' handler (${r.name} ↔ ${i.name}):`,e)}})}moveAndSlide(e){let t=this.ensureEntry(e),n=e.velocity[1]??0;e.snapToGround&&n>=0?this.kcc.enableSnapToGround(.05):this.kcc.disableSnapToGround(),this.kcc.setMaxSlopeClimbAngle(e.slopeLimitDeg*Oh);let r=0,i=0;if(t.ground&&t.ground._physics===this){let[e,n]=Ih(t.ground);r=e-(t.groundX??e),i=n-(t.groundY??n)}else t.ground=null;let a={x:((e.velocity[0]??0)*this.lastDt+r)/X*1,y:(n*this.lastDt+i)/X*1},o=t.body.translation().y*X+Ph(e);this.kcc.computeColliderMovement(t.collider,a,this.R.QueryFilterFlags.EXCLUDE_SENSORS,void 0,t=>{let r=this.byColliderHandle.get(t.handle);return!(r&&r!==e&&r.collider.oneWay===!0&&(n<0||o>Fh(r)+Nh))});let s=this.kcc.computedMovement(),c=t.body.translation();if(t.body.setNextKinematicTranslation({x:c.x+s.x,y:c.y+s.y}),e._grounded=this.kcc.computedGrounded(),e._grounded){let n=(c.x+s.x)*X,r=(c.y+s.y)*X+Ph(e)-2,i=this.castRay([n,r],[0,1],8,e);if(i?.node&&!(i.node instanceof yh)){t.ground=i.node;let[e,n]=Ih(i.node);t.groundX=e,t.groundY=n}else t.ground=null}else t.ground=null}debugLines(){if(!this.debugDraw)return null;let e=this.world.debugRender().vertices,t=new Float32Array(e.length);for(let n=0;n<e.length;n++)t[n]=e[n]*X;return t}syncJoints(e){let t=this.R;if(e)for(let[e,t]of this.joints)this.jointSet.has(e)||(this.world.removeImpulseJoint(t,!0),this.joints.delete(e));for(let e of this.jointSet){if(this.joints.has(e))continue;let{a:n,b:r}=e._resolveBodies(),i=this.entries.get(n),a=this.entries.get(r);if(!i||!a)continue;let o={x:(e.anchor[0]??0)/X,y:(e.anchor[1]??0)/X},s={x:(e.targetAnchor[0]??0)/X,y:(e.targetAnchor[1]??0)/X},c=e.length/X;if(e.length===0&&(e.type===`rope`||e.type===`spring`)){let e=i.body.translation(),t=a.body.translation();c=Math.hypot(t.x-e.x,t.y-e.y)}let l;l=e.type===`fixed`?t.JointData.fixed(o,0,s,0):e.type===`rope`?t.JointData.rope(c,o,s):e.type===`spring`?t.JointData.spring(c,e.stiffness,e.damping,o,s):t.JointData.revolute(o,s),this.joints.set(e,this.world.createImpulseJoint(l,i.body,a.body,!0))}}castRay(e,t,n,r,i){let a=Math.hypot(t[0],t[1])||1,o=new this.R.Ray({x:e[0]/X,y:e[1]/X},{x:t[0]/a,y:t[1]/a}),s=r?this.entries.get(r)?.collider:void 0,c=i?.staticOnly?this.R.QueryFilterFlags.EXCLUDE_DYNAMIC|this.R.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,l=this.world.castRayAndGetNormal(o,n/X,!0,c,void 0,s,void 0,e=>!e.isSensor());return l?{distance:l.timeOfImpact*X,normal:[l.normal.x,l.normal.y],node:this.byColliderHandle.get(l.collider.handle)??null}:null}dispose(){this.disconnect(),this.unregisterDebug(),this.world.free()}lastStructure=-1;lastRoot=null;jointSet=new Set;joints=new Map;bodySet=new Set;syncBodies(){let e=this.engine.scene;if(!e)return;let t=e.tree._structureVersion,n=t!==this.lastStructure||e.root!==this.lastRoot;n&&(this.lastStructure=t,this.lastRoot=e.root,this.bodySet.clear(),Mh(e.root,this.bodySet)),n&&(this.jointSet.clear(),jh(e.root,this.jointSet));let r=this.bodySet;for(let e of r){if(e.collider.shape===void 0){let t=this.entries.get(e);t&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null),this.warnedNoCollider.has(e)||(this.warnedNoCollider.add(e),console.warn(`[incanto] '${e.name}' has no collider — physics skips it.`));continue}let t=this.entries.get(e);t&&e._colliderChanged&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null),this.ensureEntry(e)}if(this.syncJoints(n),n)for(let[e,t]of this.entries)r.has(e)||(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null)}ensureEntry(e){let t=this.entries.get(e),n=this.R;if(!t){let[r,i]=Ih(e),a=r/X,o=i/X,s;s=e instanceof vh?n.RigidBodyDesc.dynamic():e instanceof yh||e instanceof _h?n.RigidBodyDesc.kinematicPositionBased():n.RigidBodyDesc.fixed(),s.setTranslation(a,o).setRotation(e.rotation*Oh),e instanceof vh&&(s.setGravityScale(e.gravityScale),s.setLinvel((e.linearVelocity[0]??0)/X,(e.linearVelocity[1]??0)/X),e.fixedRotation&&s.lockRotations());let c=this.world.createRigidBody(s),l=Rh(n,e.collider,e.name);l.setActiveEvents(n.ActiveEvents.COLLISION_EVENTS),l.setActiveCollisionTypes(n.ActiveCollisionTypes.ALL),e instanceof _h&&l.setSensor(!0),e instanceof vh&&l.setMass(e.mass).setFriction(e.friction).setRestitution(e.restitution);let u=this.world.createCollider(l,c);return t={body:c,collider:u,lastX:r,lastY:i,lastVX:0,lastVY:0},this.entries.set(e,t),this.byColliderHandle.set(u.handle,e),e._colliderChanged=!1,e._physics=this,t}let[r,i]=Ih(e);if((r!==t.lastX||i!==t.lastY)&&(t.body.setTranslation({x:r/X,y:i/X},!0),t.lastX=r,t.lastY=i),e instanceof vh){let n=e.linearVelocity[0]??0,r=e.linearVelocity[1]??0;(n!==t.lastVX||r!==t.lastVY)&&(t.body.setLinvel({x:n/X,y:r/X},!0),t.lastVX=n,t.lastVY=r)}return t}};function jh(e,t){e instanceof Ch&&t.add(e);for(let n of e.children)jh(n,t)}function Mh(e,t){e instanceof hh&&t.add(e);for(let n of e.children)Mh(n,t)}var Nh=4;function Ph(e){let t=e.collider;return t.shape===`rect`?(t.size?.[1]??32)/2:t.shape===`capsule`?(t.height??32)/2+(t.radius??8):t.radius??16}function Fh(e){let[,t]=Ih(e),n=e.collider;return t-(n.shape===`rect`?(n.size?.[1]??32)/2:n.shape===`capsule`?(n.height??32)/2+(n.radius??8):n.radius??16)}function Ih(e){let t=0,n=0;for(let r=e;r;r=r.parent)r instanceof mh&&(t+=r.position[0]??0,n+=r.position[1]??0);return[t,n]}function Lh(e){let t=0,n=0;for(let r=e.parent;r;r=r.parent)r instanceof mh&&(t+=r.position[0]??0,n+=r.position[1]??0);return[t,n]}function Rh(e,t,n){ph(t,n);let r=zh(e,t,n),i=t.offset;return Array.isArray(i)&&r.setTranslation((i[0]??0)/X,(i[1]??0)/X),r}function zh(e,t,n){let r=t.shape;if(r===`rect`){let r=t.size;if(!Array.isArray(r)||r.length!==2||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${n}': rect needs "size": [width, height].`);return e.ColliderDesc.cuboid(r[0]/2/X,r[1]/2/X)}if(r===`circle`){if(typeof t.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': circle needs "radius".`);return e.ColliderDesc.ball(t.radius/X)}if(r===`capsule`){if(typeof t.radius!=`number`||typeof t.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': capsule needs "radius" and "height".`);return e.ColliderDesc.capsule(t.height/2/X,t.radius/X)}throw new y(`BAD_FORMAT`,`Collider on '${n}': "shape" must be 'rect', 'circle', or 'capsule', got ${JSON.stringify(r)}.`)}var Bh=new Ws(1,1),Vh=class extends mh{static typeName=`Sprite2D`;static props={texture:{default:``},anchor:{default:[.5,.5]},flipX:{default:!1},flipY:{default:!1},tint:{default:`#ffffff`},opacity:{default:1}};texture=``;anchor=[.5,.5];flipX=!1;flipY=!1;tint=`#ffffff`;opacity=1;quadMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(Bh,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_createObject2D(){return super._createObject2D()}resolveTexture(e){if(!this.texture||!e)return null;let t=e.getTexture(this.texture),n=t.image;return!n?.width||!n.height?null:{texture:t,width:n.width,height:n.height}}_syncObject2D(e){super._syncObject2D(e);let t=this._quad(),n=t.material,r=this.resolveTexture(e);if(!r){t.visible=!1;return}t.visible=!0,n.map!==r.texture&&(n.map=r.texture,n.needsUpdate=!0);let i=r.width,a=r.height;t.scale.set(this.flipX?-i:i,this.flipY?-a:a,1);let o=this.anchor[0]??.5,s=this.anchor[1]??.5;t.position.set((.5-o)*i,(s-.5)*a,0),t.renderOrder=this.effectiveRenderOrder,n.color.set(this.tint),n.opacity=this.opacity}},Hh=class extends Vh{static typeName=`AnimatedSprite2D`;static signals=[`animationFinished`];static props={sheet:{default:``},animations:{default:{}},autoplay:{default:``}};sheet=``;animations={};autoplay=``;playing=!1;currentFrame=0;currentAnimation=``;frameList=[];frameIndex=0;frameTime=0;ownTexture=null;loadedSheetRef=``;play(e){let t=this.animations[e];if(!t)throw new y(`UNKNOWN_ANIMATION`,`No animation '${e}' on '${this.name}'. Available: [${Object.keys(this.animations).join(`, `)}].`);this.currentAnimation=e,this.frameList=Uh(t.frames,e),this.frameIndex=0,this.currentFrame=this.frameList[0]??0,this.frameTime=0,this.playing=!0}stop(){this.playing=!1}onReady(){this.autoplay&&this.play(this.autoplay)}update(e){if(!this.playing||this.currentAnimation===``)return;let t=this.animations[this.currentAnimation];if(!t||!Number.isFinite(t.fps)||t.fps<=0)return;let n=1/t.fps;for(this.frameTime+=e;this.frameTime>=n;)if(this.frameTime-=n,this.frameIndex+=1,this.frameIndex>=this.frameList.length)if(t.loop)this.frameIndex=0;else{this.frameIndex=this.frameList.length-1,this.playing=!1,this.emit(`animationFinished`,this.currentAnimation);break}this.currentFrame=this.frameList[this.frameIndex]??0}resolveTexture(e){if(!this.sheet||!e)return null;let t=e.getSheet(this.sheet);this.loadedSheetRef!==this.sheet&&(this.ownTexture=t.texture.clone(),this.ownTexture.needsUpdate=!0,this.loadedSheetRef=this.sheet);let n=this.ownTexture,r=t.texture.image;if(!r?.width||!r.height)return null;let i=Math.max(1,Math.floor(r.width/t.frameWidth)),a=this.currentFrame%i,o=Math.floor(this.currentFrame/i);return n.repeat.set(t.frameWidth/r.width,t.frameHeight/r.height),n.offset.set(a*t.frameWidth/r.width,1-(o+1)*t.frameHeight/r.height),{texture:n,width:t.frameWidth,height:t.frameHeight}}};function Uh(e,t){if(!Array.isArray(e)||e.length===0)throw new y(`BAD_FORMAT`,`Animation '${t}': "frames" must be a non-empty array.`);if(e.length===2){let[t,n]=e;if(n>=t){let e=[];for(let r=t;r<=n;r++)e.push(r);return e}}return[...e]}var Wh=class extends mh{static typeName=`Camera2D`;static props={follow:{default:``},smoothing:{default:0},zoom:{default:1},limits:{default:[]},current:{default:!1}};follow=``;smoothing=0;zoom=1;limits=[];current=!1;get effectiveZoom(){return Math.max(.01,this.zoom)}update(e){if(!this.follow)return;let t=this.getNodeOrNull(this.follow);if(!(t instanceof mh))return;let n=t.position[0]??0,r=t.position[1]??0,i=Math.min(Math.max(this.smoothing,0),.99),a=i<=0?1:1-i**(e*60),o=this.position[0]??0,s=this.position[1]??0;this.position=[o+(n-o)*a,s+(r-s)*a]}clampedCenter(e,t){let n=this.position[0]??0,r=this.position[1]??0;if(this.limits.length!==0&&this.limits.length!==4)throw new y(`BAD_FORMAT`,`Camera2D '${this.name}' limits must be [] or [minX,minY,maxX,maxY], got length ${this.limits.length}.`);if(this.limits.length===4){let[i,a,o,s]=this.limits,c=e/(2*this.effectiveZoom),l=t/(2*this.effectiveZoom);n=Gh(n,i+c,o-c),r=Gh(r,a+l,s-l)}return{x:n,y:r}}};function Gh(e,t,n){return t>n?(t+n)/2:Math.min(n,Math.max(t,e))}var Kh=class extends Pe{static typeName=`CharacterController2D`;static props={mode:{default:`platformer`,options:[`platformer`,`topDown`]},maxSpeed:{default:220},jumpHeight:{default:64},moveAction:{default:`move`},jumpAction:{default:`jump`}};mode=`platformer`;maxSpeed=220;jumpHeight=64;moveAction=`move`;jumpAction=`jump`;onReady(){if(!(this.parent instanceof yh))throw new y(`TREE_VIOLATION`,`CharacterController2D '${this.name}' must be a child of a CharacterBody2D (parent is '${this.parent?.name??`none`}').`);if(this.mode!==`platformer`&&this.mode!==`topDown`)throw new y(`PROP_TYPE_MISMATCH`,`CharacterController2D.mode must be 'platformer' or 'topDown', got '${this.mode}'.`)}fixedUpdate(e){let t=this.tree?.engine;if(!t?.scene)return;let n=this.parent;if(!(n instanceof yh))return;let r=t.input,i=r.getVector(this.moveAction);if(this.mode===`topDown`){n.velocity=[i.x*this.maxSpeed,i.y*this.maxSpeed],n.moveAndSlide();return}let a=t.scene.physics?.gravity?.[1]??980;if(n.velocity[0]=i.x*this.maxSpeed,n.isOnFloor()){let e=r.justPressed(this.jumpAction);n.velocity[1]=e?-Math.sqrt(2*a*this.jumpHeight):20}else n.velocity[1]=(n.velocity[1]??0)+a*e;n.moveAndSlide()}},qh=new Ws(1,1),Jh=class extends mh{static typeName=`ColorRect2D`;static props={size:{default:[100,100]},color:{default:`#ffffff`},opacity:{default:1},anchor:{default:[.5,.5]}};size=[100,100];color=`#ffffff`;opacity=1;anchor=[.5,.5];quadMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(qh,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._quad(),n=this.size[0]??0,r=this.size[1]??0;t.visible=n>0&&r>0&&this.opacity>0,t.scale.set(n,r,1);let i=this.anchor[0]??.5,a=this.anchor[1]??.5;t.position.set((.5-i)*n,(a-.5)*r,0),t.renderOrder=this.effectiveRenderOrder;let o=t.material;o.color.set(this.color),o.opacity=this.opacity}},Yh=new Ws(1,1),Xh=class extends mh{static typeName=`Label`;static props={text:{default:``},fontSize:{default:16},color:{default:`#ffffff`},font:{default:`monospace`},align:{default:`left`}};text=``;fontSize=16;color=`#ffffff`;font=`monospace`;align=`left`;quadMesh=null;canvas=null;lastKey=``;_quad(){return this.quadMesh||(this.quadMesh=new jo(Yh,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.quadMesh)),this.quadMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._quad();if(typeof document>`u`||this.text===``){t.visible=!1;return}let n=`${this.text}\0${this.fontSize}\0${this.color}\0${this.font}\0${this.align}`;n!==this.lastKey&&(this.lastKey=n,this.rasterize()),t.visible=!0,t.renderOrder=this.effectiveRenderOrder}rasterize(){let e=Math.min(globalThis.devicePixelRatio??1,2);this.canvas??=document.createElement(`canvas`);let t=this.canvas.getContext(`2d`);if(!t)return;let n=`${this.fontSize*e}px ${this.font}`;t.font=n;let r=t.measureText(this.text),i=Math.max(1,Math.ceil(r.width)),a=Math.ceil(this.fontSize*e*1.4);this.canvas.width=i,this.canvas.height=a,t.font=n,t.fillStyle=this.color,t.textBaseline=`middle`,t.fillText(this.text,0,a/2);let o=this._quad(),s=o.material;s.map?.dispose(),s.map=new Ps(this.canvas),s.needsUpdate=!0;let c=i/e,l=a/e;o.scale.set(c,l,1);let u=this.align===`center`?.5:+(this.align===`right`);o.position.set((.5-u)*c,0,0)}},Zh=new Ws(1,1),Qh=class e extends mh{orderGroup=`effects`;static typeName=`Particles2D`;static signals=[`finished`];static props={orderGroup:{default:`effects`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},preset:{default:`custom`,options:[`custom`,...it]},emitting:{default:!0},rate:{default:40},burst:{default:0},lifetime:{default:[.6,1.2]},speed:{default:[40,120]},directionDeg:{default:-90},spreadDeg:{default:30},gravity:{default:[0,0]},drag:{default:0},sizeStart:{default:8},sizeEnd:{default:2},colorStart:{default:`#ffffff`},colorEnd:{default:`#ffffff`},paletteColors:{default:[]},alphaStart:{default:1},alphaEnd:{default:0},shimmer:{default:0},blend:{default:`add`,options:[`add`,`normal`]},maxParticles:{default:256}};preset=`custom`;emitting=!0;rate=40;burst=0;lifetime=[.6,1.2];speed=[40,120];directionDeg=-90;spreadDeg=30;gravity=[0,0];drag=0;sizeStart=8;sizeEnd=2;colorStart=`#ffffff`;colorEnd=`#ffffff`;paletteColors=[];alphaStart=1;alphaEnd=0;shimmer=0;blend=`add`;maxParticles=256;static validateJson(e){let t=e;if(t.preset!==`custom`&&!it.includes(t.preset))throw new y(`BAD_FORMAT`,`Particles2D '${e.name}' preset must be 'custom' or one of [${it.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:it});if(t.blend!==`add`&&t.blend!==`normal`)throw new y(`BAD_FORMAT`,`Particles2D '${e.name}' blend must be 'add' or 'normal', got '${t.blend}'.`,{prop:`blend`,validOptions:[`add`,`normal`]})}sim=null;bursted=!1;finishedEmitted=!1;_ensureSim(){if(!this.sim){at(this,this.preset,ge(e.typeName));let t=this.tree?.engine?.rng??new b(4660);this.sim=new st({rate:this.emitting?this.rate:0,lifetime:[this.lifetime[0]??1,this.lifetime[1]??1],speed:[this.speed[0]??0,this.speed[1]??0],directionDeg:this.directionDeg,spreadDeg:this.spreadDeg,gravity:[this.gravity[0]??0,this.gravity[1]??0,0],drag:this.drag,maxParticles:this.maxParticles},t)}return this.sim}update(e){let t=this._ensureSim();this.burst>0&&!this.bursted&&(this.bursted=!0,t.burst(this.burst)),t.update(e),(!this.emitting||this.rate===0)&&this.bursted&&t.done&&!this.finishedEmitted&&(this.finishedEmitted=!0,this.emit(`finished`))}replay(){this.bursted=!1,this.finishedEmitted=!1}mesh=null;paletteCache=[];paletteCacheKey=``;refreshPalette(){let e=this.paletteColors;if(e.length===0)return null;let t=e.join(`|`);if(t!==this.paletteCacheKey){this.paletteCacheKey=t;for(let t=0;t<e.length;t++){let n=this.paletteCache[t];n||(n=new G,this.paletteCache[t]=n),n.set(e[t])}this.paletteCache.length=e.length}return this.paletteCache}_syncObject2D(e){super._syncObject2D(e);let t=this._ensureSim();if(!this.mesh||this.mesh.count!==this.maxParticles){this.mesh&&this.mesh.removeFromParent();let e=new yo({transparent:!0,depthWrite:!1,blending:this.blend===`add`?2:1});this.mesh=new rs(Zh,e,this.maxParticles),this.mesh.instanceMatrix.setUsage(_r),this.mesh.frustumCulled=!1,this._ensureObject2D().add(this.mesh)}let n=this.mesh,r=this.refreshPalette(),i=r?null:eg.set(this.colorStart),a=tg.set(this.colorEnd),o=this.shimmer,s=0;t.forEach(e=>{let t=this.sizeStart+(this.sizeEnd-this.sizeStart)*e.t;$h.makeScale(t,t,1),$h.setPosition(e.x,-e.y,0),n.setMatrixAt(s,$h);let c=r?r[Math.floor(e.seed*r.length)]:i,l=Math.max(0,this.alphaStart+(this.alphaEnd-this.alphaStart)*e.t);o>0&&(l*=.5+.5*Math.sin(2*Math.PI*(e.age*o+e.seed))),ng.copy(c).lerp(a,e.t).multiplyScalar(l),n.setColorAt(s,ng),s+=1}),n.count=s,n.instanceMatrix.needsUpdate=!0,n.instanceColor&&(n.instanceColor.needsUpdate=!0),n.renderOrder=this.effectiveRenderOrder}},$h=new W,eg=new G,tg=new G,ng=new G;function rg(e,t){let n=[],r=0;for(let i of e){let e=[];if(typeof i==`string`)for(let n of i){let r=t[n];if(r!==void 0)e.push(r);else if(n===`.`||n===` `)e.push(-1);else if(n>=`0`&&n<=`9`)e.push(n.charCodeAt(0)-48);else throw new y(`BAD_FORMAT`,`TileMap2D: unknown tile char '${n}' — add it to "legend" (char → tile index), or use '.'/' ' for empty and digits 0-9.`)}else for(let t of i)e.push(t);r=Math.max(r,e.length),n.push(e)}for(let e of n)for(;e.length<r;)e.push(-1);return n}function ig(e,t){let n=e.length,r=n>0?e[0].length:0,i=e.map(e=>e.map(()=>!1)),a=(n,r)=>t.has(e[r][n]),o=[];for(let e=0;e<n;e++)for(let t=0;t<r;t++){if(!a(t,e)||i[e][t])continue;let s=1;for(;t+s<r&&a(t+s,e)&&!i[e][t+s];)s++;let c=1;grow:for(;e+c<n;){for(let n=0;n<s;n++)if(!a(t+n,e+c)||i[e+c][t+n])break grow;c++}for(let n=0;n<c;n++)for(let r=0;r<s;r++)i[e+n][t+r]=!0;o.push({x:t,y:e,w:s,h:c})}return o}var ag=class extends mh{static typeName=`TileMap2D`;static props={texture:{default:``},tileSize:{default:32},columns:{default:0},cells:{default:[]},legend:{default:{}},solid:{default:[]},opacity:{default:1}};texture=``;tileSize=32;columns=0;_cells=[];_legend={};_solid=[];geometryDirty=!0;collidersDirty=!0;get cells(){return this._cells}set cells(e){this._cells=e,this.geometryDirty=!0,this.collidersDirty=!0}get legend(){return this._legend}set legend(e){this._legend=e,this.geometryDirty=!0,this.collidersDirty=!0}get solid(){return this._solid}set solid(e){this._solid=e,this.collidersDirty=!0}opacity=1;tileMesh=null;builtColumns=0;builtRows=0;static validateJson(e){let t=e;rg(t._cells,t._legend)}grid(){return rg(this._cells,this._legend)}onReady(){this.rebuildColliders()}update(e){this.collidersDirty&&this.rebuildColliders()}rebuildColliders(){this.collidersDirty=!1;for(let e of[...this.children])e.name.startsWith(`__tileSolid`)&&e.free();if(this._solid.length===0)return;let e=this.tileSize;ig(this.grid(),new Set(this._solid)).forEach((t,n)=>{let r=new gh(`__tileSolid${n}`);r.position=[(t.x+t.w/2)*e,(t.y+t.h/2)*e],r.collider={shape:`rect`,size:[t.w*e,t.h*e]},this.addChild(r)})}_mesh(){return this.tileMesh||(this.tileMesh=new jo(new q,new yo({transparent:!0,depthWrite:!1})),this._ensureObject2D().add(this.tileMesh)),this.tileMesh}_syncObject2D(e){super._syncObject2D(e);let t=this._mesh(),n=t.material;if(!this.texture||!e){t.visible=!1;return}let r=e.getTexture(this.texture),i=r.image;if(!i?.width||!i.height){t.visible=!1;return}t.visible=this.opacity>0,t.renderOrder=this.effectiveRenderOrder,n.opacity=this.opacity,n.map!==r&&(r.magFilter=zt,n.map=r,n.needsUpdate=!0,this.geometryDirty=!0);let a=this.columns>0?this.columns:Math.max(1,Math.floor(i.width/this.tileSize)),o=Math.max(1,Math.floor(i.height/this.tileSize));(a!==this.builtColumns||o!==this.builtRows)&&(this.geometryDirty=!0),this.geometryDirty&&(this.geometryDirty=!1,this.builtColumns=a,this.builtRows=o,this.buildGeometry(t.geometry,a,o))}buildGeometry(e,t,n){let r=this.grid(),i=this.tileSize,a=[],o=[],s=[];for(let e=0;e<r.length;e++){let c=r[e];for(let r=0;r<c.length;r++){let l=c[r];if(l<0)continue;let u=r*i,d=u+i,f=-(e*i),p=-((e+1)*i),m=a.length/3;a.push(u,f,0,d,f,0,d,p,0,u,p,0);let h=l%t,g=Math.floor(l/t),_=h/t,v=(h+1)/t,y=1-g/n,b=1-(g+1)/n;o.push(_,y,v,y,v,b,_,b),s.push(m,m+2,m+1,m,m+3,m+2)}}e.setAttribute(`position`,new K(new Float32Array(a),3)),e.setAttribute(`uv`,new K(new Float32Array(o),2)),e.setIndex(s),e.computeBoundingSphere()}get renderedTileCount(){let e=this.tileMesh?.geometry.getAttribute(`position`);return e?e.count/4:0}free(){this.tileMesh?.geometry.dispose(),super.free()}},og=[`top-left`,`top`,`top-right`,`left`,`center`,`right`,`bottom-left`,`bottom`,`bottom-right`],sg=class extends Pe{static typeName=`UILayer`;static props={anchor:{default:`top-left`,options:og}};anchor=`top-left`;group=null;_ensureGroup(){return this.group||(this.group=new Qi,this.group.userData.incantoNode=this),this.group}static validateJson(e){let t=e.anchor;if(!og.includes(t))throw new y(`BAD_FORMAT`,`UILayer '${e.name}' anchor must be one of [${og.join(`, `)}], got '${t}'.`,{prop:`anchor`,validOptions:og})}_anchorOrigin(e,t){let n=this.anchor;return{x:n.includes(`right`)?e:n===`top`||n===`center`||n===`bottom`?e/2:0,y:n.includes(`bottom`)?t:n===`left`||n===`center`||n===`right`?t/2:0}}};function cg(){ct(),M(mh),M(Vh),M(Jh),M(Qh),M(Hh),M(Wh),M(Xh),M(sg),M(gh),M(vh),M(_h),M(yh),M(Kh),M(Ch),M(ag)}function lg(e,t,n){return{x:(t-e.cx)*e.zoom+e.w/2,y:(n-e.cy)*e.zoom+e.h/2}}function ug(e,t,n){return{x:(t-e.w/2)/e.zoom+e.cx,y:(n-e.h/2)/e.zoom+e.cy}}var dg=new Sa,fg=new H,pg=12,mg=new Float32Array(16);function hg(e){if(!(e instanceof mh))return null;let t=e._ensureObject2D();t.updateWorldMatrix(!0,!0),dg.setFromObject(t),dg.getSize(fg);let n,r,i,a;if(!Number.isFinite(fg.x)||fg.x===0&&fg.y===0){let e=new H().setFromMatrixPosition(t.matrixWorld);n=e.x-pg,i=e.x+pg,r=e.y-pg,a=e.y+pg}else n=dg.min.x-2,i=dg.max.x+2,r=dg.min.y-2,a=dg.max.y+2;let o=[n,r,i,r,i,r,i,a,i,a,n,a,n,a,n,r];return mg.set(o),mg}function gg(){return{visited:new Set,cameras:[]}}function _g(e,t,n,r,i,a,o){let s=a??gg();s.visited.clear(),s.cameras.length=0,vg(e,t,n,!1,s.visited,s.cameras,r,i,o?.ignoreStatic===!0),yg(t,s.visited),yg(n,s.visited);let c=null;for(let e=0;e<s.cameras.length;e++){let t=s.cameras[e];if(t.current){c=t;break}}return c||=s.cameras[0]??null,{activeCamera:c}}function vg(e,t,n,r,i,a,o,s,c){let l=t,u=r;if(e instanceof mh&&!(e instanceof sg)){let t=e._ensureObject2D();if(e.static&&!c&&t.userData.incantoStaticSynced===!0){t.userData.incantoStatic=!0,i.add(t);return}}if(e instanceof sg){let t=e._ensureGroup();t.parent!==n&&n.add(t);let r=s?e._anchorOrigin(s.width,s.height):{x:0,y:0};t.position.set(r.x,-r.y,0),i.add(t),u=!0,l=t}else if(e instanceof mh){let n=e._ensureObject2D();n.parent!==t&&t.add(n),e._syncObject2D(o),i.add(n),e instanceof Wh&&!r&&a.push(e),l=n}for(let t of e.children)vg(t,l,n,u,i,a,o,s,c);if(e instanceof mh&&!(e instanceof sg)){let t=e._ensureObject2D();e.static&&!c?(t.userData.incantoStaticSynced=!0,t.userData.incantoStatic=!0):t.userData.incantoStaticSynced===!0&&(t.userData.incantoStaticSynced=!1,t.userData.incantoStatic=!1)}}function yg(e,t){let n=e.children;for(let r=n.length-1;r>=0;r--){let i=n[r];i.userData.incantoNode&&!t.has(i)?e.remove(i):i.userData.incantoStatic!==!0&&yg(i,t)}}var bg=class{viewOverride=null;webgl;worldScene=new sa;syncScratch=gg();ignoreStatic=!1;uiScene=new sa;worldCam=new el(-1,1,1,-1,-1e3,1e3);uiCam=new el(-1,1,1,-1,-1e3,1e3);engine;assets;loadedAssetScenes=new WeakSet;disconnect;canvas;constructor(e){this.canvas=e.canvas,this.engine=e.engine,this.assets=e.assets??new Qf;let t=lt(e.engine.scene?.environment,{antialias:!0,pixelRatio:1},globalThis.devicePixelRatio??1,e);this.webgl=new Zf({canvas:e.canvas,antialias:t.antialias}),this.webgl.setPixelRatio(t.pixelRatio),this.webgl.info.autoReset=!1,this.debugLines=new ws(new q,new fs({color:`#00ff6e`,transparent:!0,depthTest:!1})),this.debugLines.frustumCulled=!1,this.debugLines.renderOrder=9999,this.debugLines.visible=!1,this.worldScene.add(this.debugLines),this.selectionLines=new ws(new q,new fs({color:`#ffb020`,transparent:!0,depthTest:!1})),this.selectionLines.frustumCulled=!1,this.selectionLines.renderOrder=1e4,this.selectionLines.visible=!1,this.worldScene.add(this.selectionLines),this.disconnect=this.engine.updated.connect(()=>this.render())}debugLines;selectionLines;syncSelectionOutline(){let e=this.engine.debugSelection;e&&e.tree!==this.engine.scene?.tree&&(this.engine.debugSelection=null);let t=this.engine.debugSelection,n=t?hg(t):null;if(this.selectionLines.visible=n!==null,!n)return;let r=new Float32Array(n.length/2*3);for(let e=0,t=0;e<n.length;e+=2,t+=3)r[t]=n[e],r[t+1]=n[e+1],r[t+2]=0;this.selectionLines.geometry.setAttribute(`position`,new K(r,3)),this.selectionLines.geometry.getAttribute(`position`).needsUpdate=!0}syncDebugLines(){let e=null;for(let t of Sh(`2d`))if(e=t.debugLines(),e)break;if(this.debugLines.visible=e!==null,!e)return;let t=new Float32Array(e.length/2*3);for(let n=0,r=0;n<e.length;n+=2,r+=3)t[r]=e[n],t[r+1]=e[n+1],t[r+2]=0;this.debugLines.geometry.setAttribute(`position`,new K(t,3))}render(){let e=this.engine.scene;if(!e)return;this.webgl.info.reset(),this.syncDebugLines(),this.syncSelectionOutline(),e.assets&&!this.loadedAssetScenes.has(e)&&(this.assets.load(e.assets),this.loadedAssetScenes.add(e));let t=e.environment?.background;this.worldScene.background=typeof t==`string`?new G(t):null;let n=this.canvas.clientWidth||this.canvas.width,r=this.canvas.clientHeight||this.canvas.height,i=this.webgl.getSize(Sg);(i.x!==n||i.y!==r)&&this.webgl.setSize(n,r,!1);let a=this.viewOverride?null:gt(e.viewport),o=a?_t(n,r,a):null,s=o?o.viewW:n,c=o?o.viewH:r,{activeCamera:l}=_g(e.root,this.worldScene,this.uiScene,this.assets,{width:s,height:c},this.syncScratch),u=a?{x:a.design[0]/2,y:a.design[1]/2}:{x:n/2,y:r/2},d=1;this.viewOverride?(u={x:this.viewOverride.cx,y:this.viewOverride.cy},d=this.viewOverride.zoom):l&&(u=l.clampedCenter(s,c),d=l.effectiveZoom);let f=o?.scale??1;this.lastView={cx:u.x,cy:u.y,zoom:d*f,w:n,h:r},this.lastViewport=o,o&&(o.offsetX>.5||o.offsetY>.5)?(this.webgl.setScissorTest(!1),this.webgl.setViewport(0,0,n,r),this.webgl.clear(),this.webgl.setViewport(o.offsetX,o.offsetY,o.contentW,o.contentH),this.webgl.setScissor(o.offsetX,o.offsetY,o.contentW,o.contentH),this.webgl.setScissorTest(!0)):(this.webgl.setScissorTest(!1),this.webgl.setViewport(0,0,n,r)),xg(this.worldCam,u.x,u.y,s/d,c/d),xg(this.uiCam,s/2,c/2,s,c),this.webgl.autoClear=!0,this.webgl.render(this.worldScene,this.worldCam),this.webgl.autoClear=!1,this.webgl.render(this.uiScene,this.uiCam),this.webgl.autoClear=!0}lastViewport=null;lastView={cx:0,cy:0,zoom:1,w:1,h:1};view(){return{...this.lastView}}stats(){let e=this.webgl.info;return{triangles:e.render.triangles,drawCalls:e.render.calls,geometries:e.memory.geometries,textures:e.memory.textures}}worldFromScreen(e,t){return ug(this.lastView,e,t)}screenFromWorld(e,t){return lg(this.lastView,e,t)}pick(e,t){let{w:n,h:r}=this.lastView,i=this.lastViewport?.offsetX??0,a=this.lastViewport?.offsetY??0,o=this.lastViewport?.contentW??n,s=this.lastViewport?.contentH??r;wg.set((e-i)/o*2-1,-((t-a)/s*2-1)),Tg.setFromCamera(wg,this.worldCam);let c=Tg.intersectObjects(this.worldScene.children,!0),l=null;for(let e of c){let t=e.object;for(;t&&!t.userData.incantoNode;)t=t.parent;let n=t?.userData.incantoNode;if(!n)continue;let r=e.object.renderOrder??0;(!l||r>=l.order)&&(l={node:n,order:r})}return l?.node??null}boundsOf(e){let t=e._object2D;if(!t||(Eg.makeEmpty(),Eg.expandByObject(t),Eg.isEmpty())||(Eg.getSize(Cg),Cg.x===0&&Cg.y===0))return null;let n=this.screenFromWorld(Eg.min.x,-Eg.max.y),r=this.screenFromWorld(Eg.max.x,-Eg.min.y);return{x:n.x,y:n.y,w:r.x-n.x,h:r.y-n.y}}dispose(){this.disconnect();for(let e of[this.worldScene,this.uiScene])e.traverse(e=>{let t=e;if(!t.isMesh)return;let n=Array.isArray(t.material)?t.material:[t.material];for(let e of n)e?.map?.dispose(),e?.dispose()});this.webgl.dispose()}};function xg(e,t,n,r,i){e.position.set(t,-n,10),e.left=-r/2,e.right=r/2,e.top=i/2,e.bottom=-i/2,e.updateProjectionMatrix()}var Sg=new B,Cg=new H,wg=new B,Tg=new kl,Eg=new Sa,Dg=e({enablePhysics2D:()=>kh}),Og=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),kg=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),Ag=class extends Zi{constructor(e){super(),this.weight=0,this.isBinary=!1,this.overrideBlink=`none`,this.overrideLookAt=`none`,this.overrideMouth=`none`,this._binds=[],this.name=`VRMExpression_${e}`,this.expressionName=e,this.type=`VRMExpression`,this.visible=!1}get binds(){return this._binds}get overrideBlinkAmount(){return this.overrideBlink===`block`?+(0<this.outputWeight):this.overrideBlink===`blend`?this.outputWeight:0}get overrideLookAtAmount(){return this.overrideLookAt===`block`?+(0<this.outputWeight):this.overrideLookAt===`blend`?this.outputWeight:0}get overrideMouthAmount(){return this.overrideMouth===`block`?+(0<this.outputWeight):this.overrideMouth===`blend`?this.outputWeight:0}get outputWeight(){return this.isBinary?+(this.weight>.5):this.weight}addBind(e){this._binds.push(e)}deleteBind(e){let t=this._binds.indexOf(e);t>=0&&this._binds.splice(t,1)}applyWeight(e){let t=this.outputWeight;t*=e?.multiplier??1,this.isBinary&&t<1&&(t=0),this._binds.forEach(e=>e.applyWeight(t))}clearAppliedWeight(){this._binds.forEach(e=>e.clearAppliedWeight())}};function jg(e,t,n){let r=e.parser.json,i=r.nodes?.[t];if(i==null)return console.warn(`extractPrimitivesInternal: Attempt to use nodes[${t}] of glTF but the node doesn't exist`),null;let a=i.mesh;if(a==null)return null;let o=r.meshes?.[a];if(o==null)return console.warn(`extractPrimitivesInternal: Attempt to use meshes[${a}] of glTF but the mesh doesn't exist`),null;let s=o.primitives.length,c=[];return n.traverse(e=>{c.length<s&&e.isMesh&&c.push(e)}),c}function Mg(e,t){return kg(this,null,function*(){return jg(e,t,yield e.parser.getDependency(`node`,t))})}function Ng(e){return kg(this,null,function*(){let t=yield e.parser.getDependencies(`node`),n=new Map;return t.forEach((t,r)=>{let i=jg(e,r,t);i!=null&&n.set(r,i)}),n})}var Pg={Aa:`aa`,Ih:`ih`,Ou:`ou`,Ee:`ee`,Oh:`oh`,Blink:`blink`,Happy:`happy`,Angry:`angry`,Sad:`sad`,Relaxed:`relaxed`,LookUp:`lookUp`,Surprised:`surprised`,LookDown:`lookDown`,LookLeft:`lookLeft`,LookRight:`lookRight`,BlinkLeft:`blinkLeft`,BlinkRight:`blinkRight`,Neutral:`neutral`};function Fg(e){return Math.max(Math.min(e,1),0)}var Ig=class e{constructor(){this.blinkExpressionNames=[`blink`,`blinkLeft`,`blinkRight`],this.lookAtExpressionNames=[`lookLeft`,`lookRight`,`lookUp`,`lookDown`],this.mouthExpressionNames=[`aa`,`ee`,`ih`,`oh`,`ou`],this._expressions=[],this._expressionMap={}}get expressions(){return this._expressions.concat()}get expressionMap(){return Object.assign({},this._expressionMap)}get presetExpressionMap(){let e={},t=new Set(Object.values(Pg));return Object.entries(this._expressionMap).forEach(([n,r])=>{t.has(n)&&(e[n]=r)}),e}get customExpressionMap(){let e={},t=new Set(Object.values(Pg));return Object.entries(this._expressionMap).forEach(([n,r])=>{t.has(n)||(e[n]=r)}),e}copy(e){return this._expressions.concat().forEach(e=>{this.unregisterExpression(e)}),e._expressions.forEach(e=>{this.registerExpression(e)}),this.blinkExpressionNames=e.blinkExpressionNames.concat(),this.lookAtExpressionNames=e.lookAtExpressionNames.concat(),this.mouthExpressionNames=e.mouthExpressionNames.concat(),this}clone(){return new e().copy(this)}getExpression(e){return this._expressionMap[e]??null}registerExpression(e){this._expressions.push(e),this._expressionMap[e.expressionName]=e}unregisterExpression(e){let t=this._expressions.indexOf(e);t===-1&&console.warn(`VRMExpressionManager: The specified expressions is not registered`),this._expressions.splice(t,1),delete this._expressionMap[e.expressionName]}getValue(e){return this.getExpression(e)?.weight??null}setValue(e,t){let n=this.getExpression(e);n&&(n.weight=Fg(t))}resetValues(){this._expressions.forEach(e=>{e.weight=0})}getExpressionTrackName(e){let t=this.getExpression(e);return t?`${t.name}.weight`:null}update(){let e=this._calculateWeightMultipliers();this._expressions.forEach(e=>{e.clearAppliedWeight()}),this._expressions.forEach(t=>{let n=1,r=t.expressionName;this.blinkExpressionNames.indexOf(r)!==-1&&(n*=e.blink),this.lookAtExpressionNames.indexOf(r)!==-1&&(n*=e.lookAt),this.mouthExpressionNames.indexOf(r)!==-1&&(n*=e.mouth),t.applyWeight({multiplier:n})})}_calculateWeightMultipliers(){let e=1,t=1,n=1;return this._expressions.forEach(r=>{e-=r.overrideBlinkAmount,t-=r.overrideLookAtAmount,n-=r.overrideMouthAmount}),e=Math.max(0,e),t=Math.max(0,t),n=Math.max(0,n),{blink:e,lookAt:t,mouth:n}}},Lg={Color:`color`,EmissionColor:`emissionColor`,ShadeColor:`shadeColor`,MatcapColor:`matcapColor`,RimColor:`rimColor`,OutlineColor:`outlineColor`},Rg={_Color:Lg.Color,_EmissionColor:Lg.EmissionColor,_ShadeColor:Lg.ShadeColor,_RimColor:Lg.RimColor,_OutlineColor:Lg.OutlineColor},zg=new G,Bg=class e{constructor({material:e,type:t,targetValue:n,targetAlpha:r}){this.material=e,this.type=t,this.targetValue=n,this.targetAlpha=r??1;let i=this._initColorBindState(),a=this._initAlphaBindState();this._state={color:i,alpha:a}}applyWeight(e){let{color:t,alpha:n}=this._state;if(t!=null){let{propertyName:n,deltaValue:r}=t;this.material[n]?.add(zg.copy(r).multiplyScalar(e))}if(n!=null){let{propertyName:t,deltaValue:r}=n;this.material[t]!=null&&(this.material[t]+=r*e)}}clearAppliedWeight(){let{color:e,alpha:t}=this._state;if(e!=null){let{propertyName:t,initialValue:n}=e;this.material[t]?.copy(n)}if(t!=null){let{propertyName:e,initialValue:n}=t;this.material[e]!=null&&(this.material[e]=n)}}_initColorBindState(){let{material:e,type:t,targetValue:n}=this,r=this._getPropertyNameMap()?.[t]?.[0]??null;if(r==null)return console.warn(`Tried to add a material color bind to the material ${e.name??`(no name)`}, the type ${t} but the material or the type is not supported.`),null;let i=e[r].clone();return{propertyName:r,initialValue:i,deltaValue:new G(n.r-i.r,n.g-i.g,n.b-i.b)}}_initAlphaBindState(){let{material:e,type:t,targetAlpha:n}=this,r=this._getPropertyNameMap()?.[t]?.[1]??null;if(r==null&&n!==1)return console.warn(`Tried to add a material alpha bind to the material ${e.name??`(no name)`}, the type ${t} but the material or the type does not support alpha.`),null;if(r==null)return null;let i=e[r];return{propertyName:r,initialValue:i,deltaValue:n-i}}_getPropertyNameMap(){return Object.entries(e._propertyNameMapMap).find(([e])=>this.material[e]===!0)?.[1]??null}};Bg._propertyNameMapMap={isMeshStandardMaterial:{color:[`color`,`opacity`],emissionColor:[`emissive`,null]},isMeshBasicMaterial:{color:[`color`,`opacity`]},isMToonMaterial:{color:[`color`,`opacity`],emissionColor:[`emissive`,null],outlineColor:[`outlineColorFactor`,null],matcapColor:[`matcapFactor`,null],rimColor:[`parametricRimColorFactor`,null],shadeColor:[`shadeColorFactor`,null]}};var Vg=Bg,Hg=class{constructor({primitives:e,index:t,weight:n}){this.primitives=e,this.index=t,this.weight=n}applyWeight(e){this.primitives.forEach(t=>{t.morphTargetInfluences?.[this.index]!=null&&(t.morphTargetInfluences[this.index]+=this.weight*e)})}clearAppliedWeight(){this.primitives.forEach(e=>{e.morphTargetInfluences?.[this.index]!=null&&(e.morphTargetInfluences[this.index]=0)})}},Ug=new B,Wg=class e{constructor({material:t,scale:n,offset:r}){this.material=t,this.scale=n,this.offset=r;let i=Object.entries(e._propertyNamesMap).find(([e])=>t[e]===!0)?.[1];i==null?(console.warn(`Tried to add a texture transform bind to the material ${t.name??`(no name)`} but the material is not supported.`),this._properties=[]):(this._properties=[],i.forEach(e=>{let i=t[e]?.clone();if(!i)return null;t[e]=i;let a=i.offset.clone(),o=i.repeat.clone(),s=r.clone().sub(a),c=n.clone().sub(o);this._properties.push({name:e,initialOffset:a,deltaOffset:s,initialScale:o,deltaScale:c})}))}applyWeight(e){this._properties.forEach(t=>{let n=this.material[t.name];n!==void 0&&(n.offset.add(Ug.copy(t.deltaOffset).multiplyScalar(e)),n.repeat.add(Ug.copy(t.deltaScale).multiplyScalar(e)))})}clearAppliedWeight(){this._properties.forEach(e=>{let t=this.material[e.name];t!==void 0&&(t.offset.copy(e.initialOffset),t.repeat.copy(e.initialScale))})}};Wg._propertyNamesMap={isMeshStandardMaterial:[`map`,`emissiveMap`,`bumpMap`,`normalMap`,`displacementMap`,`roughnessMap`,`metalnessMap`,`alphaMap`],isMeshBasicMaterial:[`map`,`specularMap`,`alphaMap`],isMToonMaterial:[`map`,`normalMap`,`emissiveMap`,`shadeMultiplyTexture`,`rimMultiplyTexture`,`outlineWidthMultiplyTexture`,`uvAnimationMaskTexture`]};var Gg=Wg,Kg=new Set([`1.0`,`1.0-beta`]),qg=class e{get name(){return`VRMExpressionLoaderPlugin`}constructor(e){this.parser=e}afterRoot(e){return kg(this,null,function*(){e.userData.vrmExpressionManager=yield this._import(e)})}_import(e){return kg(this,null,function*(){return(yield this._v1Import(e))||(yield this._v0Import(e))||null})}_v1Import(e){return kg(this,null,function*(){let t=this.parser.json;if(t.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let n=t.extensions?.VRMC_vrm;if(!n)return null;let r=n.specVersion;if(!Kg.has(r))return console.warn(`VRMExpressionLoaderPlugin: Unknown VRMC_vrm specVersion "${r}"`),null;let i=n.expressions;if(!i)return null;let a=new Set(Object.values(Pg)),o=new Map;i.preset!=null&&Object.entries(i.preset).forEach(([e,t])=>{if(t!=null){if(!a.has(e)){console.warn(`VRMExpressionLoaderPlugin: Unknown preset name "${e}" detected. Ignoring the expression`);return}o.set(e,t)}}),i.custom!=null&&Object.entries(i.custom).forEach(([e,t])=>{if(a.has(e)){console.warn(`VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${e}". Ignoring the expression`);return}o.set(e,t)});let s=new Ig;return yield Promise.all(Array.from(o.entries()).map(t=>kg(this,[t],function*([t,n]){var r,i,a;let o=new Ag(t);if(e.scene.add(o),o.isBinary=n.isBinary??!1,o.overrideBlink=n.overrideBlink??`none`,o.overrideLookAt=n.overrideLookAt??`none`,o.overrideMouth=n.overrideMouth??`none`,(r=n.morphTargetBinds)==null||r.forEach(t=>kg(this,null,function*(){if(t.node===void 0||t.index===void 0)return;let r=yield Mg(e,t.node),i=t.index;if(!r.every(e=>Array.isArray(e.morphTargetInfluences)&&i<e.morphTargetInfluences.length)){console.warn(`VRMExpressionLoaderPlugin: ${n.name} attempts to index morph #${i} but not found.`);return}o.addBind(new Hg({primitives:r,index:i,weight:t.weight??1}))})),n.materialColorBinds||n.textureTransformBinds){let t=[];e.scene.traverse(e=>{let n=e.material;n&&(Array.isArray(n)?t.push(...n):t.push(n))}),(i=n.materialColorBinds)==null||i.forEach(e=>kg(this,null,function*(){t.filter(t=>{let n=this.parser.associations.get(t)?.materials;return e.material===n}).forEach(t=>{o.addBind(new Vg({material:t,type:e.type,targetValue:new G().fromArray(e.targetValue),targetAlpha:e.targetValue[3]}))})})),(a=n.textureTransformBinds)==null||a.forEach(e=>kg(this,null,function*(){t.filter(t=>{let n=this.parser.associations.get(t)?.materials;return e.material===n}).forEach(t=>{o.addBind(new Gg({material:t,offset:new B().fromArray(e.offset??[0,0]),scale:new B().fromArray(e.scale??[1,1])}))})}))}s.registerExpression(o)}))),s})}_v0Import(t){return kg(this,null,function*(){let n=this.parser.json,r=n.extensions?.VRM;if(!r)return null;let i=r.blendShapeMaster;if(!i)return null;let a=new Ig,o=i.blendShapeGroups;if(!o)return a;let s=new Set;return yield Promise.all(o.map(r=>kg(this,null,function*(){let i=r.presetName,o=(i!=null&&e.v0v1PresetNameMap[i]||null)??r.name;if(o==null){console.warn(`VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression`);return}if(s.has(o)){console.warn(`VRMExpressionLoaderPlugin: An expression preset ${i} has duplicated entries. Ignoring the expression`);return}s.add(o);let c=new Ag(o);t.scene.add(c),c.isBinary=r.isBinary??!1,r.binds&&r.binds.forEach(e=>kg(this,null,function*(){var i;if(e.mesh===void 0||e.index===void 0)return;let a=[];(i=n.nodes)==null||i.forEach((t,n)=>{t.mesh===e.mesh&&a.push(n)});let o=e.index;yield Promise.all(a.map(n=>kg(this,null,function*(){let i=yield Mg(t,n);if(!i.every(e=>Array.isArray(e.morphTargetInfluences)&&o<e.morphTargetInfluences.length)){console.warn(`VRMExpressionLoaderPlugin: ${r.name} attempts to index ${o}th morph but not found.`);return}c.addBind(new Hg({primitives:i,index:o,weight:.01*(e.weight??100)}))})))}));let l=r.materialValues;l&&l.length!==0&&l.forEach(e=>{if(e.materialName===void 0||e.propertyName===void 0||e.targetValue===void 0)return;let n=[];t.scene.traverse(t=>{if(t.material){let r=t.material;Array.isArray(r)?n.push(...r.filter(t=>(t.name===e.materialName||t.name===e.materialName+` (Outline)`)&&n.indexOf(t)===-1)):r.name===e.materialName&&n.indexOf(r)===-1&&n.push(r)}});let r=e.propertyName;n.forEach(t=>{if(r===`_MainTex_ST`){let n=new B(e.targetValue[0],e.targetValue[1]),r=new B(e.targetValue[2],e.targetValue[3]);r.y=1-r.y-n.y,c.addBind(new Gg({material:t,scale:n,offset:r}));return}let n=Rg[r];if(n){c.addBind(new Vg({material:t,type:n,targetValue:new G().fromArray(e.targetValue),targetAlpha:e.targetValue[3]}));return}console.warn(r+` is not supported`)})}),a.registerExpression(c)}))),a})}};qg.v0v1PresetNameMap={a:`aa`,e:`ee`,i:`ih`,o:`oh`,u:`ou`,blink:`blink`,joy:`happy`,angry:`angry`,sorrow:`sad`,fun:`relaxed`,lookup:`lookUp`,lookdown:`lookDown`,lookleft:`lookLeft`,lookright:`lookRight`,blink_l:`blinkLeft`,blink_r:`blinkRight`,neutral:`neutral`};var Jg=qg,Yg=class e{constructor(t,n){this._firstPersonOnlyLayer=e.DEFAULT_FIRSTPERSON_ONLY_LAYER,this._thirdPersonOnlyLayer=e.DEFAULT_THIRDPERSON_ONLY_LAYER,this._initializedLayers=!1,this.humanoid=t,this.meshAnnotations=n}copy(e){if(this.humanoid!==e.humanoid)throw Error(`VRMFirstPerson: humanoid must be same in order to copy`);return this.meshAnnotations=e.meshAnnotations.map(e=>({meshes:e.meshes.concat(),type:e.type})),this}clone(){return new e(this.humanoid,this.meshAnnotations).copy(this)}get firstPersonOnlyLayer(){return this._firstPersonOnlyLayer}get thirdPersonOnlyLayer(){return this._thirdPersonOnlyLayer}setup({firstPersonOnlyLayer:t=e.DEFAULT_FIRSTPERSON_ONLY_LAYER,thirdPersonOnlyLayer:n=e.DEFAULT_THIRDPERSON_ONLY_LAYER}={}){this._initializedLayers||=(this._firstPersonOnlyLayer=t,this._thirdPersonOnlyLayer=n,this.meshAnnotations.forEach(e=>{e.meshes.forEach(t=>{e.type===`firstPersonOnly`?(t.layers.set(this._firstPersonOnlyLayer),t.traverse(e=>e.layers.set(this._firstPersonOnlyLayer))):e.type===`thirdPersonOnly`?(t.layers.set(this._thirdPersonOnlyLayer),t.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer))):e.type===`auto`&&this._createHeadlessModel(t)})}),!0)}_excludeTriangles(e,t,n,r){let i=0;if(t!=null&&t.length>0)for(let a=0;a<e.length;a+=3){let o=e[a],s=e[a+1],c=e[a+2],l=t[o],u=n[o];if(l[0]>0&&r.includes(u[0])||l[1]>0&&r.includes(u[1])||l[2]>0&&r.includes(u[2])||l[3]>0&&r.includes(u[3]))continue;let d=t[s],f=n[s];if(d[0]>0&&r.includes(f[0])||d[1]>0&&r.includes(f[1])||d[2]>0&&r.includes(f[2])||d[3]>0&&r.includes(f[3]))continue;let p=t[c],m=n[c];p[0]>0&&r.includes(m[0])||p[1]>0&&r.includes(m[1])||p[2]>0&&r.includes(m[2])||p[3]>0&&r.includes(m[3])||(e[i++]=o,e[i++]=s,e[i++]=c)}return i}_createErasedMesh(e,t){let n=new Uo(e.geometry.clone(),e.material);n.name=`${e.name}(erase)`,n.frustumCulled=e.frustumCulled,n.layers.set(this._firstPersonOnlyLayer);let r=n.geometry,i=r.getAttribute(`skinIndex`),a=i instanceof Dl?[]:i.array,o=[];for(let e=0;e<a.length;e+=4)o.push([a[e],a[e+1],a[e+2],a[e+3]]);let s=r.getAttribute(`skinWeight`),c=s instanceof Dl?[]:s.array,l=[];for(let e=0;e<c.length;e+=4)l.push([c[e],c[e+1],c[e+2],c[e+3]]);let u=r.getIndex();if(!u)throw Error(`The geometry doesn't have an index buffer`);let d=Array.from(u.array),f=this._excludeTriangles(d,l,o,t),p=[];for(let e=0;e<f;e++)p[e]=d[e];return r.setIndex(p),e.onBeforeRender&&(n.onBeforeRender=e.onBeforeRender),n.bind(new Jo(e.skeleton.bones,e.skeleton.boneInverses),new W),n}_createHeadlessModelForSkinnedMesh(e,t){let n=[];if(t.skeleton.bones.forEach((e,t)=>{this._isEraseTarget(e)&&n.push(t)}),!n.length){t.layers.enable(this._thirdPersonOnlyLayer),t.layers.enable(this._firstPersonOnlyLayer);return}t.layers.set(this._thirdPersonOnlyLayer);let r=this._createErasedMesh(t,n);e.add(r)}_createHeadlessModel(e){if(e.type===`Group`)if(e.layers.set(this._thirdPersonOnlyLayer),this._isEraseTarget(e))e.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer));else{let t=new Qi;t.name=`_headless_${e.name}`,t.layers.set(this._firstPersonOnlyLayer),e.parent.add(t),e.children.filter(e=>e.type===`SkinnedMesh`).forEach(e=>{let n=e;this._createHeadlessModelForSkinnedMesh(t,n)})}else if(e.type===`SkinnedMesh`){let t=e;this._createHeadlessModelForSkinnedMesh(e.parent,t)}else this._isEraseTarget(e)&&(e.layers.set(this._thirdPersonOnlyLayer),e.traverse(e=>e.layers.set(this._thirdPersonOnlyLayer)))}_isEraseTarget(e){return e===this.humanoid.getRawBoneNode(`head`)?!0:e.parent?this._isEraseTarget(e.parent):!1}};Yg.DEFAULT_FIRSTPERSON_ONLY_LAYER=9,Yg.DEFAULT_THIRDPERSON_ONLY_LAYER=10;var Xg=Yg,Zg=new Set([`1.0`,`1.0-beta`]),Qg=class{get name(){return`VRMFirstPersonLoaderPlugin`}constructor(e){this.parser=e}afterRoot(e){return kg(this,null,function*(){let t=e.userData.vrmHumanoid;if(t!==null){if(t===void 0)throw Error(`VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first`);e.userData.vrmFirstPerson=yield this._import(e,t)}})}_import(e,t){return kg(this,null,function*(){return t==null?null:(yield this._v1Import(e,t))||(yield this._v0Import(e,t))||null})}_v1Import(e,t){return kg(this,null,function*(){let n=this.parser.json;if(n.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let r=n.extensions?.VRMC_vrm;if(!r)return null;let i=r.specVersion;if(!Zg.has(i))return console.warn(`VRMFirstPersonLoaderPlugin: Unknown VRMC_vrm specVersion "${i}"`),null;let a=r.firstPerson,o=[],s=yield Ng(e);return Array.from(s.entries()).forEach(([e,t])=>{let n=(a?.meshAnnotations)?.find(t=>t.node===e);o.push({meshes:t,type:n?.type??`auto`})}),new Xg(t,o)})}_v0Import(e,t){return kg(this,null,function*(){let n=this.parser.json,r=n.extensions?.VRM;if(!r)return null;let i=r.firstPerson;if(!i)return null;let a=[],o=yield Ng(e);return Array.from(o.entries()).forEach(([e,t])=>{let r=n.nodes[e],o=i.meshAnnotations?i.meshAnnotations.find(e=>e.mesh===r.mesh):void 0;a.push({meshes:t,type:this._convertV0FlagToV1Type(o?.firstPersonFlag)})}),new Xg(t,a)})}_convertV0FlagToV1Type(e){return e===`FirstPersonOnly`?`firstPersonOnly`:e===`ThirdPersonOnly`?`thirdPersonOnly`:e===`Both`?`both`:`auto`}},$g=new H,e_=new H,t_=new V,n_=class extends Qi{constructor(e){super(),this.vrmHumanoid=e,this._boneAxesMap=new Map,Object.values(e.humanBones).forEach(e=>{let t=new Ml(1);t.matrixAutoUpdate=!1,t.material.depthTest=!1,t.material.depthWrite=!1,this.add(t),this._boneAxesMap.set(e,t)})}dispose(){Array.from(this._boneAxesMap.values()).forEach(e=>{e.geometry.dispose(),e.material.dispose()})}updateMatrixWorld(e){Array.from(this._boneAxesMap.entries()).forEach(([e,t])=>{e.node.updateWorldMatrix(!0,!1),e.node.matrixWorld.decompose($g,t_,e_);let n=$g.set(.1,.1,.1).divide(e_);t.matrix.copy(e.node.matrixWorld).scale(n)}),super.updateMatrixWorld(e)}},r_=`hips.spine.chest.upperChest.neck.head.leftEye.rightEye.jaw.leftUpperLeg.leftLowerLeg.leftFoot.leftToes.rightUpperLeg.rightLowerLeg.rightFoot.rightToes.leftShoulder.leftUpperArm.leftLowerArm.leftHand.rightShoulder.rightUpperArm.rightLowerArm.rightHand.leftThumbMetacarpal.leftThumbProximal.leftThumbDistal.leftIndexProximal.leftIndexIntermediate.leftIndexDistal.leftMiddleProximal.leftMiddleIntermediate.leftMiddleDistal.leftRingProximal.leftRingIntermediate.leftRingDistal.leftLittleProximal.leftLittleIntermediate.leftLittleDistal.rightThumbMetacarpal.rightThumbProximal.rightThumbDistal.rightIndexProximal.rightIndexIntermediate.rightIndexDistal.rightMiddleProximal.rightMiddleIntermediate.rightMiddleDistal.rightRingProximal.rightRingIntermediate.rightRingDistal.rightLittleProximal.rightLittleIntermediate.rightLittleDistal`.split(`.`),i_={hips:null,spine:`hips`,chest:`spine`,upperChest:`chest`,neck:`upperChest`,head:`neck`,leftEye:`head`,rightEye:`head`,jaw:`head`,leftUpperLeg:`hips`,leftLowerLeg:`leftUpperLeg`,leftFoot:`leftLowerLeg`,leftToes:`leftFoot`,rightUpperLeg:`hips`,rightLowerLeg:`rightUpperLeg`,rightFoot:`rightLowerLeg`,rightToes:`rightFoot`,leftShoulder:`upperChest`,leftUpperArm:`leftShoulder`,leftLowerArm:`leftUpperArm`,leftHand:`leftLowerArm`,rightShoulder:`upperChest`,rightUpperArm:`rightShoulder`,rightLowerArm:`rightUpperArm`,rightHand:`rightLowerArm`,leftThumbMetacarpal:`leftHand`,leftThumbProximal:`leftThumbMetacarpal`,leftThumbDistal:`leftThumbProximal`,leftIndexProximal:`leftHand`,leftIndexIntermediate:`leftIndexProximal`,leftIndexDistal:`leftIndexIntermediate`,leftMiddleProximal:`leftHand`,leftMiddleIntermediate:`leftMiddleProximal`,leftMiddleDistal:`leftMiddleIntermediate`,leftRingProximal:`leftHand`,leftRingIntermediate:`leftRingProximal`,leftRingDistal:`leftRingIntermediate`,leftLittleProximal:`leftHand`,leftLittleIntermediate:`leftLittleProximal`,leftLittleDistal:`leftLittleIntermediate`,rightThumbMetacarpal:`rightHand`,rightThumbProximal:`rightThumbMetacarpal`,rightThumbDistal:`rightThumbProximal`,rightIndexProximal:`rightHand`,rightIndexIntermediate:`rightIndexProximal`,rightIndexDistal:`rightIndexIntermediate`,rightMiddleProximal:`rightHand`,rightMiddleIntermediate:`rightMiddleProximal`,rightMiddleDistal:`rightMiddleIntermediate`,rightRingProximal:`rightHand`,rightRingIntermediate:`rightRingProximal`,rightRingDistal:`rightRingIntermediate`,rightLittleProximal:`rightHand`,rightLittleIntermediate:`rightLittleProximal`,rightLittleDistal:`rightLittleIntermediate`};function a_(e){return e.invert?e.invert():e.inverse(),e}var o_=new H,s_=new V,c_=class{constructor(e){this.humanBones=e,this.restPose=this.getAbsolutePose()}getAbsolutePose(){let e={};return Object.keys(this.humanBones).forEach(t=>{let n=t,r=this.getBoneNode(n);r&&(o_.copy(r.position),s_.copy(r.quaternion),e[n]={position:o_.toArray(),rotation:s_.toArray()})}),e}getPose(){let e={};return Object.keys(this.humanBones).forEach(t=>{let n=t,r=this.getBoneNode(n);if(!r)return;o_.set(0,0,0),s_.identity();let i=this.restPose[n];i?.position&&o_.fromArray(i.position).negate(),i?.rotation&&a_(s_.fromArray(i.rotation)),o_.add(r.position),s_.premultiply(r.quaternion),e[n]={position:o_.toArray(),rotation:s_.toArray()}}),e}setPose(e){Object.entries(e).forEach(([e,t])=>{let n=e,r=this.getBoneNode(n);if(!r)return;let i=this.restPose[n];i&&(t?.position&&(r.position.fromArray(t.position),i.position&&r.position.add(o_.fromArray(i.position))),t?.rotation&&(r.quaternion.fromArray(t.rotation),i.rotation&&r.quaternion.multiply(s_.fromArray(i.rotation))))})}resetPose(){Object.entries(this.restPose).forEach(([e,t])=>{let n=this.getBoneNode(e);n&&(t?.position&&n.position.fromArray(t.position),t?.rotation&&n.quaternion.fromArray(t.rotation))})}getBone(e){return this.humanBones[e]??void 0}getBoneNode(e){return this.humanBones[e]?.node??null}},l_=new H,u_=new V,d_=new H,f_=class e extends c_{static _setupTransforms(e){let t=new Zi;t.name=`VRMHumanoidRig`;let n={},r={},i={},a={};r_.forEach(t=>{var o;let s=e.getBoneNode(t);if(s){let e=new H,c=new V;s.updateWorldMatrix(!0,!1),s.matrixWorld.decompose(e,c,l_),n[t]=e,r[t]=c,i[t]=s.quaternion.clone();let l=new V;(o=s.parent)==null||o.matrixWorld.decompose(l_,l,l_),a[t]=l}});let o={};return r_.forEach(r=>{let i=e.getBoneNode(r);if(i){let e=n[r],a=r,s;for(;s==null&&(a=i_[a],a!=null);)s=n[a];let c=new Zi;c.name=`Normalized_`+i.name,(a?o[a]?.node:t).add(c),c.position.copy(e),s&&c.position.sub(s),o[r]={node:c}}}),{rigBones:o,root:t,parentWorldRotations:a,boneRotations:i}}constructor(t){let{rigBones:n,root:r,parentWorldRotations:i,boneRotations:a}=e._setupTransforms(t);super(n),this.original=t,this.root=r,this._parentWorldRotations=i,this._boneRotations=a}update(){r_.forEach(e=>{let t=this.original.getBoneNode(e);if(t!=null){let n=this.getBoneNode(e),r=this._parentWorldRotations[e],i=u_.copy(r).invert(),a=this._boneRotations[e];if(t.quaternion.copy(n.quaternion).multiply(r).premultiply(i).multiply(a),e===`hips`){let e=n.getWorldPosition(d_);t.parent.updateWorldMatrix(!0,!1);let r=t.parent.matrixWorld,i=e.applyMatrix4(r.invert());t.position.copy(i)}}})}},p_=class e{get restPose(){return console.warn(`VRMHumanoid: restPose is deprecated. Use either rawRestPose or normalizedRestPose instead.`),this.rawRestPose}get rawRestPose(){return this._rawHumanBones.restPose}get normalizedRestPose(){return this._normalizedHumanBones.restPose}get humanBones(){return this._rawHumanBones.humanBones}get rawHumanBones(){return this._rawHumanBones.humanBones}get normalizedHumanBones(){return this._normalizedHumanBones.humanBones}get normalizedHumanBonesRoot(){return this._normalizedHumanBones.root}constructor(e,t){this.autoUpdateHumanBones=t?.autoUpdateHumanBones??!0,this._rawHumanBones=new c_(e),this._normalizedHumanBones=new f_(this._rawHumanBones)}copy(e){return this.autoUpdateHumanBones=e.autoUpdateHumanBones,this._rawHumanBones=new c_(e.humanBones),this._normalizedHumanBones=new f_(this._rawHumanBones),this}clone(){return new e(this.humanBones,{autoUpdateHumanBones:this.autoUpdateHumanBones}).copy(this)}getAbsolutePose(){return console.warn(`VRMHumanoid: getAbsolutePose() is deprecated. Use either getRawAbsolutePose() or getNormalizedAbsolutePose() instead.`),this.getRawAbsolutePose()}getRawAbsolutePose(){return this._rawHumanBones.getAbsolutePose()}getNormalizedAbsolutePose(){return this._normalizedHumanBones.getAbsolutePose()}getPose(){return console.warn(`VRMHumanoid: getPose() is deprecated. Use either getRawPose() or getNormalizedPose() instead.`),this.getRawPose()}getRawPose(){return this._rawHumanBones.getPose()}getNormalizedPose(){return this._normalizedHumanBones.getPose()}setPose(e){return console.warn(`VRMHumanoid: setPose() is deprecated. Use either setRawPose() or setNormalizedPose() instead.`),this.setRawPose(e)}setRawPose(e){return this._rawHumanBones.setPose(e)}setNormalizedPose(e){return this._normalizedHumanBones.setPose(e)}resetPose(){return console.warn(`VRMHumanoid: resetPose() is deprecated. Use either resetRawPose() or resetNormalizedPose() instead.`),this.resetRawPose()}resetRawPose(){return this._rawHumanBones.resetPose()}resetNormalizedPose(){return this._normalizedHumanBones.resetPose()}getBone(e){return console.warn(`VRMHumanoid: getBone() is deprecated. Use either getRawBone() or getNormalizedBone() instead.`),this.getRawBone(e)}getRawBone(e){return this._rawHumanBones.getBone(e)}getNormalizedBone(e){return this._normalizedHumanBones.getBone(e)}getBoneNode(e){return console.warn(`VRMHumanoid: getBoneNode() is deprecated. Use either getRawBoneNode() or getNormalizedBoneNode() instead.`),this.getRawBoneNode(e)}getRawBoneNode(e){return this._rawHumanBones.getBoneNode(e)}getNormalizedBoneNode(e){return this._normalizedHumanBones.getBoneNode(e)}update(){this.autoUpdateHumanBones&&this._normalizedHumanBones.update()}},m_={Hips:`hips`,Spine:`spine`,Head:`head`,LeftUpperLeg:`leftUpperLeg`,LeftLowerLeg:`leftLowerLeg`,LeftFoot:`leftFoot`,RightUpperLeg:`rightUpperLeg`,RightLowerLeg:`rightLowerLeg`,RightFoot:`rightFoot`,LeftUpperArm:`leftUpperArm`,LeftLowerArm:`leftLowerArm`,LeftHand:`leftHand`,RightUpperArm:`rightUpperArm`,RightLowerArm:`rightLowerArm`,RightHand:`rightHand`},h_=new Set([`1.0`,`1.0-beta`]),g_={leftThumbProximal:`leftThumbMetacarpal`,leftThumbIntermediate:`leftThumbProximal`,rightThumbProximal:`rightThumbMetacarpal`,rightThumbIntermediate:`rightThumbProximal`},__=class{get name(){return`VRMHumanoidLoaderPlugin`}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot,this.autoUpdateHumanBones=t?.autoUpdateHumanBones}afterRoot(e){return kg(this,null,function*(){e.userData.vrmHumanoid=yield this._import(e)})}_import(e){return kg(this,null,function*(){return(yield this._v1Import(e))||(yield this._v0Import(e))||null})}_v1Import(e){return kg(this,null,function*(){let t=this.parser.json;if(t.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let n=t.extensions?.VRMC_vrm;if(!n)return null;let r=n.specVersion;if(!h_.has(r))return console.warn(`VRMHumanoidLoaderPlugin: Unknown VRMC_vrm specVersion "${r}"`),null;let i=n.humanoid;if(!i)return null;let a=i.humanBones.leftThumbIntermediate!=null||i.humanBones.rightThumbIntermediate!=null,o={};i.humanBones!=null&&(yield Promise.all(Object.entries(i.humanBones).map(e=>kg(this,[e],function*([e,t]){let n=e,r=t.node;if(a){let e=g_[n];e!=null&&(n=e)}let i=yield this.parser.getDependency(`node`,r);if(i==null){console.warn(`A glTF node bound to the humanoid bone ${n} (index = ${r}) does not exist`);return}o[n]={node:i}}))));let s=new p_(this._ensureRequiredBonesExist(o),{autoUpdateHumanBones:this.autoUpdateHumanBones});if(e.scene.add(s.normalizedHumanBonesRoot),this.helperRoot){let e=new n_(s);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return s})}_v0Import(e){return kg(this,null,function*(){let t=this.parser.json.extensions?.VRM;if(!t)return null;let n=t.humanoid;if(!n)return null;let r={};n.humanBones!=null&&(yield Promise.all(n.humanBones.map(e=>kg(this,null,function*(){let t=e.bone,n=e.node;if(t==null||n==null)return;let i=yield this.parser.getDependency(`node`,n);if(i==null){console.warn(`A glTF node bound to the humanoid bone ${t} (index = ${n}) does not exist`);return}let a=g_[t]??t;if(r[a]!=null){console.warn(`Multiple bone entries for ${a} detected (index = ${n}), ignoring duplicated entries.`);return}r[a]={node:i}}))));let i=new p_(this._ensureRequiredBonesExist(r),{autoUpdateHumanBones:this.autoUpdateHumanBones});if(e.scene.add(i.normalizedHumanBonesRoot),this.helperRoot){let e=new n_(i);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return i})}_ensureRequiredBonesExist(e){let t=Object.values(m_).filter(t=>e[t]==null);if(t.length>0)throw Error(`VRMHumanoidLoaderPlugin: These humanoid bones are required but not exist: ${t.join(`, `)}`);return e}},v_=class extends q{constructor(){super(),this._currentTheta=0,this._currentRadius=0,this.theta=0,this.radius=0,this._currentTheta=0,this._currentRadius=0,this._attrPos=new K(new Float32Array(195),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(189),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentTheta!==this.theta&&(this._currentTheta=this.theta,e=!0),this._currentRadius!==this.radius&&(this._currentRadius=this.radius,e=!0),e&&this._buildPosition()}_buildPosition(){this._attrPos.setXYZ(0,0,0,0);for(let e=0;e<64;e++){let t=e/63*this._currentTheta;this._attrPos.setXYZ(e+1,this._currentRadius*Math.sin(t),0,this._currentRadius*Math.cos(t))}this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<63;e++)this._attrIndex.setXYZ(e*3,0,e+1,e+2);this._attrIndex.needsUpdate=!0}},y_=class extends q{constructor(){super(),this.radius=0,this._currentRadius=0,this.tail=new H,this._currentTail=new H,this._attrPos=new K(new Float32Array(294),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(194),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentRadius!==this.radius&&(this._currentRadius=this.radius,e=!0),this._currentTail.equals(this.tail)||(this._currentTail.copy(this.tail),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.setXYZ(96,0,0,0),this._attrPos.setXYZ(97,this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.setXY(192,96,97),this._attrIndex.needsUpdate=!0}},b_=new V,x_=new V,S_=new H,C_=new H,w_=Math.sqrt(2)/2,T_=new V(0,0,-w_,w_),E_=new H(0,1,0),D_=class extends Qi{constructor(e){super(),this.matrixAutoUpdate=!1,this.vrmLookAt=e;{let e=new v_;e.radius=.5;let t=new yo({color:65280,transparent:!0,opacity:.5,side:2,depthTest:!1,depthWrite:!1});this._meshPitch=new jo(e,t),this.add(this._meshPitch)}{let e=new v_;e.radius=.5;let t=new yo({color:16711680,transparent:!0,opacity:.5,side:2,depthTest:!1,depthWrite:!1});this._meshYaw=new jo(e,t),this.add(this._meshYaw)}{let e=new y_;e.radius=.1;let t=new fs({color:16777215,depthTest:!1,depthWrite:!1});this._lineTarget=new ws(e,t),this._lineTarget.frustumCulled=!1,this.add(this._lineTarget)}}dispose(){this._meshYaw.geometry.dispose(),this._meshYaw.material.dispose(),this._meshPitch.geometry.dispose(),this._meshPitch.material.dispose(),this._lineTarget.geometry.dispose(),this._lineTarget.material.dispose()}updateMatrixWorld(e){let t=ni.DEG2RAD*this.vrmLookAt.yaw;this._meshYaw.geometry.theta=t,this._meshYaw.geometry.update();let n=ni.DEG2RAD*this.vrmLookAt.pitch;this._meshPitch.geometry.theta=n,this._meshPitch.geometry.update(),this.vrmLookAt.getLookAtWorldPosition(S_),this.vrmLookAt.getLookAtWorldQuaternion(b_),b_.multiply(this.vrmLookAt.getFaceFrontQuaternion(x_)),this._meshYaw.position.copy(S_),this._meshYaw.quaternion.copy(b_),this._meshPitch.position.copy(S_),this._meshPitch.quaternion.copy(b_),this._meshPitch.quaternion.multiply(x_.setFromAxisAngle(E_,t)),this._meshPitch.quaternion.multiply(T_);let{target:r,autoUpdate:i}=this.vrmLookAt;r!=null&&i&&(r.getWorldPosition(C_).sub(S_),this._lineTarget.geometry.tail.copy(C_),this._lineTarget.geometry.update(),this._lineTarget.position.copy(S_)),super.updateMatrixWorld(e)}},O_=new H,k_=new H;function A_(e,t){return e.matrixWorld.decompose(O_,t,k_),t}function j_(e){return[Math.atan2(-e.z,e.x),Math.atan2(e.y,Math.sqrt(e.x*e.x+e.z*e.z))]}function M_(e){let t=Math.round(e/2/Math.PI);return e-2*Math.PI*t}var N_=new H(0,0,1),P_=new H,F_=new H,I_=new H,L_=new V,R_=new V,z_=new V,B_=new V,V_=new Pi,H_=class e{constructor(e,t){this.offsetFromHeadBone=new H,this.autoUpdate=!0,this.faceFront=new H(0,0,1),this.humanoid=e,this.applier=t,this._yaw=0,this._pitch=0,this._needsUpdate=!0,this._restHeadWorldQuaternion=this.getLookAtWorldQuaternion(new V)}get yaw(){return this._yaw}set yaw(e){this._yaw=e,this._needsUpdate=!0}get pitch(){return this._pitch}set pitch(e){this._pitch=e,this._needsUpdate=!0}get euler(){return console.warn(`VRMLookAt: euler is deprecated. use getEuler() instead.`),this.getEuler(new Pi)}getEuler(e){return e.set(ni.DEG2RAD*this._pitch,ni.DEG2RAD*this._yaw,0,`YXZ`)}copy(e){if(this.humanoid!==e.humanoid)throw Error(`VRMLookAt: humanoid must be same in order to copy`);return this.offsetFromHeadBone.copy(e.offsetFromHeadBone),this.applier=e.applier,this.autoUpdate=e.autoUpdate,this.target=e.target,this.faceFront.copy(e.faceFront),this}clone(){return new e(this.humanoid,this.applier).copy(this)}reset(){this._yaw=0,this._pitch=0,this._needsUpdate=!0}getLookAtWorldPosition(e){let t=this.humanoid.getRawBoneNode(`head`);return e.copy(this.offsetFromHeadBone).applyMatrix4(t.matrixWorld)}getLookAtWorldQuaternion(e){return A_(this.humanoid.getRawBoneNode(`head`),e)}getFaceFrontQuaternion(e){if(this.faceFront.distanceToSquared(N_)<.01)return e.copy(this._restHeadWorldQuaternion).invert();let[t,n]=j_(this.faceFront);return V_.set(0,.5*Math.PI+t,n,`YZX`),e.setFromEuler(V_).premultiply(B_.copy(this._restHeadWorldQuaternion).invert())}getLookAtWorldDirection(e){return this.getLookAtWorldQuaternion(R_),this.getFaceFrontQuaternion(z_),e.copy(N_).applyQuaternion(R_).applyQuaternion(z_).applyEuler(this.getEuler(V_))}lookAt(e){let t=L_.copy(this._restHeadWorldQuaternion).multiply(a_(this.getLookAtWorldQuaternion(R_))),n=this.getLookAtWorldPosition(F_),r=I_.copy(e).sub(n).applyQuaternion(t).normalize(),[i,a]=j_(this.faceFront),[o,s]=j_(r),c=M_(o-i),l=M_(a-s);this._yaw=ni.RAD2DEG*c,this._pitch=ni.RAD2DEG*l,this._needsUpdate=!0}update(e){this.target!=null&&this.autoUpdate&&this.lookAt(this.target.getWorldPosition(P_)),this._needsUpdate&&(this._needsUpdate=!1,this.applier.applyYawPitch(this._yaw,this._pitch))}};H_.EULER_ORDER=`YXZ`;var U_=H_,W_=new H(0,0,1),G_=new V,K_=new V,q_=new Pi(0,0,0,`YXZ`),J_=class{constructor(e,t,n,r,i){this.humanoid=e,this.rangeMapHorizontalInner=t,this.rangeMapHorizontalOuter=n,this.rangeMapVerticalDown=r,this.rangeMapVerticalUp=i,this.faceFront=new H(0,0,1),this._restQuatLeftEye=new V,this._restQuatRightEye=new V,this._restLeftEyeParentWorldQuat=new V,this._restRightEyeParentWorldQuat=new V;let a=this.humanoid.getRawBoneNode(`leftEye`),o=this.humanoid.getRawBoneNode(`rightEye`);a&&(this._restQuatLeftEye.copy(a.quaternion),A_(a.parent,this._restLeftEyeParentWorldQuat)),o&&(this._restQuatRightEye.copy(o.quaternion),A_(o.parent,this._restRightEyeParentWorldQuat))}applyYawPitch(e,t){let n=this.humanoid.getRawBoneNode(`leftEye`),r=this.humanoid.getRawBoneNode(`rightEye`),i=this.humanoid.getNormalizedBoneNode(`leftEye`),a=this.humanoid.getNormalizedBoneNode(`rightEye`);n&&(t<0?q_.x=-ni.DEG2RAD*this.rangeMapVerticalDown.map(-t):q_.x=ni.DEG2RAD*this.rangeMapVerticalUp.map(t),e<0?q_.y=-ni.DEG2RAD*this.rangeMapHorizontalInner.map(-e):q_.y=ni.DEG2RAD*this.rangeMapHorizontalOuter.map(e),G_.setFromEuler(q_),this._getWorldFaceFrontQuat(K_),i.quaternion.copy(K_).multiply(G_).multiply(K_.invert()),G_.copy(this._restLeftEyeParentWorldQuat),n.quaternion.copy(i.quaternion).multiply(G_).premultiply(G_.invert()).multiply(this._restQuatLeftEye)),r&&(t<0?q_.x=-ni.DEG2RAD*this.rangeMapVerticalDown.map(-t):q_.x=ni.DEG2RAD*this.rangeMapVerticalUp.map(t),e<0?q_.y=-ni.DEG2RAD*this.rangeMapHorizontalOuter.map(-e):q_.y=ni.DEG2RAD*this.rangeMapHorizontalInner.map(e),G_.setFromEuler(q_),this._getWorldFaceFrontQuat(K_),a.quaternion.copy(K_).multiply(G_).multiply(K_.invert()),G_.copy(this._restRightEyeParentWorldQuat),r.quaternion.copy(a.quaternion).multiply(G_).premultiply(G_.invert()).multiply(this._restQuatRightEye))}lookAt(e){console.warn(`VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.`);let t=ni.RAD2DEG*e.y,n=ni.RAD2DEG*e.x;this.applyYawPitch(t,n)}_getWorldFaceFrontQuat(e){if(this.faceFront.distanceToSquared(W_)<.01)return e.identity();let[t,n]=j_(this.faceFront);return q_.set(0,.5*Math.PI+t,n,`YZX`),e.setFromEuler(q_)}};J_.type=`bone`;var Y_=class{constructor(e,t,n,r,i){this.expressions=e,this.rangeMapHorizontalInner=t,this.rangeMapHorizontalOuter=n,this.rangeMapVerticalDown=r,this.rangeMapVerticalUp=i}applyYawPitch(e,t){t<0?(this.expressions.setValue(`lookDown`,0),this.expressions.setValue(`lookUp`,this.rangeMapVerticalUp.map(-t))):(this.expressions.setValue(`lookUp`,0),this.expressions.setValue(`lookDown`,this.rangeMapVerticalDown.map(t))),e<0?(this.expressions.setValue(`lookLeft`,0),this.expressions.setValue(`lookRight`,this.rangeMapHorizontalOuter.map(-e))):(this.expressions.setValue(`lookRight`,0),this.expressions.setValue(`lookLeft`,this.rangeMapHorizontalOuter.map(e)))}lookAt(e){console.warn(`VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.`);let t=ni.RAD2DEG*e.y,n=ni.RAD2DEG*e.x;this.applyYawPitch(t,n)}};Y_.type=`expression`;var X_=class{constructor(e,t){this.inputMaxValue=e,this.outputScale=t}map(e){return this.outputScale*Fg(e/this.inputMaxValue)}},Z_=new Set([`1.0`,`1.0-beta`]),Q_=.01,$_=class{get name(){return`VRMLookAtLoaderPlugin`}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot}afterRoot(e){return kg(this,null,function*(){let t=e.userData.vrmHumanoid;if(t===null)return;if(t===void 0)throw Error(`VRMLookAtLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first`);let n=e.userData.vrmExpressionManager;if(n!==null){if(n===void 0)throw Error(`VRMLookAtLoaderPlugin: vrmExpressionManager is undefined. VRMExpressionLoaderPlugin have to be used first`);e.userData.vrmLookAt=yield this._import(e,t,n)}})}_import(e,t,n){return kg(this,null,function*(){return t==null||n==null?null:(yield this._v1Import(e,t,n))||(yield this._v0Import(e,t,n))||null})}_v1Import(e,t,n){return kg(this,null,function*(){let e=this.parser.json;if(e.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let r=e.extensions?.VRMC_vrm;if(!r)return null;let i=r.specVersion;if(!Z_.has(i))return console.warn(`VRMLookAtLoaderPlugin: Unknown VRMC_vrm specVersion "${i}"`),null;let a=r.lookAt;if(!a)return null;let o=a.type===`expression`?1:10,s=this._v1ImportRangeMap(a.rangeMapHorizontalInner,o),c=this._v1ImportRangeMap(a.rangeMapHorizontalOuter,o),l=this._v1ImportRangeMap(a.rangeMapVerticalDown,o),u=this._v1ImportRangeMap(a.rangeMapVerticalUp,o),d;d=a.type===`expression`?new Y_(n,s,c,l,u):new J_(t,s,c,l,u);let f=this._importLookAt(t,d);return f.offsetFromHeadBone.fromArray(a.offsetFromHeadBone??[0,.06,0]),f})}_v1ImportRangeMap(e,t){let n=e?.inputMaxValue??90,r=e?.outputScale??t;return n<Q_&&(console.warn(`VRMLookAtLoaderPlugin: inputMaxValue of a range map is too small. Consider reviewing the range map!`),n=Q_),new X_(n,r)}_v0Import(e,t,n){return kg(this,null,function*(){let e=this.parser.json.extensions?.VRM;if(!e)return null;let r=e.firstPerson;if(!r)return null;let i=r.lookAtTypeName===`BlendShape`?1:10,a=this._v0ImportDegreeMap(r.lookAtHorizontalInner,i),o=this._v0ImportDegreeMap(r.lookAtHorizontalOuter,i),s=this._v0ImportDegreeMap(r.lookAtVerticalDown,i),c=this._v0ImportDegreeMap(r.lookAtVerticalUp,i),l;l=r.lookAtTypeName===`BlendShape`?new Y_(n,a,o,s,c):new J_(t,a,o,s,c);let u=this._importLookAt(t,l);return r.firstPersonBoneOffset?u.offsetFromHeadBone.set(r.firstPersonBoneOffset.x??0,r.firstPersonBoneOffset.y??.06,-(r.firstPersonBoneOffset.z??0)):u.offsetFromHeadBone.set(0,.06,0),u.faceFront.set(0,0,-1),l instanceof J_&&l.faceFront.set(0,0,-1),u})}_v0ImportDegreeMap(e,t){let n=e?.curve;JSON.stringify(n)!==`[0,0,0,1,1,1,1,0]`&&console.warn(`Curves of LookAtDegreeMap defined in VRM 0.0 are not supported`);let r=e?.xRange??90,i=e?.yRange??t;return r<Q_&&(console.warn(`VRMLookAtLoaderPlugin: xRange of a degree map is too small. Consider reviewing the degree map!`),r=Q_),new X_(r,i)}_importLookAt(e,t){let n=new U_(e,t);if(this.helperRoot){let e=new D_(n);this.helperRoot.add(e),e.renderOrder=this.helperRoot.renderOrder}return n}};function ev(e,t){return typeof e!=`string`||e===``?``:(/^https?:\/\//i.test(t)&&/^\//.test(e)&&(t=t.replace(/(^https?:\/\/[^/]+).*/i,`$1`)),/^(https?:)?\/\//i.test(e)||/^data:.*,.*$/i.test(e)||/^blob:.*$/i.test(e)?e:t+e)}var tv=new Set([`1.0`,`1.0-beta`]),nv=class{get name(){return`VRMMetaLoaderPlugin`}constructor(e,t){this.parser=e,this.needThumbnailImage=t?.needThumbnailImage??!1,this.acceptLicenseUrls=t?.acceptLicenseUrls??[`https://vrm.dev/licenses/1.0/`],this.acceptV0Meta=t?.acceptV0Meta??!0}afterRoot(e){return kg(this,null,function*(){e.userData.vrmMeta=yield this._import(e)})}_import(e){return kg(this,null,function*(){return(yield this._v1Import(e))??(yield this._v0Import(e))??null})}_v1Import(e){return kg(this,null,function*(){let e=this.parser.json;if(e.extensionsUsed?.indexOf(`VRMC_vrm`)===-1)return null;let t=e.extensions?.VRMC_vrm;if(t==null)return null;let n=t.specVersion;if(!tv.has(n))return console.warn(`VRMMetaLoaderPlugin: Unknown VRMC_vrm specVersion "${n}"`),null;let r=t.meta;if(!r)return null;let i=r.licenseUrl;if(!new Set(this.acceptLicenseUrls).has(i))throw Error(`VRMMetaLoaderPlugin: The license url "${i}" is not accepted`);let a;return this.needThumbnailImage&&r.thumbnailImage!=null&&(a=(yield this._extractGLTFImage(r.thumbnailImage))??void 0),{metaVersion:`1`,name:r.name,version:r.version,authors:r.authors,copyrightInformation:r.copyrightInformation,contactInformation:r.contactInformation,references:r.references,thirdPartyLicenses:r.thirdPartyLicenses,thumbnailImage:a,licenseUrl:r.licenseUrl,avatarPermission:r.avatarPermission,allowExcessivelyViolentUsage:r.allowExcessivelyViolentUsage,allowExcessivelySexualUsage:r.allowExcessivelySexualUsage,commercialUsage:r.commercialUsage,allowPoliticalOrReligiousUsage:r.allowPoliticalOrReligiousUsage,allowAntisocialOrHateUsage:r.allowAntisocialOrHateUsage,creditNotation:r.creditNotation,allowRedistribution:r.allowRedistribution,modification:r.modification,otherLicenseUrl:r.otherLicenseUrl}})}_v0Import(e){return kg(this,null,function*(){let e=this.parser.json.extensions?.VRM;if(!e)return null;let t=e.meta;if(!t)return null;if(!this.acceptV0Meta)throw Error(`VRMMetaLoaderPlugin: Attempted to load VRM0.0 meta but acceptV0Meta is false`);let n;return this.needThumbnailImage&&t.texture!=null&&t.texture!==-1&&(n=yield this.parser.getDependency(`texture`,t.texture)),{metaVersion:`0`,allowedUserName:t.allowedUserName,author:t.author,commercialUssageName:t.commercialUssageName,contactInformation:t.contactInformation,licenseName:t.licenseName,otherLicenseUrl:t.otherLicenseUrl,otherPermissionUrl:t.otherPermissionUrl,reference:t.reference,sexualUssageName:t.sexualUssageName,texture:n??void 0,title:t.title,version:t.version,violentUssageName:t.violentUssageName}})}_extractGLTFImage(e){return kg(this,null,function*(){let t=this.parser.json.images?.[e];if(t==null)return console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${e}] of glTF as a thumbnail but the image doesn't exist`),null;let n=t.uri;if(t.bufferView!=null){let e=yield this.parser.getDependency(`bufferView`,t.bufferView),r=new Blob([e],{type:t.mimeType});n=URL.createObjectURL(r)}return n==null?(console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${e}] of glTF as a thumbnail but the image couldn't load properly`),null):yield new Pc().loadAsync(ev(n,this.parser.options.path)).catch(e=>(console.error(e),console.warn(`VRMMetaLoaderPlugin: Failed to load a thumbnail image`),null))})}},rv=class{constructor(e){this.scene=e.scene,this.meta=e.meta,this.humanoid=e.humanoid,this.expressionManager=e.expressionManager,this.firstPerson=e.firstPerson,this.lookAt=e.lookAt}update(e){this.humanoid.update(),this.lookAt&&this.lookAt.update(e),this.expressionManager&&this.expressionManager.update()}},iv=class extends rv{constructor(e){super(e),this.materials=e.materials,this.springBoneManager=e.springBoneManager,this.nodeConstraintManager=e.nodeConstraintManager}update(e){super.update(e),this.nodeConstraintManager&&this.nodeConstraintManager.update(),this.springBoneManager&&this.springBoneManager.update(e),this.materials&&this.materials.forEach(t=>{t.update&&t.update(e)})}},av=Object.defineProperty,ov=Object.getOwnPropertySymbols,sv=Object.prototype.hasOwnProperty,cv=Object.prototype.propertyIsEnumerable,lv=(e,t,n)=>t in e?av(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,uv=(e,t)=>{for(var n in t||={})sv.call(t,n)&&lv(e,n,t[n]);if(ov)for(var n of ov(t))cv.call(t,n)&&lv(e,n,t[n]);return e},dv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())});function fv(e,t){e.colorSpace=t}var pv=class{get pending(){return Promise.all(this._pendings)}constructor(e,t){this._parser=e,this._materialParams=t,this._pendings=[]}assignPrimitive(e,t){t!=null&&(this._materialParams[e]=t)}assignColor(e,t,n){if(t!=null){let r=new G().fromArray(t);n&&r.convertSRGBToLinear(),this._materialParams[e]=r}}assignTexture(e,t,n){return dv(this,null,function*(){let r=dv(this,null,function*(){if(t!=null){let r=yield this._parser.assignTexture(this._materialParams,e,t);if(r==null){console.warn(`GLTFMToonMaterialParamsAssignHelper: Failed to load texture. The rendering result may be wrong`);return}n&&fv(r,`srgb`)}});return this._pendings.push(r),r})}assignTextureByIndex(e,t,n){return dv(this,null,function*(){return this.assignTexture(e,t==null?void 0:{index:t},n)})}},mv=`// #define PHONG
|
|
5678
5707
|
|
|
5679
5708
|
varying vec3 vViewPosition;
|
|
5680
5709
|
|
|
@@ -5792,7 +5821,7 @@ void main() {
|
|
|
5792
5821
|
#include <shadowmap_vertex>
|
|
5793
5822
|
#include <fog_vertex>
|
|
5794
5823
|
|
|
5795
|
-
}`,
|
|
5824
|
+
}`,hv=`// #define PHONG
|
|
5796
5825
|
|
|
5797
5826
|
uniform vec3 litFactor;
|
|
5798
5827
|
|
|
@@ -6605,17 +6634,17 @@ void main() {
|
|
|
6605
6634
|
gl_FragColor = vec4( col, diffuseColor.a );
|
|
6606
6635
|
postCorrection();
|
|
6607
6636
|
}
|
|
6608
|
-
`,
|
|
6637
|
+
`,gv={None:`none`,Normal:`normal`,LitShadeRate:`litShadeRate`,UV:`uv`},_v={None:`none`,WorldCoordinates:`worldCoordinates`,ScreenCoordinates:`screenCoordinates`};function vv(e){return e.colorSpace}var yv=class extends ec{constructor(e={}){super({vertexShader:mv,fragmentShader:hv}),this.uvAnimationScrollXSpeedFactor=0,this.uvAnimationScrollYSpeedFactor=0,this.uvAnimationRotationSpeedFactor=0,this.fog=!0,this.normalMapType=0,this._ignoreVertexColor=!0,this._v0CompatShade=!1,this._debugMode=gv.None,this._outlineWidthMode=_v.None,this._isOutline=!1,e.transparentWithZWrite&&(e.depthWrite=!0),delete e.transparentWithZWrite,e.fog=!0,e.lights=!0,e.clipping=!0,this.uniforms=Zs.merge([Y.common,Y.normalmap,Y.emissivemap,Y.fog,Y.lights,{litFactor:{value:new G(1,1,1)},mapUvTransform:{value:new U},colorAlpha:{value:1},normalMapUvTransform:{value:new U},shadeColorFactor:{value:new G(0,0,0)},shadeMultiplyTexture:{value:null},shadeMultiplyTextureUvTransform:{value:new U},shadingShiftFactor:{value:0},shadingShiftTexture:{value:null},shadingShiftTextureUvTransform:{value:new U},shadingShiftTextureScale:{value:1},shadingToonyFactor:{value:.9},giEqualizationFactor:{value:.9},matcapFactor:{value:new G(1,1,1)},matcapTexture:{value:null},matcapTextureUvTransform:{value:new U},parametricRimColorFactor:{value:new G(0,0,0)},rimMultiplyTexture:{value:null},rimMultiplyTextureUvTransform:{value:new U},rimLightingMixFactor:{value:1},parametricRimFresnelPowerFactor:{value:5},parametricRimLiftFactor:{value:0},emissive:{value:new G(0,0,0)},emissiveIntensity:{value:1},emissiveMapUvTransform:{value:new U},outlineWidthMultiplyTexture:{value:null},outlineWidthMultiplyTextureUvTransform:{value:new U},outlineWidthFactor:{value:0},outlineColorFactor:{value:new G(0,0,0)},outlineLightingMixFactor:{value:1},uvAnimationMaskTexture:{value:null},uvAnimationMaskTextureUvTransform:{value:new U},uvAnimationScrollXOffset:{value:0},uvAnimationScrollYOffset:{value:0},uvAnimationRotationPhase:{value:0}},e.uniforms??{}]),this.setValues(e),this._uploadUniformsWorkaround(),this.customProgramCacheKey=()=>[...Object.entries(this._generateDefines()).map(([e,t])=>`${e}:${t}`),this.matcapTexture?`matcapTextureColorSpace:${vv(this.matcapTexture)}`:``,this.shadeMultiplyTexture?`shadeMultiplyTextureColorSpace:${vv(this.shadeMultiplyTexture)}`:``,this.rimMultiplyTexture?`rimMultiplyTextureColorSpace:${vv(this.rimMultiplyTexture)}`:``].join(`,`),this.onBeforeCompile=e=>{let t=Object.entries(uv(uv({},this._generateDefines()),this.defines)).filter(([e,t])=>!!t).map(([e,t])=>`#define ${e} ${t}`).join(`
|
|
6609
6638
|
`)+`
|
|
6610
|
-
`;e.vertexShader=t+e.vertexShader,e.fragmentShader=t+e.fragmentShader}}get color(){return this.uniforms.litFactor.value}set color(e){this.uniforms.litFactor.value=e}get map(){return this.uniforms.map.value}set map(e){this.uniforms.map.value=e}get normalMap(){return this.uniforms.normalMap.value}set normalMap(e){this.uniforms.normalMap.value=e}get normalScale(){return this.uniforms.normalScale.value}set normalScale(e){this.uniforms.normalScale.value=e}get emissive(){return this.uniforms.emissive.value}set emissive(e){this.uniforms.emissive.value=e}get emissiveIntensity(){return this.uniforms.emissiveIntensity.value}set emissiveIntensity(e){this.uniforms.emissiveIntensity.value=e}get emissiveMap(){return this.uniforms.emissiveMap.value}set emissiveMap(e){this.uniforms.emissiveMap.value=e}get shadeColorFactor(){return this.uniforms.shadeColorFactor.value}set shadeColorFactor(e){this.uniforms.shadeColorFactor.value=e}get shadeMultiplyTexture(){return this.uniforms.shadeMultiplyTexture.value}set shadeMultiplyTexture(e){this.uniforms.shadeMultiplyTexture.value=e}get shadingShiftFactor(){return this.uniforms.shadingShiftFactor.value}set shadingShiftFactor(e){this.uniforms.shadingShiftFactor.value=e}get shadingShiftTexture(){return this.uniforms.shadingShiftTexture.value}set shadingShiftTexture(e){this.uniforms.shadingShiftTexture.value=e}get shadingShiftTextureScale(){return this.uniforms.shadingShiftTextureScale.value}set shadingShiftTextureScale(e){this.uniforms.shadingShiftTextureScale.value=e}get shadingToonyFactor(){return this.uniforms.shadingToonyFactor.value}set shadingToonyFactor(e){this.uniforms.shadingToonyFactor.value=e}get giEqualizationFactor(){return this.uniforms.giEqualizationFactor.value}set giEqualizationFactor(e){this.uniforms.giEqualizationFactor.value=e}get matcapFactor(){return this.uniforms.matcapFactor.value}set matcapFactor(e){this.uniforms.matcapFactor.value=e}get matcapTexture(){return this.uniforms.matcapTexture.value}set matcapTexture(e){this.uniforms.matcapTexture.value=e}get parametricRimColorFactor(){return this.uniforms.parametricRimColorFactor.value}set parametricRimColorFactor(e){this.uniforms.parametricRimColorFactor.value=e}get rimMultiplyTexture(){return this.uniforms.rimMultiplyTexture.value}set rimMultiplyTexture(e){this.uniforms.rimMultiplyTexture.value=e}get rimLightingMixFactor(){return this.uniforms.rimLightingMixFactor.value}set rimLightingMixFactor(e){this.uniforms.rimLightingMixFactor.value=e}get parametricRimFresnelPowerFactor(){return this.uniforms.parametricRimFresnelPowerFactor.value}set parametricRimFresnelPowerFactor(e){this.uniforms.parametricRimFresnelPowerFactor.value=e}get parametricRimLiftFactor(){return this.uniforms.parametricRimLiftFactor.value}set parametricRimLiftFactor(e){this.uniforms.parametricRimLiftFactor.value=e}get outlineWidthMultiplyTexture(){return this.uniforms.outlineWidthMultiplyTexture.value}set outlineWidthMultiplyTexture(e){this.uniforms.outlineWidthMultiplyTexture.value=e}get outlineWidthFactor(){return this.uniforms.outlineWidthFactor.value}set outlineWidthFactor(e){this.uniforms.outlineWidthFactor.value=e}get outlineColorFactor(){return this.uniforms.outlineColorFactor.value}set outlineColorFactor(e){this.uniforms.outlineColorFactor.value=e}get outlineLightingMixFactor(){return this.uniforms.outlineLightingMixFactor.value}set outlineLightingMixFactor(e){this.uniforms.outlineLightingMixFactor.value=e}get uvAnimationMaskTexture(){return this.uniforms.uvAnimationMaskTexture.value}set uvAnimationMaskTexture(e){this.uniforms.uvAnimationMaskTexture.value=e}get uvAnimationScrollXOffset(){return this.uniforms.uvAnimationScrollXOffset.value}set uvAnimationScrollXOffset(e){this.uniforms.uvAnimationScrollXOffset.value=e}get uvAnimationScrollYOffset(){return this.uniforms.uvAnimationScrollYOffset.value}set uvAnimationScrollYOffset(e){this.uniforms.uvAnimationScrollYOffset.value=e}get uvAnimationRotationPhase(){return this.uniforms.uvAnimationRotationPhase.value}set uvAnimationRotationPhase(e){this.uniforms.uvAnimationRotationPhase.value=e}get ignoreVertexColor(){return this._ignoreVertexColor}set ignoreVertexColor(e){this._ignoreVertexColor=e,this.needsUpdate=!0}get v0CompatShade(){return this._v0CompatShade}set v0CompatShade(e){this._v0CompatShade=e,this.needsUpdate=!0}get debugMode(){return this._debugMode}set debugMode(e){this._debugMode=e,this.needsUpdate=!0}get outlineWidthMode(){return this._outlineWidthMode}set outlineWidthMode(e){this._outlineWidthMode=e,this.needsUpdate=!0}get isOutline(){return this._isOutline}set isOutline(e){this._isOutline=e,this.needsUpdate=!0}get isMToonMaterial(){return!0}update(e){this._uploadUniformsWorkaround(),this._updateUVAnimation(e)}copy(e){return super.copy(e),this.map=e.map,this.normalMap=e.normalMap,this.emissiveMap=e.emissiveMap,this.shadeMultiplyTexture=e.shadeMultiplyTexture,this.shadingShiftTexture=e.shadingShiftTexture,this.matcapTexture=e.matcapTexture,this.rimMultiplyTexture=e.rimMultiplyTexture,this.outlineWidthMultiplyTexture=e.outlineWidthMultiplyTexture,this.uvAnimationMaskTexture=e.uvAnimationMaskTexture,this.normalMapType=e.normalMapType,this.uvAnimationScrollXSpeedFactor=e.uvAnimationScrollXSpeedFactor,this.uvAnimationScrollYSpeedFactor=e.uvAnimationScrollYSpeedFactor,this.uvAnimationRotationSpeedFactor=e.uvAnimationRotationSpeedFactor,this.ignoreVertexColor=e.ignoreVertexColor,this.v0CompatShade=e.v0CompatShade,this.debugMode=e.debugMode,this.outlineWidthMode=e.outlineWidthMode,this.isOutline=e.isOutline,this.needsUpdate=!0,this}_updateUVAnimation(e){this.uniforms.uvAnimationScrollXOffset.value+=e*this.uvAnimationScrollXSpeedFactor,this.uniforms.uvAnimationScrollYOffset.value+=e*this.uvAnimationScrollYSpeedFactor,this.uniforms.uvAnimationRotationPhase.value+=e*this.uvAnimationRotationSpeedFactor,this.uniforms.alphaTest.value=this.alphaTest,this.uniformsNeedUpdate=!0}_uploadUniformsWorkaround(){this.uniforms.opacity.value=this.opacity,this._updateTextureMatrix(this.uniforms.map,this.uniforms.mapUvTransform),this._updateTextureMatrix(this.uniforms.normalMap,this.uniforms.normalMapUvTransform),this._updateTextureMatrix(this.uniforms.emissiveMap,this.uniforms.emissiveMapUvTransform),this._updateTextureMatrix(this.uniforms.shadeMultiplyTexture,this.uniforms.shadeMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.shadingShiftTexture,this.uniforms.shadingShiftTextureUvTransform),this._updateTextureMatrix(this.uniforms.matcapTexture,this.uniforms.matcapTextureUvTransform),this._updateTextureMatrix(this.uniforms.rimMultiplyTexture,this.uniforms.rimMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.outlineWidthMultiplyTexture,this.uniforms.outlineWidthMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.uvAnimationMaskTexture,this.uniforms.uvAnimationMaskTextureUvTransform),this.uniformsNeedUpdate=!0}_generateDefines(){let e=this.outlineWidthMultiplyTexture!==null,t=this.map!==null||this.normalMap!==null||this.emissiveMap!==null||this.shadeMultiplyTexture!==null||this.shadingShiftTexture!==null||this.rimMultiplyTexture!==null||this.uvAnimationMaskTexture!==null;return{THREE_VRM_THREE_REVISION:184,OUTLINE:this._isOutline,MTOON_USE_UV:e||t,MTOON_UVS_VERTEX_ONLY:e&&!t,V0_COMPAT_SHADE:this._v0CompatShade,USE_SHADEMULTIPLYTEXTURE:this.shadeMultiplyTexture!==null,USE_SHADINGSHIFTTEXTURE:this.shadingShiftTexture!==null,USE_MATCAPTEXTURE:this.matcapTexture!==null,USE_RIMMULTIPLYTEXTURE:this.rimMultiplyTexture!==null,USE_OUTLINEWIDTHMULTIPLYTEXTURE:this._isOutline&&this.outlineWidthMultiplyTexture!==null,USE_UVANIMATIONMASKTEXTURE:this.uvAnimationMaskTexture!==null,IGNORE_VERTEX_COLOR:this._ignoreVertexColor===!0,DEBUG_NORMAL:this._debugMode===`normal`,DEBUG_LITSHADERATE:this._debugMode===`litShadeRate`,DEBUG_UV:this._debugMode===`uv`,OUTLINE_WIDTH_SCREEN:this._isOutline&&this._outlineWidthMode===sv.ScreenCoordinates}}_updateTextureMatrix(e,t){e.value&&(e.value.matrixAutoUpdate&&e.value.updateMatrix(),t.value.copy(e.value.matrix))}},uv=new Set([`1.0`,`1.0-beta`]),dv=class e{get name(){return e.EXTENSION_NAME}constructor(e,t={}){this.parser=e,this.materialType=t.materialType??lv,this.renderOrderOffset=t.renderOrderOffset??0,this.v0CompatShade=t.v0CompatShade??!1,this.debugMode=t.debugMode??`none`,this._mToonMaterialSet=new Set}beforeRoot(){return tv(this,null,function*(){this._removeUnlitExtensionIfMToonExists()})}afterRoot(e){return tv(this,null,function*(){e.userData.vrmMToonMaterials=Array.from(this._mToonMaterialSet)})}getMaterialType(e){return this._getMToonExtension(e)?this.materialType:null}extendMaterialParams(e,t){let n=this._getMToonExtension(e);return n?this._extendMaterialParams(n,t):null}loadMesh(e){return tv(this,null,function*(){let t=this.parser,n=t.json.meshes?.[e];if(n==null)throw Error(`MToonMaterialLoaderPlugin: Attempt to use meshes[${e}] of glTF but the mesh doesn't exist`);let r=n.primitives,i=yield t.loadMesh(e);if(r.length===1){let e=i,t=r[0].material;t!=null&&this._setupPrimitive(e,t)}else{let e=i;for(let t=0;t<r.length;t++){let n=e.children[t],i=r[t].material;i!=null&&this._setupPrimitive(n,i)}}return i})}_removeUnlitExtensionIfMToonExists(){this.parser.json.materials?.map((e,t)=>{this._getMToonExtension(t)&&e.extensions?.KHR_materials_unlit&&delete e.extensions.KHR_materials_unlit})}_getMToonExtension(t){let n=this.parser.json.materials?.[t];if(n==null){console.warn(`MToonMaterialLoaderPlugin: Attempt to use materials[${t}] of glTF but the material doesn't exist`);return}let r=n.extensions?.[e.EXTENSION_NAME];if(r==null)return;let i=r.specVersion;if(!uv.has(i)){console.warn(`MToonMaterialLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${i}"`);return}return r}_extendMaterialParams(e,t){return tv(this,null,function*(){delete t.metalness,delete t.roughness;let n=new rv(this.parser,t);n.assignPrimitive(`transparentWithZWrite`,e.transparentWithZWrite),n.assignColor(`shadeColorFactor`,e.shadeColorFactor),n.assignTexture(`shadeMultiplyTexture`,e.shadeMultiplyTexture,!0),n.assignPrimitive(`shadingShiftFactor`,e.shadingShiftFactor),n.assignTexture(`shadingShiftTexture`,e.shadingShiftTexture,!0),n.assignPrimitive(`shadingShiftTextureScale`,e.shadingShiftTexture?.scale),n.assignPrimitive(`shadingToonyFactor`,e.shadingToonyFactor),n.assignPrimitive(`giEqualizationFactor`,e.giEqualizationFactor),n.assignColor(`matcapFactor`,e.matcapFactor),n.assignTexture(`matcapTexture`,e.matcapTexture,!0),n.assignColor(`parametricRimColorFactor`,e.parametricRimColorFactor),n.assignTexture(`rimMultiplyTexture`,e.rimMultiplyTexture,!0),n.assignPrimitive(`rimLightingMixFactor`,e.rimLightingMixFactor),n.assignPrimitive(`parametricRimFresnelPowerFactor`,e.parametricRimFresnelPowerFactor),n.assignPrimitive(`parametricRimLiftFactor`,e.parametricRimLiftFactor),n.assignPrimitive(`outlineWidthMode`,e.outlineWidthMode),n.assignPrimitive(`outlineWidthFactor`,e.outlineWidthFactor),n.assignTexture(`outlineWidthMultiplyTexture`,e.outlineWidthMultiplyTexture,!1),n.assignColor(`outlineColorFactor`,e.outlineColorFactor),n.assignPrimitive(`outlineLightingMixFactor`,e.outlineLightingMixFactor),n.assignTexture(`uvAnimationMaskTexture`,e.uvAnimationMaskTexture,!1),n.assignPrimitive(`uvAnimationScrollXSpeedFactor`,e.uvAnimationScrollXSpeedFactor),n.assignPrimitive(`uvAnimationScrollYSpeedFactor`,e.uvAnimationScrollYSpeedFactor),n.assignPrimitive(`uvAnimationRotationSpeedFactor`,e.uvAnimationRotationSpeedFactor),n.assignPrimitive(`v0CompatShade`,this.v0CompatShade),n.assignPrimitive(`debugMode`,this.debugMode),yield n.pending})}_setupPrimitive(e,t){let n=this._getMToonExtension(t);if(n){e.renderOrder=this._parseRenderOrder(n)+this.renderOrderOffset,this._generateOutline(e),this._addToMaterialSet(e);return}}_shouldGenerateOutline(e){return typeof e.outlineWidthMode==`string`&&e.outlineWidthMode!==`none`&&typeof e.outlineWidthFactor==`number`&&e.outlineWidthFactor>0}_generateOutline(e){let t=e.material;if(!(t instanceof lo)||!this._shouldGenerateOutline(t))return;e.material=[t];let n=t.clone();n.name+=` (Outline)`,n.isOutline=!0,n.side=1,e.material.push(n);let r=e.geometry,i=r.index?r.index.count:r.attributes.position.count/3;r.addGroup(0,i,0),r.addGroup(0,i,1)}_addToMaterialSet(e){let t=e.material,n=new Set;Array.isArray(t)?t.forEach(e=>n.add(e)):n.add(t);for(let e of n)this._mToonMaterialSet.add(e)}_parseRenderOrder(e){return(e.transparentWithZWrite?0:19)+(e.renderQueueOffsetNumber??0)}};dv.EXTENSION_NAME=`VRMC_materials_mtoon`;var fv=dv,pv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),mv=class e{get name(){return e.EXTENSION_NAME}constructor(e){this.parser=e}extendMaterialParams(e,t){return pv(this,null,function*(){let n=this._getHDREmissiveMultiplierExtension(e);n!=null&&(console.warn("VRMMaterialsHDREmissiveMultiplierLoaderPlugin: `VRMC_materials_hdr_emissiveMultiplier` is archived. Use `KHR_materials_emissive_strength` instead."),t.emissiveIntensity=n.emissiveMultiplier)})}_getHDREmissiveMultiplierExtension(t){let n=this.parser.json.materials?.[t];if(n==null){console.warn(`VRMMaterialsHDREmissiveMultiplierLoaderPlugin: Attempt to use materials[${t}] of glTF but the material doesn't exist`);return}let r=n.extensions?.[e.EXTENSION_NAME];if(r!=null)return r}};mv.EXTENSION_NAME=`VRMC_materials_hdr_emissiveMultiplier`;var hv=mv,gv=Object.defineProperty,_v=Object.defineProperties,vv=Object.getOwnPropertyDescriptors,yv=Object.getOwnPropertySymbols,bv=Object.prototype.hasOwnProperty,xv=Object.prototype.propertyIsEnumerable,Sv=(e,t,n)=>t in e?gv(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Cv=(e,t)=>{for(var n in t||={})bv.call(t,n)&&Sv(e,n,t[n]);if(yv)for(var n of yv(t))xv.call(t,n)&&Sv(e,n,t[n]);return e},wv=(e,t)=>_v(e,vv(t)),Tv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())});function Ev(e){return e**2.2}var Dv=class{get name(){return`VRMMaterialsV0CompatPlugin`}constructor(e){this.parser=e,this._renderQueueMapTransparent=new Map,this._renderQueueMapTransparentZWrite=new Map;let t=this.parser.json;t.extensionsUsed=t.extensionsUsed??[],t.extensionsUsed.indexOf(`KHR_texture_transform`)===-1&&t.extensionsUsed.push(`KHR_texture_transform`)}beforeRoot(){return Tv(this,null,function*(){let e=this.parser.json,t=e.extensions?.VRM?.materialProperties;t&&(this._populateRenderQueueMap(t),t.forEach((t,n)=>{let r=e.materials?.[n];if(r==null){console.warn(`VRMMaterialsV0CompatPlugin: Attempt to use materials[${n}] of glTF but the material doesn't exist`);return}if(t.shader===`VRM/MToon`){let i=this._parseV0MToonProperties(t,r);e.materials[n]=i}else if(t.shader?.startsWith(`VRM/Unlit`)){let i=this._parseV0UnlitProperties(t,r);e.materials[n]=i}else t.shader===`VRM_USE_GLTFSHADER`||console.warn(`VRMMaterialsV0CompatPlugin: Unknown shader: ${t.shader}`)}))})}_parseV0MToonProperties(e,t){let n=e.keywordMap?._ALPHABLEND_ON??!1,r=e.floatProperties?._ZWrite===1&&n,i=this._v0ParseRenderQueue(e),a=e.keywordMap?._ALPHATEST_ON??!1,o=n?`BLEND`:a?`MASK`:`OPAQUE`,s=a?e.floatProperties?._Cutoff??.5:void 0,c=(e.floatProperties?._CullMode??2)===0,l=this._portTextureTransform(e),u=(e.vectorProperties?._Color??[1,1,1,1]).map((e,t)=>t===3?e:Ev(e)),d=e.textureProperties?._MainTex,f=d==null?void 0:{index:d,extensions:Cv({},l)},p=e.floatProperties?._BumpScale??1,m=e.textureProperties?._BumpMap,h=m==null?void 0:{index:m,scale:p,extensions:Cv({},l)},g=(e.vectorProperties?._EmissionColor??[0,0,0,1]).map(Ev),_=e.textureProperties?._EmissionMap,v=_==null?void 0:{index:_,extensions:Cv({},l)},y=(e.vectorProperties?._ShadeColor??[.97,.81,.86,1]).map(Ev),b=e.textureProperties?._ShadeTexture,x=b==null?void 0:{index:b,extensions:Cv({},l)},S=e.floatProperties?._ShadeShift??0,C=e.floatProperties?._ShadeToony??.9;C=ni.lerp(C,1,.5+.5*S),S=-S-(1-C);let w=e.floatProperties?._IndirectLightIntensity??.1,T=w?1-w:void 0,E=e.textureProperties?._SphereAdd,D=E==null?void 0:[1,1,1],O=E==null?void 0:{index:E},k=e.floatProperties?._RimLightingMix??0,A=e.textureProperties?._RimTexture,ee=A==null?void 0:{index:A,extensions:Cv({},l)},te=(e.vectorProperties?._RimColor??[0,0,0,1]).map(Ev),ne=e.floatProperties?._RimFresnelPower??1,re=e.floatProperties?._RimLift??0,ie=[`none`,`worldCoordinates`,`screenCoordinates`][e.floatProperties?._OutlineWidthMode??0],ae=e.floatProperties?._OutlineWidth??0;ae=.01*ae;let oe=e.textureProperties?._OutlineWidthTexture,se=oe==null?void 0:{index:oe,extensions:Cv({},l)},ce=(e.vectorProperties?._OutlineColor??[0,0,0]).map(Ev),le=(e.floatProperties?._OutlineColorMode??0)===1?e.floatProperties?._OutlineLightingMix??1:0,ue=e.textureProperties?._UvAnimMaskTexture,de=ue==null?void 0:{index:ue,extensions:Cv({},l)},j=e.floatProperties?._UvAnimScrollX??0,fe=e.floatProperties?._UvAnimScrollY??0;fe!=null&&(fe=-fe);let pe=e.floatProperties?._UvAnimRotation??0,M={specVersion:`1.0`,transparentWithZWrite:r,renderQueueOffsetNumber:i,shadeColorFactor:y,shadeMultiplyTexture:x,shadingShiftFactor:S,shadingToonyFactor:C,giEqualizationFactor:T,matcapFactor:D,matcapTexture:O,rimLightingMixFactor:k,rimMultiplyTexture:ee,parametricRimColorFactor:te,parametricRimFresnelPowerFactor:ne,parametricRimLiftFactor:re,outlineWidthMode:ie,outlineWidthFactor:ae,outlineWidthMultiplyTexture:se,outlineColorFactor:ce,outlineLightingMixFactor:le,uvAnimationMaskTexture:de,uvAnimationScrollXSpeedFactor:j,uvAnimationScrollYSpeedFactor:fe,uvAnimationRotationSpeedFactor:pe};return wv(Cv({},t),{pbrMetallicRoughness:{baseColorFactor:u,baseColorTexture:f},normalTexture:h,emissiveTexture:v,emissiveFactor:g,alphaMode:o,alphaCutoff:s,doubleSided:c,extensions:{VRMC_materials_mtoon:M}})}_parseV0UnlitProperties(e,t){let n=e.shader===`VRM/UnlitTransparentZWrite`,r=e.shader===`VRM/UnlitTransparent`||n,i=this._v0ParseRenderQueue(e),a=e.shader===`VRM/UnlitCutout`,o=r?`BLEND`:a?`MASK`:`OPAQUE`,s=a?e.floatProperties?._Cutoff??.5:void 0,c=this._portTextureTransform(e),l=(e.vectorProperties?._Color??[1,1,1,1]).map(Ev),u=e.textureProperties?._MainTex,d=u==null?void 0:{index:u,extensions:Cv({},c)},f={specVersion:`1.0`,transparentWithZWrite:n,renderQueueOffsetNumber:i,shadeColorFactor:l,shadeMultiplyTexture:d};return wv(Cv({},t),{pbrMetallicRoughness:{baseColorFactor:l,baseColorTexture:d},alphaMode:o,alphaCutoff:s,extensions:{VRMC_materials_mtoon:f}})}_portTextureTransform(e){let t=e.vectorProperties?._MainTex;if(t==null)return{};let n=[t?.[0]??0,t?.[1]??0],r=[t?.[2]??1,t?.[3]??1];return n[1]=1-r[1]-n[1],{KHR_texture_transform:{offset:n,scale:r}}}_v0ParseRenderQueue(e){let t=e.shader===`VRM/UnlitTransparentZWrite`,n=e.keywordMap?._ALPHABLEND_ON!=null||e.shader===`VRM/UnlitTransparent`||t,r=e.floatProperties?._ZWrite===1||t,i=0;if(n){let t=e.renderQueue;t!=null&&(i=r?this._renderQueueMapTransparentZWrite.get(t):this._renderQueueMapTransparent.get(t))}return i}_populateRenderQueueMap(e){let t=new Set,n=new Set;e.forEach(e=>{let r=e.shader===`VRM/UnlitTransparentZWrite`,i=e.keywordMap?._ALPHABLEND_ON!=null||e.shader===`VRM/UnlitTransparent`||r,a=e.floatProperties?._ZWrite===1||r;if(i){let r=e.renderQueue;r!=null&&(a?n.add(r):t.add(r))}}),t.size>10&&console.warn(`VRMMaterialsV0CompatPlugin: This VRM uses ${t.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`),n.size>10&&console.warn(`VRMMaterialsV0CompatPlugin: This VRM uses ${n.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`),Array.from(t).sort().forEach((e,n)=>{let r=Math.min(Math.max(n-t.size+1,-9),0);this._renderQueueMapTransparent.set(e,r)}),Array.from(n).sort().forEach((e,t)=>{let n=Math.min(Math.max(t,0),9);this._renderQueueMapTransparentZWrite.set(e,n)})}},Ov=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),kv=new H,Av=class extends Qi{constructor(e){super(),this._attrPosition=new K(new Float32Array([0,0,0,0,0,0]),3),this._attrPosition.setUsage(_r);let t=new q;t.setAttribute(`position`,this._attrPosition);let n=new fs({color:16711935,depthTest:!1,depthWrite:!1});this._line=new bs(t,n),this.add(this._line),this.constraint=e}updateMatrixWorld(e){kv.setFromMatrixPosition(this.constraint.destination.matrixWorld),this._attrPosition.setXYZ(0,kv.x,kv.y,kv.z),this.constraint.source&&kv.setFromMatrixPosition(this.constraint.source.matrixWorld),this._attrPosition.setXYZ(1,kv.x,kv.y,kv.z),this._attrPosition.needsUpdate=!0,super.updateMatrixWorld(e)}};function jv(e,t){return t.set(e.elements[12],e.elements[13],e.elements[14])}var Mv=new H,Nv=new H;function Pv(e,t){return e.decompose(Mv,t,Nv),t}function Fv(e){return e.invert?e.invert():e.inverse(),e}var Iv=class{constructor(e,t){this.destination=e,this.source=t,this.weight=1}},Lv=new H,Rv=new H,zv=new H,Bv=new V,Vv=new V,Hv=new V,Uv=class extends Iv{get aimAxis(){return this._aimAxis}set aimAxis(e){this._aimAxis=e,this._v3AimAxis.set(e===`PositiveX`?1:e===`NegativeX`?-1:0,e===`PositiveY`?1:e===`NegativeY`?-1:0,e===`PositiveZ`?1:e===`NegativeZ`?-1:0)}get dependencies(){let e=new Set([this.source]);return this.destination.parent&&e.add(this.destination.parent),e}constructor(e,t){super(e,t),this._aimAxis=`PositiveX`,this._v3AimAxis=new H(1,0,0),this._dstRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion)}update(){this.destination.updateWorldMatrix(!0,!1),this.source.updateWorldMatrix(!0,!1);let e=Bv.identity(),t=Vv.identity();this.destination.parent&&(Pv(this.destination.parent.matrixWorld,e),Fv(t.copy(e)));let n=Lv.copy(this._v3AimAxis).applyQuaternion(this._dstRestQuat).applyQuaternion(e),r=jv(this.source.matrixWorld,Rv).sub(jv(this.destination.matrixWorld,zv)).normalize(),i=Hv.setFromUnitVectors(n,r).premultiply(t).multiply(e).multiply(this._dstRestQuat);this.destination.quaternion.copy(this._dstRestQuat).slerp(i,this.weight)}};function Wv(e,t){let n=[e],r=e.parent;for(;r!==null;)n.unshift(r),r=r.parent;n.forEach(e=>{t(e)})}var Gv=class{constructor(){this._constraints=new Set,this._objectConstraintsMap=new Map}get constraints(){return this._constraints}addConstraint(e){this._constraints.add(e);let t=this._objectConstraintsMap.get(e.destination);t??(t=new Set,this._objectConstraintsMap.set(e.destination,t)),t.add(e)}deleteConstraint(e){this._constraints.delete(e),this._objectConstraintsMap.get(e.destination).delete(e)}setInitState(){let e=new Set,t=new Set;for(let n of this._constraints)this._processConstraint(n,e,t,e=>e.setInitState())}update(){let e=new Set,t=new Set;for(let n of this._constraints)this._processConstraint(n,e,t,e=>e.update())}_processConstraint(e,t,n,r){if(n.has(e))return;if(t.has(e))throw Error(`VRMNodeConstraintManager: Circular dependency detected while updating constraints`);t.add(e);let i=e.dependencies;for(let e of i)Wv(e,e=>{let i=this._objectConstraintsMap.get(e);if(i)for(let e of i)this._processConstraint(e,t,n,r)});r(e),n.add(e)}},Kv=new V,qv=new V,Jv=class extends Iv{get dependencies(){return new Set([this.source])}constructor(e,t){super(e,t),this._dstRestQuat=new V,this._invSrcRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion),Fv(this._invSrcRestQuat.copy(this.source.quaternion))}update(){let e=Kv.copy(this._invSrcRestQuat).multiply(this.source.quaternion),t=qv.copy(this._dstRestQuat).multiply(e);this.destination.quaternion.copy(this._dstRestQuat).slerp(t,this.weight)}},Yv=new H,Xv=new V,Zv=new V,Qv=class extends Iv{get rollAxis(){return this._rollAxis}set rollAxis(e){this._rollAxis=e,this._v3RollAxis.set(+(e===`X`),+(e===`Y`),+(e===`Z`))}get dependencies(){return new Set([this.source])}constructor(e,t){super(e,t),this._rollAxis=`X`,this._v3RollAxis=new H(1,0,0),this._dstRestQuat=new V,this._invDstRestQuat=new V,this._invSrcRestQuatMulDstRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion),Fv(this._invDstRestQuat.copy(this._dstRestQuat)),Fv(this._invSrcRestQuatMulDstRestQuat.copy(this.source.quaternion)).multiply(this._dstRestQuat)}update(){let e=Xv.copy(this._invDstRestQuat).multiply(this.source.quaternion).multiply(this._invSrcRestQuatMulDstRestQuat),t=Yv.copy(this._v3RollAxis).applyQuaternion(e),n=Zv.setFromUnitVectors(t,this._v3RollAxis).premultiply(this._dstRestQuat).multiply(e);this.destination.quaternion.copy(this._dstRestQuat).slerp(n,this.weight)}},$v=new Set([`1.0`,`1.0-beta`]),ey=class e{get name(){return e.EXTENSION_NAME}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot}afterRoot(e){return Ov(this,null,function*(){e.userData.vrmNodeConstraintManager=yield this._import(e)})}_import(t){return Ov(this,null,function*(){let n=this.parser.json;if(n.extensionsUsed?.indexOf(e.EXTENSION_NAME)===-1)return null;let r=new Gv,i=yield this.parser.getDependencies(`node`);return i.forEach((t,a)=>{let o=n.nodes[a]?.extensions?.[e.EXTENSION_NAME];if(o==null)return;let s=o.specVersion;if(!$v.has(s)){console.warn(`VRMNodeConstraintLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${s}"`);return}let c=o.constraint;if(c.roll!=null){let e=this._importRollConstraint(t,i,c.roll);r.addConstraint(e)}else if(c.aim!=null){let e=this._importAimConstraint(t,i,c.aim);r.addConstraint(e)}else if(c.rotation!=null){let e=this._importRotationConstraint(t,i,c.rotation);r.addConstraint(e)}}),t.scene.updateMatrixWorld(),r.setInitState(),r})}_importRollConstraint(e,t,n){let{source:r,rollAxis:i,weight:a}=n,o=t[r],s=new Qv(e,o);if(i!=null&&(s.rollAxis=i),a!=null&&(s.weight=a),this.helperRoot){let e=new Av(s);this.helperRoot.add(e)}return s}_importAimConstraint(e,t,n){let{source:r,aimAxis:i,weight:a}=n,o=t[r],s=new Uv(e,o);if(i!=null&&(s.aimAxis=i),a!=null&&(s.weight=a),this.helperRoot){let e=new Av(s);this.helperRoot.add(e)}return s}_importRotationConstraint(e,t,n){let{source:r,weight:i}=n,a=t[r],o=new Jv(e,a);if(i!=null&&(o.weight=i),this.helperRoot){let e=new Av(o);this.helperRoot.add(e)}return o}};ey.EXTENSION_NAME=`VRMC_node_constraint`;var ty=ey,ny=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),ry=class{},iy=new H,ay=new H,oy=class extends ry{get type(){return`capsule`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.tail=e?.tail??new H(0,0,0),this.radius=e?.radius??0,this.inside=e?.inside??!1}calculateCollision(e,t,n,r){iy.setFromMatrixPosition(e),ay.subVectors(this.tail,this.offset).applyMatrix4(e),ay.sub(iy);let i=ay.lengthSq();r.copy(t).sub(iy);let a=ay.dot(r);a<=0||(i<=a||ay.multiplyScalar(a/i),r.sub(ay));let o=r.length(),s=this.inside?this.radius-n-o:o-n-this.radius;return s<0&&(r.multiplyScalar(1/o),this.inside&&r.negate()),s}},sy=new H,cy=new U,ly=class extends ry{get type(){return`plane`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.normal=e?.normal??new H(0,0,1)}calculateCollision(e,t,n,r){r.setFromMatrixPosition(e),r.negate().add(t),cy.getNormalMatrix(e),sy.copy(this.normal).applyNormalMatrix(cy).normalize();let i=r.dot(sy)-n;return r.copy(sy),i}},uy=new H,dy=class extends ry{get type(){return`sphere`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.radius=e?.radius??0,this.inside=e?.inside??!1}calculateCollision(e,t,n,r){r.subVectors(t,uy.setFromMatrixPosition(e));let i=r.length(),a=this.inside?this.radius-n-i:i-n-this.radius;return a<0&&(r.multiplyScalar(1/i),this.inside&&r.negate()),a}},fy=new H,py=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentOffset=new H,this._currentTail=new H,this._shape=e,this._attrPos=new K(new Float32Array(396),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(264),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._shape.radius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0);let n=fy.copy(this._shape.tail).divideScalar(this.worldScale);this._currentTail.distanceToSquared(n)>1e-10&&(this._currentTail.copy(n),e=!0),e&&this._buildPosition()}_buildPosition(){fy.copy(this._currentTail).sub(this._currentOffset);let e=fy.length()/this._currentRadius;for(let t=0;t<=16;t++){let n=t/16*Math.PI;this._attrPos.setXYZ(t,-Math.sin(n),-Math.cos(n),0),this._attrPos.setXYZ(17+t,e+Math.sin(n),Math.cos(n),0),this._attrPos.setXYZ(34+t,-Math.sin(n),0,-Math.cos(n)),this._attrPos.setXYZ(51+t,e+Math.sin(n),0,Math.cos(n))}for(let t=0;t<32;t++){let n=t/16*Math.PI;this._attrPos.setXYZ(68+t,0,Math.sin(n),Math.cos(n)),this._attrPos.setXYZ(100+t,e,Math.sin(n),Math.cos(n))}let t=Math.atan2(fy.y,Math.sqrt(fy.x*fy.x+fy.z*fy.z)),n=-Math.atan2(fy.z,fy.x);this.rotateZ(t),this.rotateY(n),this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<34;e++){let t=(e+1)%34;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(68+e*2,34+e,34+t)}for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(136+e*2,68+e,68+t),this._attrIndex.setXY(200+e*2,100+e,100+t)}this._attrIndex.needsUpdate=!0}},my=class extends q{constructor(e){super(),this.worldScale=1,this._currentOffset=new H,this._currentNormal=new H,this._shape=e,this._attrPos=new K(new Float32Array(18),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(10),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0),this._currentNormal.equals(this._shape.normal)||(this._currentNormal.copy(this._shape.normal),e=!0),e&&this._buildPosition()}_buildPosition(){this._attrPos.setXYZ(0,-.5,-.5,0),this._attrPos.setXYZ(1,.5,-.5,0),this._attrPos.setXYZ(2,.5,.5,0),this._attrPos.setXYZ(3,-.5,.5,0),this._attrPos.setXYZ(4,0,0,0),this._attrPos.setXYZ(5,0,0,.25),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this.lookAt(this._currentNormal),this._attrPos.needsUpdate=!0}_buildIndex(){this._attrIndex.setXY(0,0,1),this._attrIndex.setXY(2,1,2),this._attrIndex.setXY(4,2,3),this._attrIndex.setXY(6,3,0),this._attrIndex.setXY(8,4,5),this._attrIndex.needsUpdate=!0}},hy=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentOffset=new H,this._shape=e,this._attrPos=new K(new Float32Array(288),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(192),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._shape.radius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.needsUpdate=!0}},gy=new H,_y=class extends Qi{constructor(e){if(super(),this.matrixAutoUpdate=!1,this.collider=e,this.collider.shape instanceof dy)this._geometry=new hy(this.collider.shape);else if(this.collider.shape instanceof oy)this._geometry=new py(this.collider.shape);else if(this.collider.shape instanceof ly)this._geometry=new my(this.collider.shape);else throw Error(`VRMSpringBoneColliderHelper: Unknown collider shape type detected`);let t=new fs({color:16711935,depthTest:!1,depthWrite:!1});this._line=new ws(this._geometry,t),this.add(this._line)}dispose(){this._geometry.dispose()}updateMatrixWorld(e){this.collider.updateWorldMatrix(!0,!1),this.matrix.copy(this.collider.matrixWorld);let t=this.matrix.elements;this._geometry.worldScale=gy.set(t[0],t[1],t[2]).length(),this._geometry.update(),super.updateMatrixWorld(e)}},vy=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentTail=new H,this._springBone=e,this._attrPos=new K(new Float32Array(294),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(194),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._springBone.settings.hitRadius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentTail.equals(this._springBone.initialLocalChildPosition)||(this._currentTail.copy(this._springBone.initialLocalChildPosition),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.setXYZ(96,0,0,0),this._attrPos.setXYZ(97,this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.setXY(192,96,97),this._attrIndex.needsUpdate=!0}},yy=new H,by=class extends Qi{constructor(e){super(),this.matrixAutoUpdate=!1,this.springBone=e,this._geometry=new vy(this.springBone);let t=new fs({color:16776960,depthTest:!1,depthWrite:!1});this._line=new ws(this._geometry,t),this.add(this._line)}dispose(){this._geometry.dispose()}updateMatrixWorld(e){this.springBone.bone.updateWorldMatrix(!0,!1),this.matrix.copy(this.springBone.bone.matrixWorld);let t=this.matrix.elements;this._geometry.worldScale=yy.set(t[0],t[1],t[2]).length(),this._geometry.update(),super.updateMatrixWorld(e)}},xy=class extends Zi{constructor(e){super(),this.colliderMatrix=new W,this.shape=e}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),Sy(this.colliderMatrix,this.matrixWorld,this.shape.offset)}};function Sy(e,t,n){let r=t.elements;e.copy(t),n&&(e.elements[12]=r[0]*n.x+r[4]*n.y+r[8]*n.z+r[12],e.elements[13]=r[1]*n.x+r[5]*n.y+r[9]*n.z+r[13],e.elements[14]=r[2]*n.x+r[6]*n.y+r[10]*n.z+r[14])}var Cy=new W;function wy(e){return e.invert?e.invert():e.getInverse(Cy.copy(e)),e}var Ty=class{constructor(e){this._inverseCache=new W,this._shouldUpdateInverse=!0,this.matrix=e;let t={set:(e,t,n)=>(this._shouldUpdateInverse=!0,e[t]=n,!0)};this._originalElements=e.elements,e.elements=new Proxy(e.elements,t)}get inverse(){return this._shouldUpdateInverse&&=(wy(this._inverseCache.copy(this.matrix)),!1),this._inverseCache}revert(){this.matrix.elements=this._originalElements}},Ey=new W,Dy=new H,Oy=new H,ky=new H,Ay=new H,jy=new W,My=class{constructor(e,t,n={},r=[]){this._currentTail=new H,this._prevTail=new H,this._boneAxis=new H,this._worldSpaceBoneLength=0,this._center=null,this._initialLocalMatrix=new W,this._initialLocalRotation=new V,this._initialLocalChildPosition=new H,this.bone=e,this.bone.matrixAutoUpdate=!1,this.child=t,this.settings={hitRadius:n.hitRadius??0,stiffness:n.stiffness??1,gravityPower:n.gravityPower??0,gravityDir:n.gravityDir?.clone()??new H(0,-1,0),dragForce:n.dragForce??.4},this.colliderGroups=r}get dependencies(){let e=new Set,t=this.bone.parent;t&&e.add(t);for(let t=0;t<this.colliderGroups.length;t++)for(let n=0;n<this.colliderGroups[t].colliders.length;n++)e.add(this.colliderGroups[t].colliders[n]);return e}get center(){return this._center}set center(e){this._center?.userData.inverseCacheProxy&&(this._center.userData.inverseCacheProxy.revert(),delete this._center.userData.inverseCacheProxy),this._center=e,this._center&&(this._center.userData.inverseCacheProxy||(this._center.userData.inverseCacheProxy=new Ty(this._center.matrixWorld)))}get initialLocalChildPosition(){return this._initialLocalChildPosition}get _parentMatrixWorld(){return this.bone.parent?this.bone.parent.matrixWorld:Ey}setInitState(){this._initialLocalMatrix.copy(this.bone.matrix),this._initialLocalRotation.copy(this.bone.quaternion),this.child?this._initialLocalChildPosition.copy(this.child.position):this._initialLocalChildPosition.copy(this.bone.position).normalize().multiplyScalar(.07);let e=this._getMatrixWorldToCenter();this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(e),this._prevTail.copy(this._currentTail),this._boneAxis.copy(this._initialLocalChildPosition).normalize()}reset(){this.bone.quaternion.copy(this._initialLocalRotation),this.bone.updateMatrix(),this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld,this.bone.matrix);let e=this._getMatrixWorldToCenter();this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(e),this._prevTail.copy(this._currentTail)}update(e){if(e<=0)return;this._calcWorldSpaceBoneLength();let t=Oy.copy(this._boneAxis).transformDirection(this._initialLocalMatrix).transformDirection(this._parentMatrixWorld);Ay.copy(this._currentTail).add(Dy.subVectors(this._currentTail,this._prevTail).multiplyScalar(1-this.settings.dragForce)).applyMatrix4(this._getMatrixCenterToWorld()).addScaledVector(t,this.settings.stiffness*e).addScaledVector(this.settings.gravityDir,this.settings.gravityPower*e),ky.setFromMatrixPosition(this.bone.matrixWorld),Ay.sub(ky).normalize().multiplyScalar(this._worldSpaceBoneLength).add(ky),this._collision(Ay),this._prevTail.copy(this._currentTail),this._currentTail.copy(Ay).applyMatrix4(this._getMatrixWorldToCenter());let n=jy.multiplyMatrices(this._parentMatrixWorld,this._initialLocalMatrix).invert();this.bone.quaternion.setFromUnitVectors(this._boneAxis,Dy.copy(Ay).applyMatrix4(n).normalize()).premultiply(this._initialLocalRotation),this.bone.updateMatrix(),this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld,this.bone.matrix)}_collision(e){for(let t=0;t<this.colliderGroups.length;t++)for(let n=0;n<this.colliderGroups[t].colliders.length;n++){let r=this.colliderGroups[t].colliders[n],i=r.shape.calculateCollision(r.colliderMatrix,e,this.settings.hitRadius,Dy);if(i<0){e.addScaledVector(Dy,-i),e.sub(ky);let t=e.length();e.multiplyScalar(this._worldSpaceBoneLength/t).add(ky)}}}_calcWorldSpaceBoneLength(){Dy.setFromMatrixPosition(this.bone.matrixWorld),this.child?Oy.setFromMatrixPosition(this.child.matrixWorld):(Oy.copy(this._initialLocalChildPosition),Oy.applyMatrix4(this.bone.matrixWorld)),this._worldSpaceBoneLength=Dy.sub(Oy).length()}_getMatrixCenterToWorld(){return this._center?this._center.matrixWorld:Ey}_getMatrixWorldToCenter(){return this._center?this._center.userData.inverseCacheProxy.inverse:Ey}};function Ny(e,t){let n=[],r=e;for(;r!==null;)n.unshift(r),r=r.parent;n.forEach(e=>{t(e)})}function Py(e,t){e.children.forEach(e=>{t(e)||Py(e,t)})}function Fy(e){let t=new Map;for(let n of e){let r=n;do{let n=(t.get(r)??0)+1;if(n===e.size)return r;t.set(r,n),r=r.parent}while(r!==null)}return null}var Iy=class{constructor(){this._joints=new Set,this._sortedJoints=[],this._hasWarnedCircularDependency=!1,this._ancestors=[],this._objectSpringBonesMap=new Map,this._isSortedJointsDirty=!1,this._relevantChildrenUpdated=this._relevantChildrenUpdated.bind(this)}get joints(){return this._joints}get springBones(){return console.warn(`VRMSpringBoneManager: springBones is deprecated. use joints instead.`),this._joints}get colliderGroups(){let e=new Set;return this._joints.forEach(t=>{t.colliderGroups.forEach(t=>{e.add(t)})}),Array.from(e)}get colliders(){let e=new Set;return this.colliderGroups.forEach(t=>{t.colliders.forEach(t=>{e.add(t)})}),Array.from(e)}addJoint(e){this._joints.add(e);let t=this._objectSpringBonesMap.get(e.bone);t??(t=new Set,this._objectSpringBonesMap.set(e.bone,t)),t.add(e),this._isSortedJointsDirty=!0}addSpringBone(e){console.warn(`VRMSpringBoneManager: addSpringBone() is deprecated. use addJoint() instead.`),this.addJoint(e)}deleteJoint(e){this._joints.delete(e),this._objectSpringBonesMap.get(e.bone).delete(e),this._isSortedJointsDirty=!0}deleteSpringBone(e){console.warn(`VRMSpringBoneManager: deleteSpringBone() is deprecated. use deleteJoint() instead.`),this.deleteJoint(e)}setInitState(){this._sortJoints();for(let e=0;e<this._sortedJoints.length;e++){let t=this._sortedJoints[e];t.bone.updateMatrix(),t.bone.updateWorldMatrix(!1,!1),t.setInitState()}}reset(){this._sortJoints();for(let e=0;e<this._sortedJoints.length;e++){let t=this._sortedJoints[e];t.bone.updateMatrix(),t.bone.updateWorldMatrix(!1,!1),t.reset()}}update(e){this._sortJoints();for(let e=0;e<this._ancestors.length;e++)this._ancestors[e].updateWorldMatrix(e===0,!1);for(let t=0;t<this._sortedJoints.length;t++){let n=this._sortedJoints[t];n.bone.updateMatrix(),n.bone.updateWorldMatrix(!1,!1),n.update(e),Py(n.bone,this._relevantChildrenUpdated)}}_sortJoints(){if(!this._isSortedJointsDirty)return;let e=[],t=new Set,n=new Set,r=new Set;for(let i of this._joints)this._insertJointSort(i,t,n,e,r);this._sortedJoints=e;let i=Fy(r);this._ancestors=[],i&&(this._ancestors.push(i),Py(i,e=>(this._objectSpringBonesMap.get(e)?.size??0)>0?!0:(this._ancestors.push(e),!1))),this._isSortedJointsDirty=!1}_insertJointSort(e,t,n,r,i){if(n.has(e))return;if(t.has(e)){this._hasWarnedCircularDependency||=(console.warn(`VRMSpringBoneManager: Circular dependency detected`),!0);return}t.add(e);let a=e.dependencies;for(let e of a){let a=!1,o=null;Ny(e,e=>{let s=this._objectSpringBonesMap.get(e);if(s)for(let e of s)a=!0,this._insertJointSort(e,t,n,r,i);else a||(o=e)}),o&&i.add(o)}r.push(e),n.add(e)}_relevantChildrenUpdated(e){return(this._objectSpringBonesMap.get(e)?.size??0)>0?!0:(e.updateWorldMatrix(!1,!1),!1)}},Ly=`VRMC_springBone_extended_collider`,Ry=new Set([`1.0`,`1.0-beta`]),zy=new Set([`1.0`]),By=class e{get name(){return e.EXTENSION_NAME}constructor(e,t){this.parser=e,this.jointHelperRoot=t?.jointHelperRoot,this.colliderHelperRoot=t?.colliderHelperRoot,this.useExtendedColliders=t?.useExtendedColliders??!0}afterRoot(e){return ny(this,null,function*(){e.userData.vrmSpringBoneManager=yield this._import(e)})}_import(e){return ny(this,null,function*(){return(yield this._v1Import(e))??(yield this._v0Import(e))??null})}_v1Import(t){return ny(this,null,function*(){var n;let r=t.parser.json;if(r.extensionsUsed?.indexOf(e.EXTENSION_NAME)===-1)return null;let i=new Iy,a=yield t.parser.getDependencies(`node`),o=r.extensions?.[e.EXTENSION_NAME];if(!o)return null;let s=o.specVersion;if(!Ry.has(s))return console.warn(`VRMSpringBoneLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${s}"`),null;let c=o.colliders?.map((t,n)=>{let r=a[t.node];if(r==null)return console.warn(`VRMSpringBoneLoaderPlugin: The collider #${n} attempted to reference a node #${t.node} but not found. Skipping the collider`),null;let i=t.shape,o=t.extensions?.[Ly];if(this.useExtendedColliders&&o!=null){let t=o.specVersion;if(!zy.has(t))console.warn(`VRMSpringBoneLoaderPlugin: Unknown ${Ly} specVersion "${t}". Fallbacking to the ${e.EXTENSION_NAME} definition`);else{let e=o.shape;if(e.sphere)return this._importSphereCollider(r,{offset:new H().fromArray(e.sphere.offset??[0,0,0]),radius:e.sphere.radius??0,inside:e.sphere.inside??!1});if(e.capsule)return this._importCapsuleCollider(r,{offset:new H().fromArray(e.capsule.offset??[0,0,0]),radius:e.capsule.radius??0,tail:new H().fromArray(e.capsule.tail??[0,0,0]),inside:e.capsule.inside??!1});if(e.plane)return this._importPlaneCollider(r,{offset:new H().fromArray(e.plane.offset??[0,0,0]),normal:new H().fromArray(e.plane.normal??[0,0,1])})}}if(i.sphere)return this._importSphereCollider(r,{offset:new H().fromArray(i.sphere.offset??[0,0,0]),radius:i.sphere.radius??0,inside:!1});if(i.capsule)return this._importCapsuleCollider(r,{offset:new H().fromArray(i.capsule.offset??[0,0,0]),radius:i.capsule.radius??0,tail:new H().fromArray(i.capsule.tail??[0,0,0]),inside:!1});console.warn(`VRMSpringBoneLoaderPlugin: The collider #${n} has no valid shape. Skipping the collider`)}),l=o.colliderGroups?.map((e,t)=>({colliders:(e.colliders??[]).map(e=>c?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The collider group #${t} attempted to reference a collider #${e} but not found. Skipping the collider`),null)).filter(e=>e!=null),name:e.name}));return(n=o.springs)==null||n.forEach((e,t)=>{let n=e.joints,r=e.colliderGroups?.map(e=>l?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The spring #${t} attempted to reference a collider group #${e} but not found. Skipping the collider group`),null)).filter(e=>e!=null),o=e.center==null?void 0:a[e.center],s;n.forEach(e=>{if(s){let t=a[s.node],n=a[e.node],c={hitRadius:s.hitRadius,dragForce:s.dragForce,gravityPower:s.gravityPower,stiffness:s.stiffness,gravityDir:s.gravityDir==null?void 0:new H().fromArray(s.gravityDir)},l=this._importJoint(t,n,c,r);o&&(l.center=o),i.addJoint(l)}s=e})}),i.setInitState(),i})}_v0Import(e){return ny(this,null,function*(){let t=e.parser.json;if(t.extensionsUsed?.indexOf(`VRM`)===-1)return null;let n=t.extensions?.VRM?.secondaryAnimation;if(!n)return null;let r=n?.boneGroups;if(!r)return null;let i=new Iy,a=yield e.parser.getDependencies(`node`),o=n.colliderGroups?.map((e,t)=>{let n=a[e.node];return n==null?(console.warn(`VRMSpringBoneLoaderPlugin: The collider group #${t} attempted to reference a node #${e.node} but not found. Skipping the collider group`),null):{colliders:(e.colliders??[]).map((e,t)=>{let r=new H(0,0,0);return e.offset&&r.set(e.offset.x??0,e.offset.y??0,e.offset.z?-e.offset.z:0),this._importSphereCollider(n,{offset:r,radius:e.radius??0,inside:!1})})}});return r?.forEach((e,t)=>{let n=e.bones;n&&n.forEach(n=>{let r=a[n];if(r==null){console.warn(`VRMSpringBoneLoaderPlugin: The spring bone group #${t} attempted to reference a node #${n} but not found. Skipping the node`);return}let s=new H;e.gravityDir?s.set(e.gravityDir.x??0,e.gravityDir.y??0,e.gravityDir.z??0):s.set(0,-1,0);let c=e.center==null?void 0:a[e.center],l={hitRadius:e.hitRadius,dragForce:e.dragForce,gravityPower:e.gravityPower,stiffness:e.stiffiness,gravityDir:s},u=e.colliderGroups?.map(e=>o?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The spring #${t} attempted to reference a collider group #${e} but not found. Skipping the collider group`),null)).filter(e=>e!=null);r.traverse(e=>{let t=e.children[0]??null,n=this._importJoint(e,t,l,u);c&&(n.center=c),i.addJoint(n)})})}),e.scene.updateMatrixWorld(),i.setInitState(),i})}_importJoint(e,t,n,r){let i=new My(e,t,n,r);if(this.jointHelperRoot){let e=new by(i);this.jointHelperRoot.add(e),e.renderOrder=this.jointHelperRoot.renderOrder}return i}_importSphereCollider(e,t){let n=new xy(new dy(t));if(e.add(n),this.colliderHelperRoot){let e=new _y(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}_importCapsuleCollider(e,t){let n=new xy(new oy(t));if(e.add(n),this.colliderHelperRoot){let e=new _y(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}_importPlaneCollider(e,t){let n=new xy(new ly(t));if(e.add(n),this.colliderHelperRoot){let e=new _y(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}};By.EXTENSION_NAME=`VRMC_springBone`;var Vy=By,Hy=class{get name(){return`VRMLoaderPlugin`}constructor(e,t){this.parser=e;let n=t?.helperRoot,r=t?.autoUpdateHumanBones;this.expressionPlugin=t?.expressionPlugin??new Rg(e),this.firstPersonPlugin=t?.firstPersonPlugin??new Hg(e),this.humanoidPlugin=t?.humanoidPlugin??new s_(e,{helperRoot:n,autoUpdateHumanBones:r}),this.lookAtPlugin=t?.lookAtPlugin??new U_(e,{helperRoot:n}),this.metaPlugin=t?.metaPlugin??new K_(e),this.mtoonMaterialPlugin=t?.mtoonMaterialPlugin??new fv(e),this.materialsHDREmissiveMultiplierPlugin=t?.materialsHDREmissiveMultiplierPlugin??new hv(e),this.materialsV0CompatPlugin=t?.materialsV0CompatPlugin??new Dv(e),this.springBonePlugin=t?.springBonePlugin??new Vy(e,{colliderHelperRoot:n,jointHelperRoot:n}),this.nodeConstraintPlugin=t?.nodeConstraintPlugin??new ty(e,{helperRoot:n})}beforeRoot(){return vg(this,null,function*(){yield this.materialsV0CompatPlugin.beforeRoot(),yield this.mtoonMaterialPlugin.beforeRoot()})}loadMesh(e){return vg(this,null,function*(){return yield this.mtoonMaterialPlugin.loadMesh(e)})}getMaterialType(e){return this.mtoonMaterialPlugin.getMaterialType(e)??null}extendMaterialParams(e,t){return vg(this,null,function*(){yield this.materialsHDREmissiveMultiplierPlugin.extendMaterialParams(e,t),yield this.mtoonMaterialPlugin.extendMaterialParams(e,t)})}afterRoot(e){return vg(this,null,function*(){yield this.metaPlugin.afterRoot(e),yield this.humanoidPlugin.afterRoot(e),yield this.expressionPlugin.afterRoot(e),yield this.lookAtPlugin.afterRoot(e),yield this.firstPersonPlugin.afterRoot(e),yield this.springBonePlugin.afterRoot(e),yield this.nodeConstraintPlugin.afterRoot(e),yield this.mtoonMaterialPlugin.afterRoot(e);let t=e.userData.vrmMeta,n=e.userData.vrmHumanoid;if(t&&n){let r=new J_({scene:e.scene,expressionManager:e.userData.vrmExpressionManager,firstPerson:e.userData.vrmFirstPerson,humanoid:n,lookAt:e.userData.vrmLookAt,meta:t,materials:e.userData.vrmMToonMaterials,springBoneManager:e.userData.vrmSpringBoneManager,nodeConstraintManager:e.userData.vrmNodeConstraintManager});e.userData.vrm=r}})}};function Uy(e){let t=new Set;return e.traverse(e=>{if(!e.isMesh)return;let n=e;t.add(n)}),t}function Wy(e,t,n){if(t.size===1){let n=t.values().next().value;if(n.weight===1)return e[n.index]}let r=new Float32Array(e[0].count*3),i=0;if(n)i=1;else for(let e of t)i+=e.weight;for(let n of t){let t=e[n.index],a=n.weight/i;for(let e=0;e<t.count;e++)r[e*3+0]+=t.getX(e)*a,r[e*3+1]+=t.getY(e)*a,r[e*3+2]+=t.getZ(e)*a}return new K(r,3)}function Gy(e){let t=Uy(e.scene),n=new Map,r=e.expressionManager?.expressionMap;if(r!=null)for(let[e,t]of Object.entries(r)){let r=new Set;for(let i of t.binds)if(i instanceof Mg){if(i.weight!==0)for(let t of i.primitives){let r=n.get(t);r??(r=new Map,n.set(t,r));let a=r.get(e);a??(a=new Set,r.set(e,a)),a.add(i)}r.add(i)}for(let e of r)t.deleteBind(e)}for(let e of t){let t=n.get(e);if(t==null)continue;let i=e.geometry.morphAttributes;e.geometry.morphAttributes={};let a=e.geometry.clone();e.geometry=a;let o=a.morphTargetsRelative,s=i.position!=null,c=i.normal!=null,l={},u={},d=[];if(s||c){s&&(l.position=[]),c&&(l.normal=[]);let n=0;for(let[a,f]of t)s&&(l.position[n]=Wy(i.position,f,o)),c&&(l.normal[n]=Wy(i.normal,f,o)),r?.[a].addBind(new Mg({index:n,weight:1,primitives:[e]})),u[a]=n,d.push(0),n++}a.morphAttributes=l,e.morphTargetDictionary=u,e.morphTargetInfluences=d}}function Ky(e,t,n){if(e.getComponent)return e.getComponent(t,n);{let r=e.array[t*e.itemSize+n];return e.normalized&&(r=ni.denormalize(r,e.array)),r}}function qy(e,t,n,r){e.setComponent?e.setComponent(t,n,r):(e.normalized&&(r=ni.normalize(r,e.array)),e.array[t*e.itemSize+n]=r)}function Jy(e){let t=Yy(e),n=new Set;for(let e of t)n.has(e.geometry)&&(e.geometry=nb(e.geometry)),n.add(e.geometry);let r=new Map;for(let e of n){let t=e.getAttribute(`skinIndex`),n=r.get(t)??new Map;r.set(t,n);let i=e.getAttribute(`skinWeight`),a=Xy(t,i);n.set(i,a)}let i=new Map;for(let e of t){let t=Zy(e,r);i.set(e,t)}let a=[];for(let[e,t]of i){let n=!1;for(let r of a)if(Qy(t,r.boneInverseMap)){n=!0,r.meshes.add(e);for(let[e,n]of t)r.boneInverseMap.set(e,n);break}n||a.push({boneInverseMap:t,meshes:new Set([e])})}let o=new Map,s=new tb,c=new tb,l=new tb;for(let e of a){let{boneInverseMap:t,meshes:n}=e,r=Array.from(t.keys()),i=new Jo(r,Array.from(t.values())),a=c.getOrCreate(i);for(let e of n){let t=e.geometry.getAttribute(`skinIndex`),n=s.getOrCreate(t),i=e.skeleton.bones,c=`${n};${a};${i.map(e=>l.getOrCreate(e)).join(`,`)}`,u=o.get(c);u??(u=t.clone(),$y(u,i,r),o.set(c,u)),e.geometry.setAttribute(`skinIndex`,u)}for(let e of n)e.bind(i,new W)}}function Yy(e){let t=new Set;return e.traverse(e=>{if(!e.isSkinnedMesh)return;let n=e;t.add(n)}),t}function Xy(e,t){let n=new Set;for(let r=0;r<e.count;r++)for(let i=0;i<e.itemSize;i++){let a=Ky(e,r,i);Ky(t,r,i)!==0&&n.add(a)}return n}function Zy(e,t){let n=new Map,r=e.skeleton,i=e.geometry,a=i.getAttribute(`skinIndex`),o=i.getAttribute(`skinWeight`),s=t.get(a)?.get(o);if(!s)throw Error(`Unreachable. attributeUsedIndexSetMap does not know the skin index attribute or the skin weight attribute.`);for(let e of s)n.set(r.bones[e],r.boneInverses[e]);return n}function Qy(e,t){for(let[n,r]of e.entries()){let e=t.get(n);if(e!=null&&!eb(r,e))return!1}return!0}function $y(e,t,n){let r=new Map;for(let e of t)r.set(e,r.size);let i=new Map;for(let[e,t]of n.entries()){let n=r.get(t);i.set(n,e)}for(let t=0;t<e.count;t++)for(let n=0;n<e.itemSize;n++){let r=Ky(e,t,n),a=i.get(r);qy(e,t,n,a)}e.needsUpdate=!0}function eb(e,t,n){if(n||=1e-4,e.elements.length!=t.elements.length)return!1;for(let r=0,i=e.elements.length;r<i;r++)if(Math.abs(e.elements[r]-t.elements[r])>n)return!1;return!0}var tb=class{constructor(){this._objectIndexMap=new Map,this._index=0}get(e){return this._objectIndexMap.get(e)}getOrCreate(e){let t=this._objectIndexMap.get(e);return t??(t=this._index,this._objectIndexMap.set(e,t),this._index++),t}};function nb(e){let t=new q;t.name=e.name,t.setIndex(e.index);for(let[n,r]of Object.entries(e.attributes))t.setAttribute(n,r);for(let[n,r]of Object.entries(e.morphAttributes)){let e=n;t.morphAttributes[e]=r.concat()}t.morphTargetsRelative=e.morphTargetsRelative,t.groups=[];for(let n of e.groups)t.addGroup(n.start,n.count,n.materialIndex);return t.boundingSphere=e.boundingSphere?.clone()??null,t.boundingBox=e.boundingBox?.clone()??null,t.drawRange.start=e.drawRange.start,t.drawRange.count=e.drawRange.count,t.userData=e.userData,t}function rb(e){if(Object.values(e).forEach(e=>{e?.isTexture&&e.dispose()}),e.isShaderMaterial){let t=e.uniforms;t&&Object.values(t).forEach(e=>{let t=e.value;t?.isTexture&&t.dispose()})}e.dispose()}function ib(e){let t=e.geometry;t&&t.dispose();let n=e.skeleton;n&&n.dispose();let r=e.material;r&&(Array.isArray(r)?r.forEach(e=>rb(e)):r&&rb(r))}function ab(e){e.traverse(ib)}function ob(e,t){console.warn(`VRMUtils.removeUnnecessaryJoints: removeUnnecessaryJoints is deprecated. Use combineSkeletons instead. combineSkeletons contributes more to the performance improvement. This function will be removed in the next major version.`);let n=t?.experimentalSameBoneCounts??!1,r=[];e.traverse(e=>{e.type===`SkinnedMesh`&&r.push(e)});let i=new Map,a=0;for(let e of r){let t=e.geometry.getAttribute(`skinIndex`);if(i.has(t))continue;let n=new Map,r=new Map;for(let e=0;e<t.count;e++)for(let i=0;i<t.itemSize;i++){let a=Ky(t,e,i),o=n.get(a);o??(o=n.size,n.set(a,o),r.set(o,a)),qy(t,e,i,o)}t.needsUpdate=!0,i.set(t,r),a=Math.max(a,n.size)}for(let e of r){let t=e.geometry.getAttribute(`skinIndex`),r=i.get(t),o=[],s=[],c=n?a:r.size;for(let t=0;t<c;t++){let n=r.get(t)??0;o.push(e.skeleton.bones[n]),s.push(e.skeleton.boneInverses[n])}let l=new Jo(o,s);e.bind(l,new W)}}function sb(e,t){let n=e.position.count,r=Array(n),i=0,a=t.array;for(let e=0;e<a.length;e++){let t=a[e];r[t]||(r[t]=!0,i++)}return{isVertexUsed:r,vertexCount:n,verticesUsed:i}}function cb(e){let t=[],n=[],r=0;for(let i=0;i<e.length;i++)if(e[i]){let e=r++;t[i]=e,n[e]=i}return{originalIndexNewIndexMap:t,newIndexOriginalIndexMap:n}}function lb(e,t){t.name=e.name,t.morphTargetsRelative=e.morphTargetsRelative,e.groups.forEach(e=>{t.addGroup(e.start,e.count,e.materialIndex)}),t.boundingBox=e.boundingBox?.clone()??null,t.boundingSphere=e.boundingSphere?.clone()??null,t.setDrawRange(e.drawRange.start,e.drawRange.count),t.userData=e.userData}function ub(e,t,n){let r=t.array,i=new r.constructor(r.length);for(let e=0;e<r.length;e++)i[e]=n[r[e]];e.setIndex(new K(i,t.itemSize,t.normalized))}function db(e,t,n){let r=e.constructor,i=new r(t.length*n),a=!0;for(let r=0;r<t.length;r++){let o=t[r]*n,s=r*n;for(let t=0;t<n;t++){let n=e[o+t];i[s+t]=n,a&&=n===0}}return[i,a]}function fb(e){let t=new Map,n=[];for(let[r,i]of Object.entries(e))if(i.isInterleavedBufferAttribute){let e=i,n=e.data,a=t.get(n)??[];t.set(n,a),a.push([r,e])}else{let e=i;n.push([r,e])}return[t,n]}function pb(e,t,n){let[r,i]=fb(t);for(let[t,i]of r){let r=t.array,{stride:a}=t,[o,s]=db(r,n,a),c=new ao(o,a);c.setUsage(t.usage);for(let[t,n]of i){let{itemSize:r,offset:i,normalized:a}=n,o=new so(c,r,i,a);e.setAttribute(t,o)}}for(let[t,r]of i){let i=r.array,{itemSize:a,normalized:o}=r,[s,c]=db(i,n,a);e.setAttribute(t,new K(s,a,o))}}function mb(e){let t=new Map,n=[];for(let[r,i]of Object.entries(e)){let e=r;for(let r=0;r<i.length;r++){let a=i[r];if(a.isInterleavedBufferAttribute){let n=a,i=n.data,o=t.get(i)??[];t.set(i,o),o.push([e,r,n])}else{let t=a;n.push([e,r,t])}}}return[t,n]}function hb(e,t,n){let r=!0,[i,a]=mb(t),o={};for(let[e,t]of i){let i=e.array,{stride:a}=e,[s,c]=db(i,n,a);r&&=c;let l=new ao(s,a);l.setUsage(e.usage);for(let[e,n,r]of t){let{itemSize:t,offset:i,normalized:a}=r,s=new so(l,t,i,a);o[e]??(o[e]=[]),o[e][n]=s}}for(let[e,t,i]of a){let a=i,s=a.array,{itemSize:c,normalized:l}=a,[u,d]=db(s,n,c);r&&=d,o[e]??(o[e]=[]),o[e][t]=new K(u,c,l)}e.morphAttributes=r?{}:o}function gb(e){let t=new Map;e.traverse(e=>{if(!e.isMesh)return;let n=e,r=n.geometry,i=r.index;if(i==null)return;let a=t.get(r);if(a!=null){n.geometry=a;return}let{isVertexUsed:o,vertexCount:s,verticesUsed:c}=sb(r.attributes,i);if(c===s)return;let{originalIndexNewIndexMap:l,newIndexOriginalIndexMap:u}=cb(o),d=new q;lb(r,d),t.set(r,d),ub(d,i,l),pb(d,r.attributes,u),hb(d,r.morphAttributes,u),n.geometry=d}),Array.from(t.keys()).forEach(e=>{e.dispose()})}function _b(e){e.meta?.metaVersion===`0`&&(e.scene.rotation.y=Math.PI)}var vb=class{constructor(){}};vb.combineMorphs=Gy,vb.combineSkeletons=Jy,vb.deepDispose=ab,vb.removeUnnecessaryJoints=ob,vb.removeUnnecessaryVertices=gb,vb.rotateVRM0=_b;function yb(e,t){if(t===0)return console.warn(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.`),e;if(t===2||t===1){let n=e.getIndex();if(n===null){let t=[],r=e.getAttribute(`position`);if(r!==void 0){for(let e=0;e<r.count;e++)t.push(e);e.setIndex(t),n=e.getIndex()}else return console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.`),e}let r=n.count-2,i=[];if(t===2)for(let e=1;e<=r;e++)i.push(n.getX(0)),i.push(n.getX(e)),i.push(n.getX(e+1));else for(let e=0;e<r;e++)e%2==0?(i.push(n.getX(e)),i.push(n.getX(e+1)),i.push(n.getX(e+2))):(i.push(n.getX(e+2)),i.push(n.getX(e+1)),i.push(n.getX(e)));i.length/3!==r&&console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.`);let a=e.clone();return a.setIndex(i),a.clearGroups(),a}else return console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:`,t),e}function bb(e){let t=new Map,n=new Map,r=e.clone();return xb(e,r,function(e,r){t.set(r,e),n.set(e,r)}),r.traverse(function(e){if(!e.isSkinnedMesh)return;let r=e,i=t.get(e),a=i.skeleton.bones;r.skeleton=i.skeleton.clone(),r.bindMatrix.copy(i.bindMatrix),r.skeleton.bones=a.map(function(e){return n.get(e)}),r.bind(r.skeleton,r.bindMatrix)}),r}function xb(e,t,n){n(e,t);for(let r=0;r<e.children.length;r++)xb(e.children[r],t.children[r],n)}var Sb=class extends kc{constructor(e){super(e),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new kb(e)}),this.register(function(e){return new Ab(e)}),this.register(function(e){return new zb(e)}),this.register(function(e){return new Bb(e)}),this.register(function(e){return new Vb(e)}),this.register(function(e){return new Mb(e)}),this.register(function(e){return new Nb(e)}),this.register(function(e){return new Pb(e)}),this.register(function(e){return new Fb(e)}),this.register(function(e){return new Ob(e)}),this.register(function(e){return new Ib(e)}),this.register(function(e){return new jb(e)}),this.register(function(e){return new Rb(e)}),this.register(function(e){return new Lb(e)}),this.register(function(e){return new Eb(e)}),this.register(function(e){return new Hb(e,Tb.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new Hb(e,Tb.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new Ub(e)})}load(e,t,n,r){let i=this,a;if(this.resourcePath!==``)a=this.resourcePath;else if(this.path!==``){let t=il.extractUrlBase(e);a=il.resolveURL(t,this.path)}else a=il.extractUrlBase(e);this.manager.itemStart(e);let o=function(t){r?r(t):console.error(t),i.manager.itemError(e),i.manager.itemEnd(e)},s=new Mc(this.manager);s.setPath(this.path),s.setResponseType(`arraybuffer`),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(e,function(n){try{i.parse(n,a,function(n){t(n),i.manager.itemEnd(e)},o)}catch(e){o(e)}},n,o)}setDRACOLoader(e){return this.dracoLoader=e,this}setKTX2Loader(e){return this.ktx2Loader=e,this}setMeshoptDecoder(e){return this.meshoptDecoder=e,this}register(e){return this.pluginCallbacks.indexOf(e)===-1&&this.pluginCallbacks.push(e),this}unregister(e){return this.pluginCallbacks.indexOf(e)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(e),1),this}parse(e,t,n,r){let i,a={},o={},s=new TextDecoder;if(typeof e==`string`)i=JSON.parse(e);else if(e instanceof ArrayBuffer)if(s.decode(new Uint8Array(e,0,4))===Wb){try{a[Tb.KHR_BINARY_GLTF]=new qb(e)}catch(e){r&&r(e);return}i=JSON.parse(a[Tb.KHR_BINARY_GLTF].content)}else i=JSON.parse(s.decode(e));else i=e;if(i.asset===void 0||i.asset.version[0]<2){r&&r(Error(`THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.`));return}let c=new yx(i,{path:t||this.resourcePath||``,crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let e=0;e<this.pluginCallbacks.length;e++){let t=this.pluginCallbacks[e](c);t.name||console.error(`THREE.GLTFLoader: Invalid plugin found: missing name`),o[t.name]=t,a[t.name]=!0}if(i.extensionsUsed)for(let e=0;e<i.extensionsUsed.length;++e){let t=i.extensionsUsed[e],n=i.extensionsRequired||[];switch(t){case Tb.KHR_MATERIALS_UNLIT:a[t]=new Db;break;case Tb.KHR_DRACO_MESH_COMPRESSION:a[t]=new Jb(i,this.dracoLoader);break;case Tb.KHR_TEXTURE_TRANSFORM:a[t]=new Yb;break;case Tb.KHR_MESH_QUANTIZATION:a[t]=new Xb;break;default:n.indexOf(t)>=0&&o[t]===void 0&&console.warn(`THREE.GLTFLoader: Unknown extension "`+t+`".`)}}c.setExtensions(a),c.setPlugins(o),c.parse(n,r)}parseAsync(e,t){let n=this;return new Promise(function(r,i){n.parse(e,t,r,i)})}};function Cb(){let e={};return{get:function(t){return e[t]},add:function(t,n){e[t]=n},remove:function(t){delete e[t]},removeAll:function(){e={}}}}function wb(e,t,n){let r=e.json.materials[t];return r.extensions&&r.extensions[n]?r.extensions[n]:null}var Tb={KHR_BINARY_GLTF:`KHR_binary_glTF`,KHR_DRACO_MESH_COMPRESSION:`KHR_draco_mesh_compression`,KHR_LIGHTS_PUNCTUAL:`KHR_lights_punctual`,KHR_MATERIALS_CLEARCOAT:`KHR_materials_clearcoat`,KHR_MATERIALS_DISPERSION:`KHR_materials_dispersion`,KHR_MATERIALS_IOR:`KHR_materials_ior`,KHR_MATERIALS_SHEEN:`KHR_materials_sheen`,KHR_MATERIALS_SPECULAR:`KHR_materials_specular`,KHR_MATERIALS_TRANSMISSION:`KHR_materials_transmission`,KHR_MATERIALS_IRIDESCENCE:`KHR_materials_iridescence`,KHR_MATERIALS_ANISOTROPY:`KHR_materials_anisotropy`,KHR_MATERIALS_UNLIT:`KHR_materials_unlit`,KHR_MATERIALS_VOLUME:`KHR_materials_volume`,KHR_TEXTURE_BASISU:`KHR_texture_basisu`,KHR_TEXTURE_TRANSFORM:`KHR_texture_transform`,KHR_MESH_QUANTIZATION:`KHR_mesh_quantization`,KHR_MATERIALS_EMISSIVE_STRENGTH:`KHR_materials_emissive_strength`,EXT_MATERIALS_BUMP:`EXT_materials_bump`,EXT_TEXTURE_WEBP:`EXT_texture_webp`,EXT_TEXTURE_AVIF:`EXT_texture_avif`,EXT_MESHOPT_COMPRESSION:`EXT_meshopt_compression`,KHR_MESHOPT_COMPRESSION:`KHR_meshopt_compression`,EXT_MESH_GPU_INSTANCING:`EXT_mesh_gpu_instancing`},Eb=class{constructor(e){this.parser=e,this.name=Tb.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){let e=this.parser,t=this.parser.json.nodes||[];for(let n=0,r=t.length;n<r;n++){let r=t[n];r.extensions&&r.extensions[this.name]&&r.extensions[this.name].light!==void 0&&e._addNodeRef(this.cache,r.extensions[this.name].light)}}_loadLight(e){let t=this.parser,n=`light:`+e,r=t.cache.get(n);if(r)return r;let i=t.json,a=((i.extensions&&i.extensions[this.name]||{}).lights||[])[e],o,s=new G(16777215);a.color!==void 0&&s.setRGB(a.color[0],a.color[1],a.color[2],fr);let c=a.range===void 0?0:a.range;switch(a.type){case`directional`:o=new nl(s),o.target.position.set(0,0,-1),o.add(o.target);break;case`point`:o=new $c(s),o.distance=c;break;case`spot`:o=new Zc(s),o.distance=c,a.spot=a.spot||{},a.spot.innerConeAngle=a.spot.innerConeAngle===void 0?0:a.spot.innerConeAngle,a.spot.outerConeAngle=a.spot.outerConeAngle===void 0?Math.PI/4:a.spot.outerConeAngle,o.angle=a.spot.outerConeAngle,o.penumbra=1-a.spot.innerConeAngle/a.spot.outerConeAngle,o.target.position.set(0,0,-1),o.add(o.target);break;default:throw Error(`THREE.GLTFLoader: Unexpected light type: `+a.type)}return o.position.set(0,0,0),dx(o,a),a.intensity!==void 0&&(o.intensity=a.intensity),o.name=t.createUniqueName(a.name||`light_`+e),r=Promise.resolve(o),t.cache.add(n,r),r}getDependency(e,t){if(e===`light`)return this._loadLight(t)}createNodeAttachment(e){let t=this,n=this.parser,r=n.json.nodes[e],i=(r.extensions&&r.extensions[this.name]||{}).light;return i===void 0?null:this._loadLight(i).then(function(e){return n._getNodeRef(t.cache,i,e)})}},Db=class{constructor(){this.name=Tb.KHR_MATERIALS_UNLIT}getMaterialType(){return yo}extendParams(e,t,n){let r=[];e.color=new G(1,1,1),e.opacity=1;let i=t.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){let t=i.baseColorFactor;e.color.setRGB(t[0],t[1],t[2],fr),e.opacity=t[3]}i.baseColorTexture!==void 0&&r.push(n.assignTexture(e,`map`,i.baseColorTexture,dr))}return Promise.all(r)}},Ob=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);return n===null||n.emissiveStrength!==void 0&&(t.emissiveIntensity=n.emissiveStrength),Promise.resolve()}},kb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_CLEARCOAT}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];if(n.clearcoatFactor!==void 0&&(t.clearcoat=n.clearcoatFactor),n.clearcoatTexture!==void 0&&r.push(this.parser.assignTexture(t,`clearcoatMap`,n.clearcoatTexture)),n.clearcoatRoughnessFactor!==void 0&&(t.clearcoatRoughness=n.clearcoatRoughnessFactor),n.clearcoatRoughnessTexture!==void 0&&r.push(this.parser.assignTexture(t,`clearcoatRoughnessMap`,n.clearcoatRoughnessTexture)),n.clearcoatNormalTexture!==void 0&&(r.push(this.parser.assignTexture(t,`clearcoatNormalMap`,n.clearcoatNormalTexture)),n.clearcoatNormalTexture.scale!==void 0)){let e=n.clearcoatNormalTexture.scale;t.clearcoatNormalScale=new B(e,e)}return Promise.all(r)}},Ab=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_DISPERSION}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);return n===null||(t.dispersion=n.dispersion===void 0?0:n.dispersion),Promise.resolve()}},jb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_IRIDESCENCE}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.iridescenceFactor!==void 0&&(t.iridescence=n.iridescenceFactor),n.iridescenceTexture!==void 0&&r.push(this.parser.assignTexture(t,`iridescenceMap`,n.iridescenceTexture)),n.iridescenceIor!==void 0&&(t.iridescenceIOR=n.iridescenceIor),t.iridescenceThicknessRange===void 0&&(t.iridescenceThicknessRange=[100,400]),n.iridescenceThicknessMinimum!==void 0&&(t.iridescenceThicknessRange[0]=n.iridescenceThicknessMinimum),n.iridescenceThicknessMaximum!==void 0&&(t.iridescenceThicknessRange[1]=n.iridescenceThicknessMaximum),n.iridescenceThicknessTexture!==void 0&&r.push(this.parser.assignTexture(t,`iridescenceThicknessMap`,n.iridescenceThicknessTexture)),Promise.all(r)}},Mb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_SHEEN}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];if(t.sheenColor=new G(0,0,0),t.sheenRoughness=0,t.sheen=1,n.sheenColorFactor!==void 0){let e=n.sheenColorFactor;t.sheenColor.setRGB(e[0],e[1],e[2],fr)}return n.sheenRoughnessFactor!==void 0&&(t.sheenRoughness=n.sheenRoughnessFactor),n.sheenColorTexture!==void 0&&r.push(this.parser.assignTexture(t,`sheenColorMap`,n.sheenColorTexture,dr)),n.sheenRoughnessTexture!==void 0&&r.push(this.parser.assignTexture(t,`sheenRoughnessMap`,n.sheenRoughnessTexture)),Promise.all(r)}},Nb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_TRANSMISSION}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.transmissionFactor!==void 0&&(t.transmission=n.transmissionFactor),n.transmissionTexture!==void 0&&r.push(this.parser.assignTexture(t,`transmissionMap`,n.transmissionTexture)),Promise.all(r)}},Pb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_VOLUME}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];t.thickness=n.thicknessFactor===void 0?0:n.thicknessFactor,n.thicknessTexture!==void 0&&r.push(this.parser.assignTexture(t,`thicknessMap`,n.thicknessTexture)),t.attenuationDistance=n.attenuationDistance||1/0;let i=n.attenuationColor||[1,1,1];return t.attenuationColor=new G().setRGB(i[0],i[1],i[2],fr),Promise.all(r)}},Fb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_IOR}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);return n===null?Promise.resolve():(t.ior=n.ior===void 0?1.5:n.ior,t.ior===0&&(t.ior=1e3),Promise.resolve())}},Ib=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_SPECULAR}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];t.specularIntensity=n.specularFactor===void 0?1:n.specularFactor,n.specularTexture!==void 0&&r.push(this.parser.assignTexture(t,`specularIntensityMap`,n.specularTexture));let i=n.specularColorFactor||[1,1,1];return t.specularColor=new G().setRGB(i[0],i[1],i[2],fr),n.specularColorTexture!==void 0&&r.push(this.parser.assignTexture(t,`specularColorMap`,n.specularColorTexture,dr)),Promise.all(r)}},Lb=class{constructor(e){this.parser=e,this.name=Tb.EXT_MATERIALS_BUMP}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return t.bumpScale=n.bumpFactor===void 0?1:n.bumpFactor,n.bumpTexture!==void 0&&r.push(this.parser.assignTexture(t,`bumpMap`,n.bumpTexture)),Promise.all(r)}},Rb=class{constructor(e){this.parser=e,this.name=Tb.KHR_MATERIALS_ANISOTROPY}getMaterialType(e){return wb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=wb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.anisotropyStrength!==void 0&&(t.anisotropy=n.anisotropyStrength),n.anisotropyRotation!==void 0&&(t.anisotropyRotation=n.anisotropyRotation),n.anisotropyTexture!==void 0&&r.push(this.parser.assignTexture(t,`anisotropyMap`,n.anisotropyTexture)),Promise.all(r)}},zb=class{constructor(e){this.parser=e,this.name=Tb.KHR_TEXTURE_BASISU}loadTexture(e){let t=this.parser,n=t.json,r=n.textures[e];if(!r.extensions||!r.extensions[this.name])return null;let i=r.extensions[this.name],a=t.options.ktx2Loader;if(!a){if(n.extensionsRequired&&n.extensionsRequired.indexOf(this.name)>=0)throw Error(`THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures`);return null}return t.loadTextureImage(e,i.source,a)}},Bb=class{constructor(e){this.parser=e,this.name=Tb.EXT_TEXTURE_WEBP}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return n.loadTextureImage(e,a.source,s)}},Vb=class{constructor(e){this.parser=e,this.name=Tb.EXT_TEXTURE_AVIF}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return n.loadTextureImage(e,a.source,s)}},Hb=class{constructor(e,t){this.name=t,this.parser=e}loadBufferView(e){let t=this.parser.json,n=t.bufferViews[e];if(n.extensions&&n.extensions[this.name]){let e=n.extensions[this.name],r=this.parser.getDependency(`buffer`,e.buffer),i=this.parser.options.meshoptDecoder;if(!i||!i.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw Error(`THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files`);return null}return r.then(function(t){let n=e.byteOffset||0,r=e.byteLength||0,a=e.count,o=e.byteStride,s=new Uint8Array(t,n,r);return i.decodeGltfBufferAsync?i.decodeGltfBufferAsync(a,o,s,e.mode,e.filter).then(function(e){return e.buffer}):i.ready.then(function(){let t=new ArrayBuffer(a*o);return i.decodeGltfBuffer(new Uint8Array(t),a,o,s,e.mode,e.filter),t})})}else return null}},Ub=class{constructor(e){this.name=Tb.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){let t=this.parser.json,n=t.nodes[e];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;let r=t.meshes[n.mesh];for(let e of r.primitives)if(e.mode!==ex.TRIANGLES&&e.mode!==ex.TRIANGLE_STRIP&&e.mode!==ex.TRIANGLE_FAN&&e.mode!==void 0)return null;let i=n.extensions[this.name].attributes,a=[],o={};for(let e in i)a.push(this.parser.getDependency(`accessor`,i[e]).then(t=>(o[e]=t,o[e])));return a.length<1?null:(a.push(this.parser.createNodeMesh(e)),Promise.all(a).then(e=>{let t=e.pop(),n=t.isGroup?t.children:[t],r=e[0].count,i=[];for(let e of n){let t=new W,n=new H,a=new V,s=new H(1,1,1),c=new rs(e.geometry,e.material,r);for(let e=0;e<r;e++)o.TRANSLATION&&n.fromBufferAttribute(o.TRANSLATION,e),o.ROTATION&&a.fromBufferAttribute(o.ROTATION,e),o.SCALE&&s.fromBufferAttribute(o.SCALE,e),c.setMatrixAt(e,t.compose(n,a,s));for(let t in o)if(t===`_COLOR_0`){let e=o[t];c.instanceColor=new Yo(e.array,e.itemSize,e.normalized)}else t!==`TRANSLATION`&&t!==`ROTATION`&&t!==`SCALE`&&e.geometry.setAttribute(t,o[t]);Zi.prototype.copy.call(c,e),this.parser.assignFinalMaterial(c),i.push(c)}return t.isGroup?(t.clear(),t.add(...i),t):i[0]}))}},Wb=`glTF`,Gb=12,Kb={JSON:1313821514,BIN:5130562},qb=class{constructor(e){this.name=Tb.KHR_BINARY_GLTF,this.content=null,this.body=null;let t=new DataView(e,0,Gb),n=new TextDecoder;if(this.header={magic:n.decode(new Uint8Array(e.slice(0,4))),version:t.getUint32(4,!0),length:t.getUint32(8,!0)},this.header.magic!==Wb)throw Error(`THREE.GLTFLoader: Unsupported glTF-Binary header.`);if(this.header.version<2)throw Error(`THREE.GLTFLoader: Legacy binary file detected.`);let r=this.header.length-Gb,i=new DataView(e,Gb),a=0;for(;a<r;){let t=i.getUint32(a,!0);a+=4;let r=i.getUint32(a,!0);if(a+=4,r===Kb.JSON){let r=new Uint8Array(e,Gb+a,t);this.content=n.decode(r)}else if(r===Kb.BIN){let n=Gb+a;this.body=e.slice(n,n+t)}a+=t}if(this.content===null)throw Error(`THREE.GLTFLoader: JSON content not found.`)}},Jb=class{constructor(e,t){if(!t)throw Error(`THREE.GLTFLoader: No DRACOLoader instance provided.`);this.name=Tb.KHR_DRACO_MESH_COMPRESSION,this.json=e,this.dracoLoader=t,this.dracoLoader.preload()}decodePrimitive(e,t){let n=this.json,r=this.dracoLoader,i=e.extensions[this.name].bufferView,a=e.extensions[this.name].attributes,o={},s={},c={};for(let e in a){let t=ax[e]||e.toLowerCase();o[t]=a[e]}for(let t in e.attributes){let r=ax[t]||t.toLowerCase();if(a[t]!==void 0){let i=n.accessors[e.attributes[t]];c[r]=tx[i.componentType].name,s[r]=i.normalized===!0}}return t.getDependency(`bufferView`,i).then(function(e){return new Promise(function(t,n){r.decodeDracoFile(e,function(e){for(let t in e.attributes){let n=e.attributes[t],r=s[t];r!==void 0&&(n.normalized=r)}t(e)},o,c,fr,n)})})}},Yb=class{constructor(){this.name=Tb.KHR_TEXTURE_TRANSFORM}extendTexture(e,t){return(t.texCoord===void 0||t.texCoord===e.channel)&&t.offset===void 0&&t.rotation===void 0&&t.scale===void 0?e:(e=e.clone(),t.texCoord!==void 0&&(e.channel=t.texCoord),t.offset!==void 0&&e.offset.fromArray(t.offset),t.rotation!==void 0&&(e.rotation=t.rotation),t.scale!==void 0&&e.repeat.fromArray(t.scale),e.needsUpdate=!0,e)}},Xb=class{constructor(){this.name=Tb.KHR_MESH_QUANTIZATION}},Zb=class extends uc{constructor(e,t,n,r){super(e,t,n,r)}copySampleValue_(e){let t=this.resultBuffer,n=this.sampleValues,r=this.valueSize,i=e*r*3+r;for(let e=0;e!==r;e++)t[e]=n[i+e];return t}interpolate_(e,t,n,r){let i=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=o*2,c=o*3,l=r-t,u=(n-t)/l,d=u*u,f=d*u,p=e*c,m=p-c,h=-2*f+3*d,g=f-d,_=1-h,v=g-d+u;for(let e=0;e!==o;e++){let t=a[m+e+o],n=a[m+e+s]*l,r=a[p+e+o],c=a[p+e]*l;i[e]=_*t+v*n+h*r+g*c}return i}},Qb=new V,$b=class extends Zb{interpolate_(e,t,n,r){let i=super.interpolate_(e,t,n,r);return Qb.fromArray(i).normalize().toArray(i),i}},ex={FLOAT:5126,FLOAT_MAT3:35675,FLOAT_MAT4:35676,FLOAT_VEC2:35664,FLOAT_VEC3:35665,FLOAT_VEC4:35666,LINEAR:9729,REPEAT:10497,SAMPLER_2D:35678,POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6,UNSIGNED_BYTE:5121,UNSIGNED_SHORT:5123},tx={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},nx={9728:zt,9729:Ht,9984:Bt,9985:Ut,9986:Vt,9987:Wt},rx={33071:Lt,33648:Rt,10497:It},ix={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},ax={POSITION:`position`,NORMAL:`normal`,TANGENT:`tangent`,TEXCOORD_0:`uv`,TEXCOORD_1:`uv1`,TEXCOORD_2:`uv2`,TEXCOORD_3:`uv3`,COLOR_0:`color`,WEIGHTS_0:`skinWeight`,JOINTS_0:`skinIndex`},ox={scale:`scale`,translation:`position`,rotation:`quaternion`,weights:`morphTargetInfluences`},sx={CUBICSPLINE:void 0,LINEAR:tr,STEP:er},cx={OPAQUE:`OPAQUE`,MASK:`MASK`,BLEND:`BLEND`};function lx(e){return e.DefaultMaterial===void 0&&(e.DefaultMaterial=new nc({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:0})),e.DefaultMaterial}function ux(e,t,n){for(let r in n.extensions)e[r]===void 0&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[r]=n.extensions[r])}function dx(e,t){t.extras!==void 0&&(typeof t.extras==`object`?Object.assign(e.userData,t.extras):console.warn(`THREE.GLTFLoader: Ignoring primitive type .extras, `+t.extras))}function fx(e,t,n){let r=!1,i=!1,a=!1;for(let e=0,n=t.length;e<n;e++){let n=t[e];if(n.POSITION!==void 0&&(r=!0),n.NORMAL!==void 0&&(i=!0),n.COLOR_0!==void 0&&(a=!0),r&&i&&a)break}if(!r&&!i&&!a)return Promise.resolve(e);let o=[],s=[],c=[];for(let l=0,u=t.length;l<u;l++){let u=t[l];if(r){let t=u.POSITION===void 0?e.attributes.position:n.getDependency(`accessor`,u.POSITION);o.push(t)}if(i){let t=u.NORMAL===void 0?e.attributes.normal:n.getDependency(`accessor`,u.NORMAL);s.push(t)}if(a){let t=u.COLOR_0===void 0?e.attributes.color:n.getDependency(`accessor`,u.COLOR_0);c.push(t)}}return Promise.all([Promise.all(o),Promise.all(s),Promise.all(c)]).then(function(t){let n=t[0],o=t[1],s=t[2];return r&&(e.morphAttributes.position=n),i&&(e.morphAttributes.normal=o),a&&(e.morphAttributes.color=s),e.morphTargetsRelative=!0,e})}function px(e,t){if(e.updateMorphTargets(),t.weights!==void 0)for(let n=0,r=t.weights.length;n<r;n++)e.morphTargetInfluences[n]=t.weights[n];if(t.extras&&Array.isArray(t.extras.targetNames)){let n=t.extras.targetNames;if(e.morphTargetInfluences.length===n.length){e.morphTargetDictionary={};for(let t=0,r=n.length;t<r;t++)e.morphTargetDictionary[n[t]]=t}else console.warn(`THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.`)}}function mx(e){let t,n=e.extensions&&e.extensions[Tb.KHR_DRACO_MESH_COMPRESSION];if(t=n?`draco:`+n.bufferView+`:`+n.indices+`:`+hx(n.attributes):e.indices+`:`+hx(e.attributes)+`:`+e.mode,e.targets!==void 0)for(let n=0,r=e.targets.length;n<r;n++)t+=`:`+hx(e.targets[n]);return t}function hx(e){let t=``,n=Object.keys(e).sort();for(let r=0,i=n.length;r<i;r++)t+=n[r]+`:`+e[n[r]]+`;`;return t}function gx(e){switch(e){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw Error(`THREE.GLTFLoader: Unsupported normalized accessor component type.`)}}function _x(e){return e.search(/\.jpe?g($|\?)/i)>0||e.search(/^data\:image\/jpeg/)===0?`image/jpeg`:e.search(/\.webp($|\?)/i)>0||e.search(/^data\:image\/webp/)===0?`image/webp`:e.search(/\.ktx2($|\?)/i)>0||e.search(/^data\:image\/ktx2/)===0?`image/ktx2`:`image/png`}var vx=new W,yx=class{constructor(e={},t={}){this.json=e,this.extensions={},this.plugins={},this.options=t,this.cache=new Cb,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,r=-1,i=!1,a=-1;if(typeof navigator<`u`&&navigator.userAgent!==void 0){let e=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(e)===!0;let t=e.match(/Version\/(\d+)/);r=n&&t?parseInt(t[1],10):-1,i=e.indexOf(`Firefox`)>-1,a=i?e.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>`u`||n&&r<17||i&&a<98?this.textureLoader=new Ic(this.options.manager):this.textureLoader=new ol(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new Mc(this.options.manager),this.fileLoader.setResponseType(`arraybuffer`),this.options.crossOrigin===`use-credentials`&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){let n=this,r=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(e){return e._markDefs&&e._markDefs()}),Promise.all(this._invokeAll(function(e){return e.beforeRoot&&e.beforeRoot()})).then(function(){return Promise.all([n.getDependencies(`scene`),n.getDependencies(`animation`),n.getDependencies(`camera`)])}).then(function(t){let a={scene:t[0][r.scene||0],scenes:t[0],animations:t[1],cameras:t[2],asset:r.asset,parser:n,userData:{}};return ux(i,a,r),dx(a,r),Promise.all(n._invokeAll(function(e){return e.afterRoot&&e.afterRoot(a)})).then(function(){for(let e of a.scenes)e.updateMatrixWorld();e(a)})}).catch(t)}_markDefs(){let e=this.json.nodes||[],t=this.json.skins||[],n=this.json.meshes||[];for(let n=0,r=t.length;n<r;n++){let r=t[n].joints;for(let t=0,n=r.length;t<n;t++)e[r[t]].isBone=!0}for(let t=0,r=e.length;t<r;t++){let r=e[t];r.mesh!==void 0&&(this._addNodeRef(this.meshCache,r.mesh),r.skin!==void 0&&(n[r.mesh].isSkinnedMesh=!0)),r.camera!==void 0&&this._addNodeRef(this.cameraCache,r.camera)}}_addNodeRef(e,t){t!==void 0&&(e.refs[t]===void 0&&(e.refs[t]=e.uses[t]=0),e.refs[t]++)}_getNodeRef(e,t,n){if(e.refs[t]<=1)return n;let r=n.clone(),i=(e,t)=>{let n=this.associations.get(e);n!=null&&this.associations.set(t,n);for(let[n,r]of e.children.entries())i(r,t.children[n])};return i(n,r),r.name+=`_instance_`+ e.uses[t]++,r}_invokeOne(e){let t=Object.values(this.plugins);t.push(this);for(let n=0;n<t.length;n++){let r=e(t[n]);if(r)return r}return null}_invokeAll(e){let t=Object.values(this.plugins);t.unshift(this);let n=[];for(let r=0;r<t.length;r++){let i=e(t[r]);i&&n.push(i)}return n}getDependency(e,t){let n=e+`:`+t,r=this.cache.get(n);if(!r){switch(e){case`scene`:r=this.loadScene(t);break;case`node`:r=this._invokeOne(function(e){return e.loadNode&&e.loadNode(t)});break;case`mesh`:r=this._invokeOne(function(e){return e.loadMesh&&e.loadMesh(t)});break;case`accessor`:r=this.loadAccessor(t);break;case`bufferView`:r=this._invokeOne(function(e){return e.loadBufferView&&e.loadBufferView(t)});break;case`buffer`:r=this.loadBuffer(t);break;case`material`:r=this._invokeOne(function(e){return e.loadMaterial&&e.loadMaterial(t)});break;case`texture`:r=this._invokeOne(function(e){return e.loadTexture&&e.loadTexture(t)});break;case`skin`:r=this.loadSkin(t);break;case`animation`:r=this._invokeOne(function(e){return e.loadAnimation&&e.loadAnimation(t)});break;case`camera`:r=this.loadCamera(t);break;default:if(r=this._invokeOne(function(n){return n!=this&&n.getDependency&&n.getDependency(e,t)}),!r)throw Error(`Unknown type: `+e);break}this.cache.add(n,r)}return r}getDependencies(e){let t=this.cache.get(e);if(!t){let n=this,r=this.json[e+(e===`mesh`?`es`:`s`)]||[];t=Promise.all(r.map(function(t,r){return n.getDependency(e,r)})),this.cache.add(e,t)}return t}loadBuffer(e){let t=this.json.buffers[e],n=this.fileLoader;if(t.type&&t.type!==`arraybuffer`)throw Error(`THREE.GLTFLoader: `+t.type+` buffer type is not supported.`);if(t.uri===void 0&&e===0)return Promise.resolve(this.extensions[Tb.KHR_BINARY_GLTF].body);let r=this.options;return new Promise(function(e,i){n.load(il.resolveURL(t.uri,r.path),e,void 0,function(){i(Error(`THREE.GLTFLoader: Failed to load buffer "`+t.uri+`".`))})})}loadBufferView(e){let t=this.json.bufferViews[e];return this.getDependency(`buffer`,t.buffer).then(function(e){let n=t.byteLength||0,r=t.byteOffset||0;return e.slice(r,r+n)})}loadAccessor(e){let t=this,n=this.json,r=this.json.accessors[e];if(r.bufferView===void 0&&r.sparse===void 0){let e=ix[r.type],t=tx[r.componentType],n=r.normalized===!0,i=new t(r.count*e);return Promise.resolve(new K(i,e,n))}let i=[];return r.bufferView===void 0?i.push(null):i.push(this.getDependency(`bufferView`,r.bufferView)),r.sparse!==void 0&&(i.push(this.getDependency(`bufferView`,r.sparse.indices.bufferView)),i.push(this.getDependency(`bufferView`,r.sparse.values.bufferView))),Promise.all(i).then(function(e){let i=e[0],a=ix[r.type],o=tx[r.componentType],s=o.BYTES_PER_ELEMENT,c=s*a,l=r.byteOffset||0,u=r.bufferView===void 0?void 0:n.bufferViews[r.bufferView].byteStride,d=r.normalized===!0,f,p;if(u&&u!==c){let e=Math.floor(l/u),n=`InterleavedBuffer:`+r.bufferView+`:`+r.componentType+`:`+e+`:`+r.count,c=t.cache.get(n);c||(f=new o(i,e*u,r.count*u/s),c=new ao(f,u/s),t.cache.add(n,c)),p=new so(c,a,l%u/s,d)}else f=i===null?new o(r.count*a):new o(i,l,r.count*a),p=new K(f,a,d);if(r.sparse!==void 0){let t=ix.SCALAR,n=tx[r.sparse.indices.componentType],s=r.sparse.indices.byteOffset||0,c=r.sparse.values.byteOffset||0,l=new n(e[1],s,r.sparse.count*t),u=new o(e[2],c,r.sparse.count*a);i!==null&&(p=new K(p.array.slice(),p.itemSize,p.normalized)),p.normalized=!1;for(let e=0,t=l.length;e<t;e++){let t=l[e];if(p.setX(t,u[e*a]),a>=2&&p.setY(t,u[e*a+1]),a>=3&&p.setZ(t,u[e*a+2]),a>=4&&p.setW(t,u[e*a+3]),a>=5)throw Error(`THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.`)}p.normalized=d}return p})}loadTexture(e){let t=this.json,n=this.options,r=t.textures[e].source,i=t.images[r],a=this.textureLoader;if(i.uri){let e=n.manager.getHandler(i.uri);e!==null&&(a=e)}return this.loadTextureImage(e,r,a)}loadTextureImage(e,t,n){let r=this,i=this.json,a=i.textures[e],o=i.images[t],s=(o.uri||o.bufferView)+`:`+a.sampler;if(this.textureCache[s])return this.textureCache[s];let c=this.loadImageSource(t,n).then(function(t){t.flipY=!1,t.name=a.name||o.name||``,t.name===``&&typeof o.uri==`string`&&o.uri.startsWith(`data:image/`)===!1&&(t.name=o.uri);let n=(i.samplers||{})[a.sampler]||{};return t.magFilter=nx[n.magFilter]||1006,t.minFilter=nx[n.minFilter]||1008,t.wrapS=rx[n.wrapS]||1e3,t.wrapT=rx[n.wrapT]||1e3,t.generateMipmaps=!t.isCompressedTexture&&t.minFilter!==1003&&t.minFilter!==1006,r.associations.set(t,{textures:e}),t}).catch(function(){return null});return this.textureCache[s]=c,c}loadImageSource(e,t){let n=this,r=this.json,i=this.options;if(this.sourceCache[e]!==void 0)return this.sourceCache[e].then(e=>e.clone());let a=r.images[e],o=self.URL||self.webkitURL,s=a.uri||``,c=!1;if(a.bufferView!==void 0)s=n.getDependency(`bufferView`,a.bufferView).then(function(e){c=!0;let t=new Blob([e],{type:a.mimeType});return s=o.createObjectURL(t),s});else if(a.uri===void 0)throw Error(`THREE.GLTFLoader: Image `+e+` is missing URI and bufferView`);let l=Promise.resolve(s).then(function(e){return new Promise(function(n,r){let a=n;t.isImageBitmapLoader===!0&&(a=function(e){let t=new yi(e);t.needsUpdate=!0,n(t)}),t.load(il.resolveURL(e,i.path),a,void 0,r)})}).then(function(e){return c===!0&&o.revokeObjectURL(s),dx(e,a),e.userData.mimeType=a.mimeType||_x(a.uri),e}).catch(function(e){throw console.error(`THREE.GLTFLoader: Couldn't load texture`,s),e});return this.sourceCache[e]=l,l}assignTexture(e,t,n,r){let i=this;return this.getDependency(`texture`,n.index).then(function(a){if(!a)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(a=a.clone(),a.channel=n.texCoord),i.extensions[Tb.KHR_TEXTURE_TRANSFORM]){let e=n.extensions===void 0?void 0:n.extensions[Tb.KHR_TEXTURE_TRANSFORM];if(e){let t=i.associations.get(a);a=i.extensions[Tb.KHR_TEXTURE_TRANSFORM].extendTexture(a,e),i.associations.set(a,t)}}return r!==void 0&&(a.colorSpace=r),e[t]=a,a})}assignFinalMaterial(e){let t=e.geometry,n=e.material,r=t.attributes.tangent===void 0,i=t.attributes.color!==void 0,a=t.attributes.normal===void 0;if(e.isPoints){let e=`PointsMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new Es,lo.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,t.sizeAttenuation=!1,this.cache.add(e,t)),n=t}else if(e.isLine){let e=`LineBasicMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new fs,lo.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,this.cache.add(e,t)),n=t}if(r||i||a){let e=`ClonedMaterial:`+n.uuid+`:`;r&&(e+=`derivative-tangents:`),i&&(e+=`vertex-colors:`),a&&(e+=`flat-shading:`);let t=this.cache.get(e);t||(t=n.clone(),i&&(t.vertexColors=!0),a&&(t.flatShading=!0),r&&(t.normalScale&&(t.normalScale.y*=-1),t.clearcoatNormalScale&&(t.clearcoatNormalScale.y*=-1)),this.cache.add(e,t),this.associations.set(t,this.associations.get(n))),n=t}e.material=n}getMaterialType(){return nc}loadMaterial(e){let t=this,n=this.json,r=this.extensions,i=n.materials[e],a,o={},s=i.extensions||{},c=[];if(s[Tb.KHR_MATERIALS_UNLIT]){let e=r[Tb.KHR_MATERIALS_UNLIT];a=e.getMaterialType(),c.push(e.extendParams(o,i,t))}else{let n=i.pbrMetallicRoughness||{};if(o.color=new G(1,1,1),o.opacity=1,Array.isArray(n.baseColorFactor)){let e=n.baseColorFactor;o.color.setRGB(e[0],e[1],e[2],fr),o.opacity=e[3]}n.baseColorTexture!==void 0&&c.push(t.assignTexture(o,`map`,n.baseColorTexture,dr)),o.metalness=n.metallicFactor===void 0?1:n.metallicFactor,o.roughness=n.roughnessFactor===void 0?1:n.roughnessFactor,n.metallicRoughnessTexture!==void 0&&(c.push(t.assignTexture(o,`metalnessMap`,n.metallicRoughnessTexture)),c.push(t.assignTexture(o,`roughnessMap`,n.metallicRoughnessTexture))),a=this._invokeOne(function(t){return t.getMaterialType&&t.getMaterialType(e)}),c.push(Promise.all(this._invokeAll(function(t){return t.extendMaterialParams&&t.extendMaterialParams(e,o)})))}i.doubleSided===!0&&(o.side=2);let l=i.alphaMode||cx.OPAQUE;if(l===cx.BLEND?(o.transparent=!0,o.depthWrite=!1):(o.transparent=!1,l===cx.MASK&&(o.alphaTest=i.alphaCutoff===void 0?.5:i.alphaCutoff)),i.normalTexture!==void 0&&a!==yo&&(c.push(t.assignTexture(o,`normalMap`,i.normalTexture)),o.normalScale=new B(1,1),i.normalTexture.scale!==void 0)){let e=i.normalTexture.scale;o.normalScale.set(e,e)}if(i.occlusionTexture!==void 0&&a!==yo&&(c.push(t.assignTexture(o,`aoMap`,i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(o.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&a!==yo){let e=i.emissiveFactor;o.emissive=new G().setRGB(e[0],e[1],e[2],fr)}return i.emissiveTexture!==void 0&&a!==yo&&c.push(t.assignTexture(o,`emissiveMap`,i.emissiveTexture,dr)),Promise.all(c).then(function(){let n=new a(o);return i.name&&(n.name=i.name),dx(n,i),t.associations.set(n,{materials:e}),i.extensions&&ux(r,n,i),n})}createUniqueName(e){let t=Cl.sanitizeNodeName(e||``);return t in this.nodeNamesUsed?t+`_`+ ++this.nodeNamesUsed[t]:(this.nodeNamesUsed[t]=0,t)}loadGeometries(e){let t=this,n=this.extensions,r=this.primitiveCache;function i(e){return n[Tb.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(e,t).then(function(n){return xx(n,e,t)})}let a=[];for(let n=0,o=e.length;n<o;n++){let o=e[n],s=mx(o),c=r[s];if(c)a.push(c.promise);else{let e;e=o.extensions&&o.extensions[Tb.KHR_DRACO_MESH_COMPRESSION]?i(o):xx(new q,o,t),r[s]={primitive:o,promise:e},a.push(e)}}return Promise.all(a)}loadMesh(e){let t=this,n=this.json,r=this.extensions,i=n.meshes[e],a=i.primitives,o=[];for(let e=0,t=a.length;e<t;e++){let t=a[e].material===void 0?lx(this.cache):this.getDependency(`material`,a[e].material);o.push(t)}return o.push(t.loadGeometries(a)),Promise.all(o).then(function(n){let o=n.slice(0,n.length-1),s=n[n.length-1],c=[];for(let n=0,l=s.length;n<l;n++){let l=s[n],u=a[n],d,f=o[n];if(u.mode===ex.TRIANGLES||u.mode===ex.TRIANGLE_STRIP||u.mode===ex.TRIANGLE_FAN||u.mode===void 0)d=i.isSkinnedMesh===!0?new Uo(l,f):new jo(l,f),d.isSkinnedMesh===!0&&d.normalizeSkinWeights(),u.mode===ex.TRIANGLE_STRIP?d.geometry=yb(d.geometry,1):u.mode===ex.TRIANGLE_FAN&&(d.geometry=yb(d.geometry,2));else if(u.mode===ex.LINES)d=new ws(l,f);else if(u.mode===ex.LINE_STRIP)d=new bs(l,f);else if(u.mode===ex.LINE_LOOP)d=new Ts(l,f);else if(u.mode===ex.POINTS)d=new js(l,f);else throw Error(`THREE.GLTFLoader: Primitive mode unsupported: `+u.mode);Object.keys(d.geometry.morphAttributes).length>0&&px(d,i),d.name=t.createUniqueName(i.name||`mesh_`+e),dx(d,i),u.extensions&&ux(r,d,u),t.assignFinalMaterial(d),c.push(d)}for(let n=0,r=c.length;n<r;n++)t.associations.set(c[n],{meshes:e,primitives:n});if(c.length===1)return i.extensions&&ux(r,c[0],i),c[0];let l=new Qi;i.extensions&&ux(r,l,i),t.associations.set(l,{meshes:e});for(let e=0,t=c.length;e<t;e++)l.add(c[e]);return l})}loadCamera(e){let t,n=this.json.cameras[e],r=n[n.type];if(!r){console.warn(`THREE.GLTFLoader: Missing camera parameters.`);return}return n.type===`perspective`?t=new Yc(ni.radToDeg(r.yfov),r.aspectRatio||1,r.znear||1,r.zfar||2e6):n.type===`orthographic`&&(t=new el(-r.xmag,r.xmag,r.ymag,-r.ymag,r.znear,r.zfar)),n.name&&(t.name=this.createUniqueName(n.name)),dx(t,n),Promise.resolve(t)}loadSkin(e){let t=this.json.skins[e],n=[];for(let e=0,r=t.joints.length;e<r;e++)n.push(this._loadNodeShallow(t.joints[e]));return t.inverseBindMatrices===void 0?n.push(null):n.push(this.getDependency(`accessor`,t.inverseBindMatrices)),Promise.all(n).then(function(e){let n=e.pop(),r=e,i=[],a=[];for(let e=0,o=r.length;e<o;e++){let o=r[e];if(o){i.push(o);let t=new W;n!==null&&t.fromArray(n.array,e*16),a.push(t)}else console.warn(`THREE.GLTFLoader: Joint "%s" could not be found.`,t.joints[e])}return new Jo(i,a)})}loadAnimation(e){let t=this.json,n=this,r=t.animations[e],i=r.name?r.name:`animation_`+e,a=[],o=[],s=[],c=[],l=[];for(let e=0,t=r.channels.length;e<t;e++){let t=r.channels[e],n=r.samplers[t.sampler],i=t.target,u=i.node,d=r.parameters===void 0?n.input:r.parameters[n.input],f=r.parameters===void 0?n.output:r.parameters[n.output];i.node!==void 0&&(a.push(this.getDependency(`node`,u)),o.push(this.getDependency(`accessor`,d)),s.push(this.getDependency(`accessor`,f)),c.push(n),l.push(i))}return Promise.all([Promise.all(a),Promise.all(o),Promise.all(s),Promise.all(c),Promise.all(l)]).then(function(e){let t=e[0],a=e[1],o=e[2],s=e[3],c=e[4],l=[];for(let e=0,r=t.length;e<r;e++){let r=t[e],i=a[e],u=o[e],d=s[e],f=c[e];if(r===void 0)continue;r.updateMatrix&&r.updateMatrix();let p=n._createAnimationTracks(r,i,u,d,f);if(p)for(let e=0;e<p.length;e++)l.push(p[e])}let u=new Cc(i,void 0,l);return dx(u,r),u})}createNodeMesh(e){let t=this.json,n=this,r=t.nodes[e];return r.mesh===void 0?null:n.getDependency(`mesh`,r.mesh).then(function(e){let t=n._getNodeRef(n.meshCache,r.mesh,e);return r.weights!==void 0&&t.traverse(function(e){if(e.isMesh)for(let t=0,n=r.weights.length;t<n;t++)e.morphTargetInfluences[t]=r.weights[t]}),t})}loadNode(e){let t=this.json,n=this,r=t.nodes[e],i=n._loadNodeShallow(e),a=[],o=r.children||[];for(let e=0,t=o.length;e<t;e++)a.push(n.getDependency(`node`,o[e]));let s=r.skin===void 0?Promise.resolve(null):n.getDependency(`skin`,r.skin);return Promise.all([i,Promise.all(a),s]).then(function(e){let t=e[0],n=e[1],r=e[2];r!==null&&t.traverse(function(e){e.isSkinnedMesh&&e.bind(r,vx)});for(let e=0,r=n.length;e<r;e++)t.add(n[e]);if(t.userData.pivot!==void 0&&n.length>0){let e=t.userData.pivot,r=n[0];t.pivot=new H().fromArray(e),t.position.x-=e[0],t.position.y-=e[1],t.position.z-=e[2],r.position.set(0,0,0),delete t.userData.pivot}return t})}_loadNodeShallow(e){let t=this.json,n=this.extensions,r=this;if(this.nodeCache[e]!==void 0)return this.nodeCache[e];let i=t.nodes[e],a=i.name?r.createUniqueName(i.name):``,o=[],s=r._invokeOne(function(t){return t.createNodeMesh&&t.createNodeMesh(e)});return s&&o.push(s),i.camera!==void 0&&o.push(r.getDependency(`camera`,i.camera).then(function(e){return r._getNodeRef(r.cameraCache,i.camera,e)})),r._invokeAll(function(t){return t.createNodeAttachment&&t.createNodeAttachment(e)}).forEach(function(e){o.push(e)}),this.nodeCache[e]=Promise.all(o).then(function(t){let o;if(o=i.isBone===!0?new Wo:t.length>1?new Qi:t.length===1?t[0]:new Zi,o!==t[0])for(let e=0,n=t.length;e<n;e++)o.add(t[e]);if(i.name&&(o.userData.name=i.name,o.name=a),dx(o,i),i.extensions&&ux(n,o,i),i.matrix!==void 0){let e=new W;e.fromArray(i.matrix),o.applyMatrix4(e)}else i.translation!==void 0&&o.position.fromArray(i.translation),i.rotation!==void 0&&o.quaternion.fromArray(i.rotation),i.scale!==void 0&&o.scale.fromArray(i.scale);if(!r.associations.has(o))r.associations.set(o,{});else if(i.mesh!==void 0&&r.meshCache.refs[i.mesh]>1){let e=r.associations.get(o);r.associations.set(o,{...e})}return r.associations.get(o).nodes=e,o}),this.nodeCache[e]}loadScene(e){let t=this.extensions,n=this.json.scenes[e],r=this,i=new Qi;n.name&&(i.name=r.createUniqueName(n.name)),dx(i,n),n.extensions&&ux(t,i,n);let a=n.nodes||[],o=[];for(let e=0,t=a.length;e<t;e++)o.push(r.getDependency(`node`,a[e]));return Promise.all(o).then(function(e){for(let t=0,n=e.length;t<n;t++){let n=e[t];n.parent===null?i.add(n):i.add(bb(n))}return r.associations=(e=>{let t=new Map;for(let[e,n]of r.associations)(e instanceof lo||e instanceof yi)&&t.set(e,n);return e.traverse(e=>{let n=r.associations.get(e);n!=null&&t.set(e,n)}),t})(i),i})}_createAnimationTracks(e,t,n,r,i){let a=[],o=e.name?e.name:e.uuid,s=[];function c(e){e.morphTargetInfluences&&s.push(e.name?e.name:e.uuid)}ox[i.path]===ox.weights?(c(e),e.isGroup&&e.children.forEach(c)):s.push(o);let l;switch(ox[i.path]){case ox.weights:l=vc;break;case ox.rotation:l=bc;break;case ox.translation:case ox.scale:l=Sc;break;default:switch(n.itemSize){case 1:l=vc;break;default:l=Sc;break}break}let u=r.interpolation===void 0?tr:sx[r.interpolation],d=this._getArrayFromAccessor(n);for(let e=0,n=s.length;e<n;e++){let n=new l(s[e]+`.`+ox[i.path],t.array,d,u);r.interpolation===`CUBICSPLINE`&&this._createCubicSplineTrackInterpolant(n),a.push(n)}return a}_getArrayFromAccessor(e){let t=e.array;if(e.normalized){let e=gx(t.constructor),n=new Float32Array(t.length);for(let r=0,i=t.length;r<i;r++)n[r]=t[r]*e;t=n}return t}_createCubicSplineTrackInterpolant(e){e.createInterpolant=function(e){return new(this instanceof bc?$b:Zb)(this.times,this.values,this.getValueSize()/3,e)},e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}};function bx(e,t,n){let r=t.attributes,i=new Sa;if(r.POSITION!==void 0){let e=n.json.accessors[r.POSITION],t=e.min,a=e.max;if(t!==void 0&&a!==void 0){if(i.set(new H(t[0],t[1],t[2]),new H(a[0],a[1],a[2])),e.normalized){let t=gx(tx[e.componentType]);i.min.multiplyScalar(t),i.max.multiplyScalar(t)}}else{console.warn(`THREE.GLTFLoader: Missing min/max properties for accessor POSITION.`);return}}else return;let a=t.targets;if(a!==void 0){let e=new H,t=new H;for(let r=0,i=a.length;r<i;r++){let i=a[r];if(i.POSITION!==void 0){let r=n.json.accessors[i.POSITION],a=r.min,o=r.max;if(a!==void 0&&o!==void 0){if(t.setX(Math.max(Math.abs(a[0]),Math.abs(o[0]))),t.setY(Math.max(Math.abs(a[1]),Math.abs(o[1]))),t.setZ(Math.max(Math.abs(a[2]),Math.abs(o[2]))),r.normalized){let e=gx(tx[r.componentType]);t.multiplyScalar(e)}e.max(t)}else console.warn(`THREE.GLTFLoader: Missing min/max properties for accessor POSITION.`)}}i.expandByVector(e)}e.boundingBox=i;let o=new Za;i.getCenter(o.center),o.radius=i.min.distanceTo(i.max)/2,e.boundingSphere=o}function xx(e,t,n){let r=t.attributes,i=[];function a(t,r){return n.getDependency(`accessor`,t).then(function(t){e.setAttribute(r,t)})}for(let t in r){let n=ax[t]||t.toLowerCase();n in e.attributes||i.push(a(r[t],n))}if(t.indices!==void 0&&!e.index){let r=n.getDependency(`accessor`,t.indices).then(function(t){e.setIndex(t)});i.push(r)}return li.workingColorSpace!==`srgb-linear`&&`COLOR_0`in r&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${li.workingColorSpace}" not supported.`),dx(e,t),bx(e,t,n),Promise.all(i).then(function(){return t.targets===void 0?e:fx(e,t.targets,n)})}var Sx=class{models=new Map;animations=new Map;modelKeys=new Map;animationKeys=new Map;loader;constructor(){this.loader=new Sb,this.loader.register(e=>new Hy(e))}load(e){for(let[t,n]of Object.entries(e)){let e=n;typeof e.url==`string`&&(e.type===`model`?this.modelKeys.set(`$${t}`,e.url):e.type===`animation`&&this.animationKeys.set(`$${t}`,{url:e.url,clip:e.clip}))}}animationRefs(){return[...this.animationKeys.keys()]}modelRefs(){return[...this.modelKeys.keys()]}getModel(e){let t=this.modelKeys.get(e)??e,n=this.models.get(t);return n||(n={status:`loading`,scene:null,animations:[],isVrm:!1,vrm:null,claimedBy:null,retargeted:new Map},this.models.set(t,n),this.loader.load(t,e=>{let t=e.userData.vrm;t?(vb.removeUnnecessaryVertices(e.scene),vb.combineSkeletons(e.scene),vb.rotateVRM0(t),n.scene=t.scene,n.vrm=t,n.isVrm=!0):n.scene=e.scene,n.animations=e.animations??[],n.status=`ready`},void 0,e=>{n.status=`error`,n.error=e instanceof Error?e.message:String(e),console.error(`incanto: failed to load model '${t}':`,e)}),n)}getAnimation(e){let t=this.animationKeys.get(e)??{url:e},n=this.animations.get(t.url);return n||(n={status:`loading`,clips:[],scene:null,clip:t.clip},this.animations.set(t.url,n),this.loader.load(t.url,e=>{n.clips=e.animations??[],n.scene=e.scene,n.status=`ready`,n.clips.length===0&&console.warn(`incanto: animation asset '${t.url}' contains no clips`)},void 0,e=>{n.status=`error`,n.error=e instanceof Error?e.message:String(e),console.error(`incanto: failed to load animation '${t.url}':`,e)}),n)}dispose(){for(let e of this.models.values())e.scene?.traverse(e=>{let t=e;t.geometry?.dispose();let n=Array.isArray(t.material)?t.material:[t.material];for(let e of n)if(e){for(let t of Object.values(e))t?.isTexture&&t.dispose();e.dispose()}});this.models.clear(),this.animations.clear()}},Cx=Math.atan(1/Math.SQRT2);function wx(e,t,n,r,i,a){let o=[t[0],t[1]+n,t[2]];if(e===`firstPerson`)return{position:o,rotation:[-i,r,0]};if(e===`quarter`){let e=Cx;return{position:[o[0],o[1]+a*Math.sin(e),o[2]+a*Math.cos(e)],rotation:[-e,0,0]}}if(e===`side`)return{position:[o[0],o[1],o[2]+a],rotation:[0,0,0]};let s=Math.cos(i);return{position:[o[0]+Math.sin(r)*s*a,o[1]+Math.sin(i)*a,o[2]+Math.cos(r)*s*a],rotation:[-i,r,0]}}function Tx(e,t,n,r,i){let a=t[0]-e[0],o=t[1]-e[1],s=t[2]-e[2],c=Math.hypot(a,o,s);if(c<1e-4)return[t[0],t[1],t[2]];let l=[a/c,o/c,s/c],u=n(e,l,c);if(u===null)return[t[0],t[1],t[2]];let d=Math.min(c,Math.max(i,u-r));return[e[0]+l[0]*d,e[1]+l[1]*d,e[2]+l[2]*d]}function Ex(e,t,n){let r=t(e,n);return r===null||r>=n?[e[0],e[1],e[2]]:[e[0],e[1]+(n-r),e[2]]}function Dx(e,t,n){let r=Math.sin(n),i=Math.cos(n);return[e*i-t*r,0,-e*r-t*i]}function Ox(e,t){return e?Math.min(.6+(t?.4:0),1):0}function kx(e,t){return e?t<=0?`idle`:t<.3?`walk`:t<.7?`run`:`fastRun`:`airborne`}var Ax=class extends qp{static typeName=`Joint3D`;static props={type:{default:`spherical`,options:[`fixed`,`spherical`,`rope`,`spring`]},target:{default:``},anchor:{default:[0,0,0]},targetAnchor:{default:[0,0,0]},length:{default:0},stiffness:{default:50},damping:{default:5}};type=`spherical`;target=``;anchor=[0,0,0];targetAnchor=[0,0,0];length=0;stiffness=50;damping=5;onEnterTree(){if(!(this.parent instanceof Jp))throw new y(`TREE_VIOLATION`,`Joint3D '${this.name}' must be a child of a physics body (its body A); parent is '${this.parent?.name??`none`}'.`);if(this.target===``)throw new y(`BAD_FORMAT`,`Joint3D '${this.name}' needs a "target" node path to the body it links to.`)}_resolveBodies(){let e=this.parent,t=this.getNodeOrNull(this.target);if(!(t instanceof Jp))throw new y(`NODE_NOT_FOUND`,`Joint3D '${this.name}': target '${this.target}' is not a physics body.`);return{a:e,b:t}}},jx=256,Mx=.3,Nx=.6,Px=45;function Fx(e){let{width:t,depth:n,segsX:r,segsZ:i,maxHeight:a,seed:o}=e,s=e.roughness??.5,c=e.detail??4,l=e.flatThreshold??.95,u=e.islandEdge??!1,d=Math.max(0,Math.min(e.edgeWrapRadius??20,Px)),f=e.edgeBottom??-50,p=e.edgeCornerSmoothness??1,m=(e.basins??[]).map(e=>({cx:e.x+t/2,cz:e.z+n/2,radius:e.radius,depth:e.depth})),h=(e.channels??[]).map(e=>({half:Math.max(e.width,0)/2,taper:Math.max(e.taper??e.width,.001),depth:e.depth,segs:e.path.map(e=>({x:(e[0]??0)+t/2,z:(e[1]??0)+n/2})).flatMap((e,t,n)=>t===0?[]:[{ax:n[t-1].x,az:n[t-1].z,bx:e.x,bz:e.z}])})).filter(e=>e.segs.length>0&&e.depth!==0),g=et(o),_=(e,t)=>(g(e,t)+1)*.5,v=(e,t)=>{let n=e/jx,r=t/jx,i=0,o=.2,u=5;for(let e=0;e<5;e++)i+=_(n*o,r*o)*u,u*=.5,o*=2;let d=0;o=.5,u=.1;for(let e=0;e<c;e++)d+=_(n*o,r*o)*u,u*=s,o*=2;i=Math.abs(i)**1.5*Math.sign(i),i<Mx&&(i*=.3);let f=a*(i+d*(i*.5+.5)+1)/2,p=a*l;if(Math.abs(f-p)<Nx&&(f=p),m.length>0){let n=0,r=0;for(let i of m){let a=Math.hypot(e-i.cx,t-i.cz);if(a<i.radius){let e=a/i.radius,t=1-e*e*(3-2*e);i.depth>=0?n=Math.max(n,i.depth*t):r=Math.max(r,-i.depth*t)}}f+=r-n}if(h.length>0){let n=0;for(let r of h){let i=1/0;for(let n of r.segs){let a=n.bx-n.ax,o=n.bz-n.az,s=a*a+o*o,c=s>1e-9?Math.min(1,Math.max(0,((e-n.ax)*a+(t-n.az)*o)/s)):0,l=n.ax+a*c,u=n.az+o*c,d=Math.hypot(e-l,t-u);if(d<i&&(i=d),i<=r.half)break}if(i>=r.half+r.taper)continue;let a=Math.min(1,Math.max(0,(i-r.half)/r.taper));n=Math.max(n,r.depth*(1-a*a*(3-2*a)))}f-=n}return f},y=(e,a,o)=>{if(!u||d<=0)return o;let s=d,c=Math.min(e,t-e),l=Math.min(a,n-a),m=(t/r+n/i)*.002,h=Math.max(0,s-c+m),g=Math.max(0,s-l+m);if(h<=0&&g<=0)return o;let _=2+(1-Math.min(1,Math.max(0,p)))*30,v=(h**_+g**_)**(1/_),y=o-(s-Math.sqrt(Math.max(0,s*s-v*v)));return v>=s&&(y=Math.min(y,f)),y},b=r+1,x=i+1,S=new Float32Array(b*x),C=1/0,w=-1/0;for(let e=0;e<x;e++){let a=e/i*n;for(let n=0;n<b;n++){let i=n/r*t,o=v(i,a);o<C&&(C=o),o>w&&(w=o),S[e*b+n]=y(i,a,o)}}let T=(e,a)=>{let o=Math.min(Math.max((e+t/2)/t*r,0),r),s=Math.min(Math.max((a+n/2)/n*i,0),i),c=Math.min(Math.floor(o),r-1),l=Math.min(Math.floor(s),i-1),u=o-c,d=s-l,f=S[l*b+c],p=S[l*b+c+1],m=S[(l+1)*b+c],h=S[(l+1)*b+c+1];return(f*(1-u)+p*u)*(1-d)+(m*(1-u)+h*u)*d},E=(e,r)=>v(e+t/2,r+n/2);return{width:t,depth:n,segsX:r,segsZ:i,heights:S,minHeight:C,maxHeight:w,heightAt:T,baseHeight:E,slopeAt:(e,t)=>{let n=(E(e+1,t)-E(e-1,t))/2,r=(E(e,t+1)-E(e,t-1))/2;return Math.atan(Math.sqrt(n*n+r*r))}}}function Ix(e,t,n,r){return e<t-r||e>n+r?0:e>=t&&e<=n?1:e<t?(e-(t-r))/r:(n+r-e)/r}function Lx(e,t,n,r=1.2){let i=[0,0,0,0],a=Math.min(n.length,4),o=0;for(let s=0;s<a;s++){let a=n[s],[c,l]=a.heightRange??[0,1],[u,d]=a.slopeRange??[0,Math.PI/2],f=Ix(e,c,l,a.heightBlendRange??.1)*Ix(t,u,d,a.slopeBlendRange??.1);f**=1/r,i[s]=f,o+=f}if(o===0)return[1,0,0,0];for(let e=0;e<4;e++)i[e]=i[e]/o;return i}function Rx(e,t,n){let r=e.indexOf(t);if(r===-1)throw new y(`BAD_FORMAT`,`Terrain3D shader patch: marker '${t}' not found in the three.js shader — the installed three version moved its chunks.`);let i=r+t.length;return`${e.slice(0,i)}\n${n}${e.slice(i)}`}var zx=`
|
|
6639
|
+
`;e.vertexShader=t+e.vertexShader,e.fragmentShader=t+e.fragmentShader}}get color(){return this.uniforms.litFactor.value}set color(e){this.uniforms.litFactor.value=e}get map(){return this.uniforms.map.value}set map(e){this.uniforms.map.value=e}get normalMap(){return this.uniforms.normalMap.value}set normalMap(e){this.uniforms.normalMap.value=e}get normalScale(){return this.uniforms.normalScale.value}set normalScale(e){this.uniforms.normalScale.value=e}get emissive(){return this.uniforms.emissive.value}set emissive(e){this.uniforms.emissive.value=e}get emissiveIntensity(){return this.uniforms.emissiveIntensity.value}set emissiveIntensity(e){this.uniforms.emissiveIntensity.value=e}get emissiveMap(){return this.uniforms.emissiveMap.value}set emissiveMap(e){this.uniforms.emissiveMap.value=e}get shadeColorFactor(){return this.uniforms.shadeColorFactor.value}set shadeColorFactor(e){this.uniforms.shadeColorFactor.value=e}get shadeMultiplyTexture(){return this.uniforms.shadeMultiplyTexture.value}set shadeMultiplyTexture(e){this.uniforms.shadeMultiplyTexture.value=e}get shadingShiftFactor(){return this.uniforms.shadingShiftFactor.value}set shadingShiftFactor(e){this.uniforms.shadingShiftFactor.value=e}get shadingShiftTexture(){return this.uniforms.shadingShiftTexture.value}set shadingShiftTexture(e){this.uniforms.shadingShiftTexture.value=e}get shadingShiftTextureScale(){return this.uniforms.shadingShiftTextureScale.value}set shadingShiftTextureScale(e){this.uniforms.shadingShiftTextureScale.value=e}get shadingToonyFactor(){return this.uniforms.shadingToonyFactor.value}set shadingToonyFactor(e){this.uniforms.shadingToonyFactor.value=e}get giEqualizationFactor(){return this.uniforms.giEqualizationFactor.value}set giEqualizationFactor(e){this.uniforms.giEqualizationFactor.value=e}get matcapFactor(){return this.uniforms.matcapFactor.value}set matcapFactor(e){this.uniforms.matcapFactor.value=e}get matcapTexture(){return this.uniforms.matcapTexture.value}set matcapTexture(e){this.uniforms.matcapTexture.value=e}get parametricRimColorFactor(){return this.uniforms.parametricRimColorFactor.value}set parametricRimColorFactor(e){this.uniforms.parametricRimColorFactor.value=e}get rimMultiplyTexture(){return this.uniforms.rimMultiplyTexture.value}set rimMultiplyTexture(e){this.uniforms.rimMultiplyTexture.value=e}get rimLightingMixFactor(){return this.uniforms.rimLightingMixFactor.value}set rimLightingMixFactor(e){this.uniforms.rimLightingMixFactor.value=e}get parametricRimFresnelPowerFactor(){return this.uniforms.parametricRimFresnelPowerFactor.value}set parametricRimFresnelPowerFactor(e){this.uniforms.parametricRimFresnelPowerFactor.value=e}get parametricRimLiftFactor(){return this.uniforms.parametricRimLiftFactor.value}set parametricRimLiftFactor(e){this.uniforms.parametricRimLiftFactor.value=e}get outlineWidthMultiplyTexture(){return this.uniforms.outlineWidthMultiplyTexture.value}set outlineWidthMultiplyTexture(e){this.uniforms.outlineWidthMultiplyTexture.value=e}get outlineWidthFactor(){return this.uniforms.outlineWidthFactor.value}set outlineWidthFactor(e){this.uniforms.outlineWidthFactor.value=e}get outlineColorFactor(){return this.uniforms.outlineColorFactor.value}set outlineColorFactor(e){this.uniforms.outlineColorFactor.value=e}get outlineLightingMixFactor(){return this.uniforms.outlineLightingMixFactor.value}set outlineLightingMixFactor(e){this.uniforms.outlineLightingMixFactor.value=e}get uvAnimationMaskTexture(){return this.uniforms.uvAnimationMaskTexture.value}set uvAnimationMaskTexture(e){this.uniforms.uvAnimationMaskTexture.value=e}get uvAnimationScrollXOffset(){return this.uniforms.uvAnimationScrollXOffset.value}set uvAnimationScrollXOffset(e){this.uniforms.uvAnimationScrollXOffset.value=e}get uvAnimationScrollYOffset(){return this.uniforms.uvAnimationScrollYOffset.value}set uvAnimationScrollYOffset(e){this.uniforms.uvAnimationScrollYOffset.value=e}get uvAnimationRotationPhase(){return this.uniforms.uvAnimationRotationPhase.value}set uvAnimationRotationPhase(e){this.uniforms.uvAnimationRotationPhase.value=e}get ignoreVertexColor(){return this._ignoreVertexColor}set ignoreVertexColor(e){this._ignoreVertexColor=e,this.needsUpdate=!0}get v0CompatShade(){return this._v0CompatShade}set v0CompatShade(e){this._v0CompatShade=e,this.needsUpdate=!0}get debugMode(){return this._debugMode}set debugMode(e){this._debugMode=e,this.needsUpdate=!0}get outlineWidthMode(){return this._outlineWidthMode}set outlineWidthMode(e){this._outlineWidthMode=e,this.needsUpdate=!0}get isOutline(){return this._isOutline}set isOutline(e){this._isOutline=e,this.needsUpdate=!0}get isMToonMaterial(){return!0}update(e){this._uploadUniformsWorkaround(),this._updateUVAnimation(e)}copy(e){return super.copy(e),this.map=e.map,this.normalMap=e.normalMap,this.emissiveMap=e.emissiveMap,this.shadeMultiplyTexture=e.shadeMultiplyTexture,this.shadingShiftTexture=e.shadingShiftTexture,this.matcapTexture=e.matcapTexture,this.rimMultiplyTexture=e.rimMultiplyTexture,this.outlineWidthMultiplyTexture=e.outlineWidthMultiplyTexture,this.uvAnimationMaskTexture=e.uvAnimationMaskTexture,this.normalMapType=e.normalMapType,this.uvAnimationScrollXSpeedFactor=e.uvAnimationScrollXSpeedFactor,this.uvAnimationScrollYSpeedFactor=e.uvAnimationScrollYSpeedFactor,this.uvAnimationRotationSpeedFactor=e.uvAnimationRotationSpeedFactor,this.ignoreVertexColor=e.ignoreVertexColor,this.v0CompatShade=e.v0CompatShade,this.debugMode=e.debugMode,this.outlineWidthMode=e.outlineWidthMode,this.isOutline=e.isOutline,this.needsUpdate=!0,this}_updateUVAnimation(e){this.uniforms.uvAnimationScrollXOffset.value+=e*this.uvAnimationScrollXSpeedFactor,this.uniforms.uvAnimationScrollYOffset.value+=e*this.uvAnimationScrollYSpeedFactor,this.uniforms.uvAnimationRotationPhase.value+=e*this.uvAnimationRotationSpeedFactor,this.uniforms.alphaTest.value=this.alphaTest,this.uniformsNeedUpdate=!0}_uploadUniformsWorkaround(){this.uniforms.opacity.value=this.opacity,this._updateTextureMatrix(this.uniforms.map,this.uniforms.mapUvTransform),this._updateTextureMatrix(this.uniforms.normalMap,this.uniforms.normalMapUvTransform),this._updateTextureMatrix(this.uniforms.emissiveMap,this.uniforms.emissiveMapUvTransform),this._updateTextureMatrix(this.uniforms.shadeMultiplyTexture,this.uniforms.shadeMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.shadingShiftTexture,this.uniforms.shadingShiftTextureUvTransform),this._updateTextureMatrix(this.uniforms.matcapTexture,this.uniforms.matcapTextureUvTransform),this._updateTextureMatrix(this.uniforms.rimMultiplyTexture,this.uniforms.rimMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.outlineWidthMultiplyTexture,this.uniforms.outlineWidthMultiplyTextureUvTransform),this._updateTextureMatrix(this.uniforms.uvAnimationMaskTexture,this.uniforms.uvAnimationMaskTextureUvTransform),this.uniformsNeedUpdate=!0}_generateDefines(){let e=this.outlineWidthMultiplyTexture!==null,t=this.map!==null||this.normalMap!==null||this.emissiveMap!==null||this.shadeMultiplyTexture!==null||this.shadingShiftTexture!==null||this.rimMultiplyTexture!==null||this.uvAnimationMaskTexture!==null;return{THREE_VRM_THREE_REVISION:184,OUTLINE:this._isOutline,MTOON_USE_UV:e||t,MTOON_UVS_VERTEX_ONLY:e&&!t,V0_COMPAT_SHADE:this._v0CompatShade,USE_SHADEMULTIPLYTEXTURE:this.shadeMultiplyTexture!==null,USE_SHADINGSHIFTTEXTURE:this.shadingShiftTexture!==null,USE_MATCAPTEXTURE:this.matcapTexture!==null,USE_RIMMULTIPLYTEXTURE:this.rimMultiplyTexture!==null,USE_OUTLINEWIDTHMULTIPLYTEXTURE:this._isOutline&&this.outlineWidthMultiplyTexture!==null,USE_UVANIMATIONMASKTEXTURE:this.uvAnimationMaskTexture!==null,IGNORE_VERTEX_COLOR:this._ignoreVertexColor===!0,DEBUG_NORMAL:this._debugMode===`normal`,DEBUG_LITSHADERATE:this._debugMode===`litShadeRate`,DEBUG_UV:this._debugMode===`uv`,OUTLINE_WIDTH_SCREEN:this._isOutline&&this._outlineWidthMode===_v.ScreenCoordinates}}_updateTextureMatrix(e,t){e.value&&(e.value.matrixAutoUpdate&&e.value.updateMatrix(),t.value.copy(e.value.matrix))}},bv=new Set([`1.0`,`1.0-beta`]),xv=class e{get name(){return e.EXTENSION_NAME}constructor(e,t={}){this.parser=e,this.materialType=t.materialType??yv,this.renderOrderOffset=t.renderOrderOffset??0,this.v0CompatShade=t.v0CompatShade??!1,this.debugMode=t.debugMode??`none`,this._mToonMaterialSet=new Set}beforeRoot(){return dv(this,null,function*(){this._removeUnlitExtensionIfMToonExists()})}afterRoot(e){return dv(this,null,function*(){e.userData.vrmMToonMaterials=Array.from(this._mToonMaterialSet)})}getMaterialType(e){return this._getMToonExtension(e)?this.materialType:null}extendMaterialParams(e,t){let n=this._getMToonExtension(e);return n?this._extendMaterialParams(n,t):null}loadMesh(e){return dv(this,null,function*(){let t=this.parser,n=t.json.meshes?.[e];if(n==null)throw Error(`MToonMaterialLoaderPlugin: Attempt to use meshes[${e}] of glTF but the mesh doesn't exist`);let r=n.primitives,i=yield t.loadMesh(e);if(r.length===1){let e=i,t=r[0].material;t!=null&&this._setupPrimitive(e,t)}else{let e=i;for(let t=0;t<r.length;t++){let n=e.children[t],i=r[t].material;i!=null&&this._setupPrimitive(n,i)}}return i})}_removeUnlitExtensionIfMToonExists(){this.parser.json.materials?.map((e,t)=>{this._getMToonExtension(t)&&e.extensions?.KHR_materials_unlit&&delete e.extensions.KHR_materials_unlit})}_getMToonExtension(t){let n=this.parser.json.materials?.[t];if(n==null){console.warn(`MToonMaterialLoaderPlugin: Attempt to use materials[${t}] of glTF but the material doesn't exist`);return}let r=n.extensions?.[e.EXTENSION_NAME];if(r==null)return;let i=r.specVersion;if(!bv.has(i)){console.warn(`MToonMaterialLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${i}"`);return}return r}_extendMaterialParams(e,t){return dv(this,null,function*(){delete t.metalness,delete t.roughness;let n=new pv(this.parser,t);n.assignPrimitive(`transparentWithZWrite`,e.transparentWithZWrite),n.assignColor(`shadeColorFactor`,e.shadeColorFactor),n.assignTexture(`shadeMultiplyTexture`,e.shadeMultiplyTexture,!0),n.assignPrimitive(`shadingShiftFactor`,e.shadingShiftFactor),n.assignTexture(`shadingShiftTexture`,e.shadingShiftTexture,!0),n.assignPrimitive(`shadingShiftTextureScale`,e.shadingShiftTexture?.scale),n.assignPrimitive(`shadingToonyFactor`,e.shadingToonyFactor),n.assignPrimitive(`giEqualizationFactor`,e.giEqualizationFactor),n.assignColor(`matcapFactor`,e.matcapFactor),n.assignTexture(`matcapTexture`,e.matcapTexture,!0),n.assignColor(`parametricRimColorFactor`,e.parametricRimColorFactor),n.assignTexture(`rimMultiplyTexture`,e.rimMultiplyTexture,!0),n.assignPrimitive(`rimLightingMixFactor`,e.rimLightingMixFactor),n.assignPrimitive(`parametricRimFresnelPowerFactor`,e.parametricRimFresnelPowerFactor),n.assignPrimitive(`parametricRimLiftFactor`,e.parametricRimLiftFactor),n.assignPrimitive(`outlineWidthMode`,e.outlineWidthMode),n.assignPrimitive(`outlineWidthFactor`,e.outlineWidthFactor),n.assignTexture(`outlineWidthMultiplyTexture`,e.outlineWidthMultiplyTexture,!1),n.assignColor(`outlineColorFactor`,e.outlineColorFactor),n.assignPrimitive(`outlineLightingMixFactor`,e.outlineLightingMixFactor),n.assignTexture(`uvAnimationMaskTexture`,e.uvAnimationMaskTexture,!1),n.assignPrimitive(`uvAnimationScrollXSpeedFactor`,e.uvAnimationScrollXSpeedFactor),n.assignPrimitive(`uvAnimationScrollYSpeedFactor`,e.uvAnimationScrollYSpeedFactor),n.assignPrimitive(`uvAnimationRotationSpeedFactor`,e.uvAnimationRotationSpeedFactor),n.assignPrimitive(`v0CompatShade`,this.v0CompatShade),n.assignPrimitive(`debugMode`,this.debugMode),yield n.pending})}_setupPrimitive(e,t){let n=this._getMToonExtension(t);if(n){e.renderOrder=this._parseRenderOrder(n)+this.renderOrderOffset,this._generateOutline(e),this._addToMaterialSet(e);return}}_shouldGenerateOutline(e){return typeof e.outlineWidthMode==`string`&&e.outlineWidthMode!==`none`&&typeof e.outlineWidthFactor==`number`&&e.outlineWidthFactor>0}_generateOutline(e){let t=e.material;if(!(t instanceof lo)||!this._shouldGenerateOutline(t))return;e.material=[t];let n=t.clone();n.name+=` (Outline)`,n.isOutline=!0,n.side=1,e.material.push(n);let r=e.geometry,i=r.index?r.index.count:r.attributes.position.count/3;r.addGroup(0,i,0),r.addGroup(0,i,1)}_addToMaterialSet(e){let t=e.material,n=new Set;Array.isArray(t)?t.forEach(e=>n.add(e)):n.add(t);for(let e of n)this._mToonMaterialSet.add(e)}_parseRenderOrder(e){return(e.transparentWithZWrite?0:19)+(e.renderQueueOffsetNumber??0)}};xv.EXTENSION_NAME=`VRMC_materials_mtoon`;var Sv=xv,Cv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),wv=class e{get name(){return e.EXTENSION_NAME}constructor(e){this.parser=e}extendMaterialParams(e,t){return Cv(this,null,function*(){let n=this._getHDREmissiveMultiplierExtension(e);n!=null&&(console.warn("VRMMaterialsHDREmissiveMultiplierLoaderPlugin: `VRMC_materials_hdr_emissiveMultiplier` is archived. Use `KHR_materials_emissive_strength` instead."),t.emissiveIntensity=n.emissiveMultiplier)})}_getHDREmissiveMultiplierExtension(t){let n=this.parser.json.materials?.[t];if(n==null){console.warn(`VRMMaterialsHDREmissiveMultiplierLoaderPlugin: Attempt to use materials[${t}] of glTF but the material doesn't exist`);return}let r=n.extensions?.[e.EXTENSION_NAME];if(r!=null)return r}};wv.EXTENSION_NAME=`VRMC_materials_hdr_emissiveMultiplier`;var Tv=wv,Ev=Object.defineProperty,Dv=Object.defineProperties,Ov=Object.getOwnPropertyDescriptors,kv=Object.getOwnPropertySymbols,Av=Object.prototype.hasOwnProperty,jv=Object.prototype.propertyIsEnumerable,Mv=(e,t,n)=>t in e?Ev(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Nv=(e,t)=>{for(var n in t||={})Av.call(t,n)&&Mv(e,n,t[n]);if(kv)for(var n of kv(t))jv.call(t,n)&&Mv(e,n,t[n]);return e},Pv=(e,t)=>Dv(e,Ov(t)),Fv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())});function Iv(e){return e**2.2}var Lv=class{get name(){return`VRMMaterialsV0CompatPlugin`}constructor(e){this.parser=e,this._renderQueueMapTransparent=new Map,this._renderQueueMapTransparentZWrite=new Map;let t=this.parser.json;t.extensionsUsed=t.extensionsUsed??[],t.extensionsUsed.indexOf(`KHR_texture_transform`)===-1&&t.extensionsUsed.push(`KHR_texture_transform`)}beforeRoot(){return Fv(this,null,function*(){let e=this.parser.json,t=e.extensions?.VRM?.materialProperties;t&&(this._populateRenderQueueMap(t),t.forEach((t,n)=>{let r=e.materials?.[n];if(r==null){console.warn(`VRMMaterialsV0CompatPlugin: Attempt to use materials[${n}] of glTF but the material doesn't exist`);return}if(t.shader===`VRM/MToon`){let i=this._parseV0MToonProperties(t,r);e.materials[n]=i}else if(t.shader?.startsWith(`VRM/Unlit`)){let i=this._parseV0UnlitProperties(t,r);e.materials[n]=i}else t.shader===`VRM_USE_GLTFSHADER`||console.warn(`VRMMaterialsV0CompatPlugin: Unknown shader: ${t.shader}`)}))})}_parseV0MToonProperties(e,t){let n=e.keywordMap?._ALPHABLEND_ON??!1,r=e.floatProperties?._ZWrite===1&&n,i=this._v0ParseRenderQueue(e),a=e.keywordMap?._ALPHATEST_ON??!1,o=n?`BLEND`:a?`MASK`:`OPAQUE`,s=a?e.floatProperties?._Cutoff??.5:void 0,c=(e.floatProperties?._CullMode??2)===0,l=this._portTextureTransform(e),u=(e.vectorProperties?._Color??[1,1,1,1]).map((e,t)=>t===3?e:Iv(e)),d=e.textureProperties?._MainTex,f=d==null?void 0:{index:d,extensions:Nv({},l)},p=e.floatProperties?._BumpScale??1,m=e.textureProperties?._BumpMap,h=m==null?void 0:{index:m,scale:p,extensions:Nv({},l)},g=(e.vectorProperties?._EmissionColor??[0,0,0,1]).map(Iv),_=e.textureProperties?._EmissionMap,v=_==null?void 0:{index:_,extensions:Nv({},l)},y=(e.vectorProperties?._ShadeColor??[.97,.81,.86,1]).map(Iv),b=e.textureProperties?._ShadeTexture,x=b==null?void 0:{index:b,extensions:Nv({},l)},S=e.floatProperties?._ShadeShift??0,C=e.floatProperties?._ShadeToony??.9;C=ni.lerp(C,1,.5+.5*S),S=-S-(1-C);let w=e.floatProperties?._IndirectLightIntensity??.1,T=w?1-w:void 0,E=e.textureProperties?._SphereAdd,D=E==null?void 0:[1,1,1],O=E==null?void 0:{index:E},k=e.floatProperties?._RimLightingMix??0,A=e.textureProperties?._RimTexture,ee=A==null?void 0:{index:A,extensions:Nv({},l)},te=(e.vectorProperties?._RimColor??[0,0,0,1]).map(Iv),ne=e.floatProperties?._RimFresnelPower??1,re=e.floatProperties?._RimLift??0,ie=[`none`,`worldCoordinates`,`screenCoordinates`][e.floatProperties?._OutlineWidthMode??0],ae=e.floatProperties?._OutlineWidth??0;ae=.01*ae;let oe=e.textureProperties?._OutlineWidthTexture,se=oe==null?void 0:{index:oe,extensions:Nv({},l)},ce=(e.vectorProperties?._OutlineColor??[0,0,0]).map(Iv),le=(e.floatProperties?._OutlineColorMode??0)===1?e.floatProperties?._OutlineLightingMix??1:0,ue=e.textureProperties?._UvAnimMaskTexture,de=ue==null?void 0:{index:ue,extensions:Nv({},l)},j=e.floatProperties?._UvAnimScrollX??0,fe=e.floatProperties?._UvAnimScrollY??0;fe!=null&&(fe=-fe);let pe=e.floatProperties?._UvAnimRotation??0,M={specVersion:`1.0`,transparentWithZWrite:r,renderQueueOffsetNumber:i,shadeColorFactor:y,shadeMultiplyTexture:x,shadingShiftFactor:S,shadingToonyFactor:C,giEqualizationFactor:T,matcapFactor:D,matcapTexture:O,rimLightingMixFactor:k,rimMultiplyTexture:ee,parametricRimColorFactor:te,parametricRimFresnelPowerFactor:ne,parametricRimLiftFactor:re,outlineWidthMode:ie,outlineWidthFactor:ae,outlineWidthMultiplyTexture:se,outlineColorFactor:ce,outlineLightingMixFactor:le,uvAnimationMaskTexture:de,uvAnimationScrollXSpeedFactor:j,uvAnimationScrollYSpeedFactor:fe,uvAnimationRotationSpeedFactor:pe};return Pv(Nv({},t),{pbrMetallicRoughness:{baseColorFactor:u,baseColorTexture:f},normalTexture:h,emissiveTexture:v,emissiveFactor:g,alphaMode:o,alphaCutoff:s,doubleSided:c,extensions:{VRMC_materials_mtoon:M}})}_parseV0UnlitProperties(e,t){let n=e.shader===`VRM/UnlitTransparentZWrite`,r=e.shader===`VRM/UnlitTransparent`||n,i=this._v0ParseRenderQueue(e),a=e.shader===`VRM/UnlitCutout`,o=r?`BLEND`:a?`MASK`:`OPAQUE`,s=a?e.floatProperties?._Cutoff??.5:void 0,c=this._portTextureTransform(e),l=(e.vectorProperties?._Color??[1,1,1,1]).map(Iv),u=e.textureProperties?._MainTex,d=u==null?void 0:{index:u,extensions:Nv({},c)},f={specVersion:`1.0`,transparentWithZWrite:n,renderQueueOffsetNumber:i,shadeColorFactor:l,shadeMultiplyTexture:d};return Pv(Nv({},t),{pbrMetallicRoughness:{baseColorFactor:l,baseColorTexture:d},alphaMode:o,alphaCutoff:s,extensions:{VRMC_materials_mtoon:f}})}_portTextureTransform(e){let t=e.vectorProperties?._MainTex;if(t==null)return{};let n=[t?.[0]??0,t?.[1]??0],r=[t?.[2]??1,t?.[3]??1];return n[1]=1-r[1]-n[1],{KHR_texture_transform:{offset:n,scale:r}}}_v0ParseRenderQueue(e){let t=e.shader===`VRM/UnlitTransparentZWrite`,n=e.keywordMap?._ALPHABLEND_ON!=null||e.shader===`VRM/UnlitTransparent`||t,r=e.floatProperties?._ZWrite===1||t,i=0;if(n){let t=e.renderQueue;t!=null&&(i=r?this._renderQueueMapTransparentZWrite.get(t):this._renderQueueMapTransparent.get(t))}return i}_populateRenderQueueMap(e){let t=new Set,n=new Set;e.forEach(e=>{let r=e.shader===`VRM/UnlitTransparentZWrite`,i=e.keywordMap?._ALPHABLEND_ON!=null||e.shader===`VRM/UnlitTransparent`||r,a=e.floatProperties?._ZWrite===1||r;if(i){let r=e.renderQueue;r!=null&&(a?n.add(r):t.add(r))}}),t.size>10&&console.warn(`VRMMaterialsV0CompatPlugin: This VRM uses ${t.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`),n.size>10&&console.warn(`VRMMaterialsV0CompatPlugin: This VRM uses ${n.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`),Array.from(t).sort().forEach((e,n)=>{let r=Math.min(Math.max(n-t.size+1,-9),0);this._renderQueueMapTransparent.set(e,r)}),Array.from(n).sort().forEach((e,t)=>{let n=Math.min(Math.max(t,0),9);this._renderQueueMapTransparentZWrite.set(e,n)})}},Rv=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),zv=new H,Bv=class extends Qi{constructor(e){super(),this._attrPosition=new K(new Float32Array([0,0,0,0,0,0]),3),this._attrPosition.setUsage(_r);let t=new q;t.setAttribute(`position`,this._attrPosition);let n=new fs({color:16711935,depthTest:!1,depthWrite:!1});this._line=new bs(t,n),this.add(this._line),this.constraint=e}updateMatrixWorld(e){zv.setFromMatrixPosition(this.constraint.destination.matrixWorld),this._attrPosition.setXYZ(0,zv.x,zv.y,zv.z),this.constraint.source&&zv.setFromMatrixPosition(this.constraint.source.matrixWorld),this._attrPosition.setXYZ(1,zv.x,zv.y,zv.z),this._attrPosition.needsUpdate=!0,super.updateMatrixWorld(e)}};function Vv(e,t){return t.set(e.elements[12],e.elements[13],e.elements[14])}var Hv=new H,Uv=new H;function Wv(e,t){return e.decompose(Hv,t,Uv),t}function Gv(e){return e.invert?e.invert():e.inverse(),e}var Kv=class{constructor(e,t){this.destination=e,this.source=t,this.weight=1}},qv=new H,Jv=new H,Yv=new H,Xv=new V,Zv=new V,Qv=new V,$v=class extends Kv{get aimAxis(){return this._aimAxis}set aimAxis(e){this._aimAxis=e,this._v3AimAxis.set(e===`PositiveX`?1:e===`NegativeX`?-1:0,e===`PositiveY`?1:e===`NegativeY`?-1:0,e===`PositiveZ`?1:e===`NegativeZ`?-1:0)}get dependencies(){let e=new Set([this.source]);return this.destination.parent&&e.add(this.destination.parent),e}constructor(e,t){super(e,t),this._aimAxis=`PositiveX`,this._v3AimAxis=new H(1,0,0),this._dstRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion)}update(){this.destination.updateWorldMatrix(!0,!1),this.source.updateWorldMatrix(!0,!1);let e=Xv.identity(),t=Zv.identity();this.destination.parent&&(Wv(this.destination.parent.matrixWorld,e),Gv(t.copy(e)));let n=qv.copy(this._v3AimAxis).applyQuaternion(this._dstRestQuat).applyQuaternion(e),r=Vv(this.source.matrixWorld,Jv).sub(Vv(this.destination.matrixWorld,Yv)).normalize(),i=Qv.setFromUnitVectors(n,r).premultiply(t).multiply(e).multiply(this._dstRestQuat);this.destination.quaternion.copy(this._dstRestQuat).slerp(i,this.weight)}};function ey(e,t){let n=[e],r=e.parent;for(;r!==null;)n.unshift(r),r=r.parent;n.forEach(e=>{t(e)})}var ty=class{constructor(){this._constraints=new Set,this._objectConstraintsMap=new Map}get constraints(){return this._constraints}addConstraint(e){this._constraints.add(e);let t=this._objectConstraintsMap.get(e.destination);t??(t=new Set,this._objectConstraintsMap.set(e.destination,t)),t.add(e)}deleteConstraint(e){this._constraints.delete(e),this._objectConstraintsMap.get(e.destination).delete(e)}setInitState(){let e=new Set,t=new Set;for(let n of this._constraints)this._processConstraint(n,e,t,e=>e.setInitState())}update(){let e=new Set,t=new Set;for(let n of this._constraints)this._processConstraint(n,e,t,e=>e.update())}_processConstraint(e,t,n,r){if(n.has(e))return;if(t.has(e))throw Error(`VRMNodeConstraintManager: Circular dependency detected while updating constraints`);t.add(e);let i=e.dependencies;for(let e of i)ey(e,e=>{let i=this._objectConstraintsMap.get(e);if(i)for(let e of i)this._processConstraint(e,t,n,r)});r(e),n.add(e)}},ny=new V,ry=new V,iy=class extends Kv{get dependencies(){return new Set([this.source])}constructor(e,t){super(e,t),this._dstRestQuat=new V,this._invSrcRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion),Gv(this._invSrcRestQuat.copy(this.source.quaternion))}update(){let e=ny.copy(this._invSrcRestQuat).multiply(this.source.quaternion),t=ry.copy(this._dstRestQuat).multiply(e);this.destination.quaternion.copy(this._dstRestQuat).slerp(t,this.weight)}},ay=new H,oy=new V,sy=new V,cy=class extends Kv{get rollAxis(){return this._rollAxis}set rollAxis(e){this._rollAxis=e,this._v3RollAxis.set(+(e===`X`),+(e===`Y`),+(e===`Z`))}get dependencies(){return new Set([this.source])}constructor(e,t){super(e,t),this._rollAxis=`X`,this._v3RollAxis=new H(1,0,0),this._dstRestQuat=new V,this._invDstRestQuat=new V,this._invSrcRestQuatMulDstRestQuat=new V}setInitState(){this._dstRestQuat.copy(this.destination.quaternion),Gv(this._invDstRestQuat.copy(this._dstRestQuat)),Gv(this._invSrcRestQuatMulDstRestQuat.copy(this.source.quaternion)).multiply(this._dstRestQuat)}update(){let e=oy.copy(this._invDstRestQuat).multiply(this.source.quaternion).multiply(this._invSrcRestQuatMulDstRestQuat),t=ay.copy(this._v3RollAxis).applyQuaternion(e),n=sy.setFromUnitVectors(t,this._v3RollAxis).premultiply(this._dstRestQuat).multiply(e);this.destination.quaternion.copy(this._dstRestQuat).slerp(n,this.weight)}},ly=new Set([`1.0`,`1.0-beta`]),uy=class e{get name(){return e.EXTENSION_NAME}constructor(e,t){this.parser=e,this.helperRoot=t?.helperRoot}afterRoot(e){return Rv(this,null,function*(){e.userData.vrmNodeConstraintManager=yield this._import(e)})}_import(t){return Rv(this,null,function*(){let n=this.parser.json;if(n.extensionsUsed?.indexOf(e.EXTENSION_NAME)===-1)return null;let r=new ty,i=yield this.parser.getDependencies(`node`);return i.forEach((t,a)=>{let o=n.nodes[a]?.extensions?.[e.EXTENSION_NAME];if(o==null)return;let s=o.specVersion;if(!ly.has(s)){console.warn(`VRMNodeConstraintLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${s}"`);return}let c=o.constraint;if(c.roll!=null){let e=this._importRollConstraint(t,i,c.roll);r.addConstraint(e)}else if(c.aim!=null){let e=this._importAimConstraint(t,i,c.aim);r.addConstraint(e)}else if(c.rotation!=null){let e=this._importRotationConstraint(t,i,c.rotation);r.addConstraint(e)}}),t.scene.updateMatrixWorld(),r.setInitState(),r})}_importRollConstraint(e,t,n){let{source:r,rollAxis:i,weight:a}=n,o=t[r],s=new cy(e,o);if(i!=null&&(s.rollAxis=i),a!=null&&(s.weight=a),this.helperRoot){let e=new Bv(s);this.helperRoot.add(e)}return s}_importAimConstraint(e,t,n){let{source:r,aimAxis:i,weight:a}=n,o=t[r],s=new $v(e,o);if(i!=null&&(s.aimAxis=i),a!=null&&(s.weight=a),this.helperRoot){let e=new Bv(s);this.helperRoot.add(e)}return s}_importRotationConstraint(e,t,n){let{source:r,weight:i}=n,a=t[r],o=new iy(e,a);if(i!=null&&(o.weight=i),this.helperRoot){let e=new Bv(o);this.helperRoot.add(e)}return o}};uy.EXTENSION_NAME=`VRMC_node_constraint`;var dy=uy,fy=(e,t,n)=>new Promise((r,i)=>{var a=e=>{try{s(n.next(e))}catch(e){i(e)}},o=e=>{try{s(n.throw(e))}catch(e){i(e)}},s=e=>e.done?r(e.value):Promise.resolve(e.value).then(a,o);s((n=n.apply(e,t)).next())}),py=class{},my=new H,hy=new H,gy=class extends py{get type(){return`capsule`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.tail=e?.tail??new H(0,0,0),this.radius=e?.radius??0,this.inside=e?.inside??!1}calculateCollision(e,t,n,r){my.setFromMatrixPosition(e),hy.subVectors(this.tail,this.offset).applyMatrix4(e),hy.sub(my);let i=hy.lengthSq();r.copy(t).sub(my);let a=hy.dot(r);a<=0||(i<=a||hy.multiplyScalar(a/i),r.sub(hy));let o=r.length(),s=this.inside?this.radius-n-o:o-n-this.radius;return s<0&&(r.multiplyScalar(1/o),this.inside&&r.negate()),s}},_y=new H,vy=new U,yy=class extends py{get type(){return`plane`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.normal=e?.normal??new H(0,0,1)}calculateCollision(e,t,n,r){r.setFromMatrixPosition(e),r.negate().add(t),vy.getNormalMatrix(e),_y.copy(this.normal).applyNormalMatrix(vy).normalize();let i=r.dot(_y)-n;return r.copy(_y),i}},by=new H,xy=class extends py{get type(){return`sphere`}constructor(e){super(),this.offset=e?.offset??new H(0,0,0),this.radius=e?.radius??0,this.inside=e?.inside??!1}calculateCollision(e,t,n,r){r.subVectors(t,by.setFromMatrixPosition(e));let i=r.length(),a=this.inside?this.radius-n-i:i-n-this.radius;return a<0&&(r.multiplyScalar(1/i),this.inside&&r.negate()),a}},Sy=new H,Cy=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentOffset=new H,this._currentTail=new H,this._shape=e,this._attrPos=new K(new Float32Array(396),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(264),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._shape.radius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0);let n=Sy.copy(this._shape.tail).divideScalar(this.worldScale);this._currentTail.distanceToSquared(n)>1e-10&&(this._currentTail.copy(n),e=!0),e&&this._buildPosition()}_buildPosition(){Sy.copy(this._currentTail).sub(this._currentOffset);let e=Sy.length()/this._currentRadius;for(let t=0;t<=16;t++){let n=t/16*Math.PI;this._attrPos.setXYZ(t,-Math.sin(n),-Math.cos(n),0),this._attrPos.setXYZ(17+t,e+Math.sin(n),Math.cos(n),0),this._attrPos.setXYZ(34+t,-Math.sin(n),0,-Math.cos(n)),this._attrPos.setXYZ(51+t,e+Math.sin(n),0,Math.cos(n))}for(let t=0;t<32;t++){let n=t/16*Math.PI;this._attrPos.setXYZ(68+t,0,Math.sin(n),Math.cos(n)),this._attrPos.setXYZ(100+t,e,Math.sin(n),Math.cos(n))}let t=Math.atan2(Sy.y,Math.sqrt(Sy.x*Sy.x+Sy.z*Sy.z)),n=-Math.atan2(Sy.z,Sy.x);this.rotateZ(t),this.rotateY(n),this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<34;e++){let t=(e+1)%34;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(68+e*2,34+e,34+t)}for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(136+e*2,68+e,68+t),this._attrIndex.setXY(200+e*2,100+e,100+t)}this._attrIndex.needsUpdate=!0}},wy=class extends q{constructor(e){super(),this.worldScale=1,this._currentOffset=new H,this._currentNormal=new H,this._shape=e,this._attrPos=new K(new Float32Array(18),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(10),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1;this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0),this._currentNormal.equals(this._shape.normal)||(this._currentNormal.copy(this._shape.normal),e=!0),e&&this._buildPosition()}_buildPosition(){this._attrPos.setXYZ(0,-.5,-.5,0),this._attrPos.setXYZ(1,.5,-.5,0),this._attrPos.setXYZ(2,.5,.5,0),this._attrPos.setXYZ(3,-.5,.5,0),this._attrPos.setXYZ(4,0,0,0),this._attrPos.setXYZ(5,0,0,.25),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this.lookAt(this._currentNormal),this._attrPos.needsUpdate=!0}_buildIndex(){this._attrIndex.setXY(0,0,1),this._attrIndex.setXY(2,1,2),this._attrIndex.setXY(4,2,3),this._attrIndex.setXY(6,3,0),this._attrIndex.setXY(8,4,5),this._attrIndex.needsUpdate=!0}},Ty=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentOffset=new H,this._shape=e,this._attrPos=new K(new Float32Array(288),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(192),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._shape.radius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentOffset.equals(this._shape.offset)||(this._currentOffset.copy(this._shape.offset),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentOffset.x,this._currentOffset.y,this._currentOffset.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.needsUpdate=!0}},Ey=new H,Dy=class extends Qi{constructor(e){if(super(),this.matrixAutoUpdate=!1,this.collider=e,this.collider.shape instanceof xy)this._geometry=new Ty(this.collider.shape);else if(this.collider.shape instanceof gy)this._geometry=new Cy(this.collider.shape);else if(this.collider.shape instanceof yy)this._geometry=new wy(this.collider.shape);else throw Error(`VRMSpringBoneColliderHelper: Unknown collider shape type detected`);let t=new fs({color:16711935,depthTest:!1,depthWrite:!1});this._line=new ws(this._geometry,t),this.add(this._line)}dispose(){this._geometry.dispose()}updateMatrixWorld(e){this.collider.updateWorldMatrix(!0,!1),this.matrix.copy(this.collider.matrixWorld);let t=this.matrix.elements;this._geometry.worldScale=Ey.set(t[0],t[1],t[2]).length(),this._geometry.update(),super.updateMatrixWorld(e)}},Oy=class extends q{constructor(e){super(),this.worldScale=1,this._currentRadius=0,this._currentTail=new H,this._springBone=e,this._attrPos=new K(new Float32Array(294),3),this.setAttribute(`position`,this._attrPos),this._attrIndex=new K(new Uint16Array(194),1),this.setIndex(this._attrIndex),this._buildIndex(),this.update()}update(){let e=!1,t=this._springBone.settings.hitRadius/this.worldScale;this._currentRadius!==t&&(this._currentRadius=t,e=!0),this._currentTail.equals(this._springBone.initialLocalChildPosition)||(this._currentTail.copy(this._springBone.initialLocalChildPosition),e=!0),e&&this._buildPosition()}_buildPosition(){for(let e=0;e<32;e++){let t=e/16*Math.PI;this._attrPos.setXYZ(e,Math.cos(t),Math.sin(t),0),this._attrPos.setXYZ(32+e,0,Math.cos(t),Math.sin(t)),this._attrPos.setXYZ(64+e,Math.sin(t),0,Math.cos(t))}this.scale(this._currentRadius,this._currentRadius,this._currentRadius),this.translate(this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.setXYZ(96,0,0,0),this._attrPos.setXYZ(97,this._currentTail.x,this._currentTail.y,this._currentTail.z),this._attrPos.needsUpdate=!0}_buildIndex(){for(let e=0;e<32;e++){let t=(e+1)%32;this._attrIndex.setXY(e*2,e,t),this._attrIndex.setXY(64+e*2,32+e,32+t),this._attrIndex.setXY(128+e*2,64+e,64+t)}this._attrIndex.setXY(192,96,97),this._attrIndex.needsUpdate=!0}},ky=new H,Ay=class extends Qi{constructor(e){super(),this.matrixAutoUpdate=!1,this.springBone=e,this._geometry=new Oy(this.springBone);let t=new fs({color:16776960,depthTest:!1,depthWrite:!1});this._line=new ws(this._geometry,t),this.add(this._line)}dispose(){this._geometry.dispose()}updateMatrixWorld(e){this.springBone.bone.updateWorldMatrix(!0,!1),this.matrix.copy(this.springBone.bone.matrixWorld);let t=this.matrix.elements;this._geometry.worldScale=ky.set(t[0],t[1],t[2]).length(),this._geometry.update(),super.updateMatrixWorld(e)}},jy=class extends Zi{constructor(e){super(),this.colliderMatrix=new W,this.shape=e}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),My(this.colliderMatrix,this.matrixWorld,this.shape.offset)}};function My(e,t,n){let r=t.elements;e.copy(t),n&&(e.elements[12]=r[0]*n.x+r[4]*n.y+r[8]*n.z+r[12],e.elements[13]=r[1]*n.x+r[5]*n.y+r[9]*n.z+r[13],e.elements[14]=r[2]*n.x+r[6]*n.y+r[10]*n.z+r[14])}var Ny=new W;function Py(e){return e.invert?e.invert():e.getInverse(Ny.copy(e)),e}var Fy=class{constructor(e){this._inverseCache=new W,this._shouldUpdateInverse=!0,this.matrix=e;let t={set:(e,t,n)=>(this._shouldUpdateInverse=!0,e[t]=n,!0)};this._originalElements=e.elements,e.elements=new Proxy(e.elements,t)}get inverse(){return this._shouldUpdateInverse&&=(Py(this._inverseCache.copy(this.matrix)),!1),this._inverseCache}revert(){this.matrix.elements=this._originalElements}},Iy=new W,Ly=new H,Ry=new H,zy=new H,By=new H,Vy=new W,Hy=class{constructor(e,t,n={},r=[]){this._currentTail=new H,this._prevTail=new H,this._boneAxis=new H,this._worldSpaceBoneLength=0,this._center=null,this._initialLocalMatrix=new W,this._initialLocalRotation=new V,this._initialLocalChildPosition=new H,this.bone=e,this.bone.matrixAutoUpdate=!1,this.child=t,this.settings={hitRadius:n.hitRadius??0,stiffness:n.stiffness??1,gravityPower:n.gravityPower??0,gravityDir:n.gravityDir?.clone()??new H(0,-1,0),dragForce:n.dragForce??.4},this.colliderGroups=r}get dependencies(){let e=new Set,t=this.bone.parent;t&&e.add(t);for(let t=0;t<this.colliderGroups.length;t++)for(let n=0;n<this.colliderGroups[t].colliders.length;n++)e.add(this.colliderGroups[t].colliders[n]);return e}get center(){return this._center}set center(e){this._center?.userData.inverseCacheProxy&&(this._center.userData.inverseCacheProxy.revert(),delete this._center.userData.inverseCacheProxy),this._center=e,this._center&&(this._center.userData.inverseCacheProxy||(this._center.userData.inverseCacheProxy=new Fy(this._center.matrixWorld)))}get initialLocalChildPosition(){return this._initialLocalChildPosition}get _parentMatrixWorld(){return this.bone.parent?this.bone.parent.matrixWorld:Iy}setInitState(){this._initialLocalMatrix.copy(this.bone.matrix),this._initialLocalRotation.copy(this.bone.quaternion),this.child?this._initialLocalChildPosition.copy(this.child.position):this._initialLocalChildPosition.copy(this.bone.position).normalize().multiplyScalar(.07);let e=this._getMatrixWorldToCenter();this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(e),this._prevTail.copy(this._currentTail),this._boneAxis.copy(this._initialLocalChildPosition).normalize()}reset(){this.bone.quaternion.copy(this._initialLocalRotation),this.bone.updateMatrix(),this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld,this.bone.matrix);let e=this._getMatrixWorldToCenter();this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(e),this._prevTail.copy(this._currentTail)}update(e){if(e<=0)return;this._calcWorldSpaceBoneLength();let t=Ry.copy(this._boneAxis).transformDirection(this._initialLocalMatrix).transformDirection(this._parentMatrixWorld);By.copy(this._currentTail).add(Ly.subVectors(this._currentTail,this._prevTail).multiplyScalar(1-this.settings.dragForce)).applyMatrix4(this._getMatrixCenterToWorld()).addScaledVector(t,this.settings.stiffness*e).addScaledVector(this.settings.gravityDir,this.settings.gravityPower*e),zy.setFromMatrixPosition(this.bone.matrixWorld),By.sub(zy).normalize().multiplyScalar(this._worldSpaceBoneLength).add(zy),this._collision(By),this._prevTail.copy(this._currentTail),this._currentTail.copy(By).applyMatrix4(this._getMatrixWorldToCenter());let n=Vy.multiplyMatrices(this._parentMatrixWorld,this._initialLocalMatrix).invert();this.bone.quaternion.setFromUnitVectors(this._boneAxis,Ly.copy(By).applyMatrix4(n).normalize()).premultiply(this._initialLocalRotation),this.bone.updateMatrix(),this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld,this.bone.matrix)}_collision(e){for(let t=0;t<this.colliderGroups.length;t++)for(let n=0;n<this.colliderGroups[t].colliders.length;n++){let r=this.colliderGroups[t].colliders[n],i=r.shape.calculateCollision(r.colliderMatrix,e,this.settings.hitRadius,Ly);if(i<0){e.addScaledVector(Ly,-i),e.sub(zy);let t=e.length();e.multiplyScalar(this._worldSpaceBoneLength/t).add(zy)}}}_calcWorldSpaceBoneLength(){Ly.setFromMatrixPosition(this.bone.matrixWorld),this.child?Ry.setFromMatrixPosition(this.child.matrixWorld):(Ry.copy(this._initialLocalChildPosition),Ry.applyMatrix4(this.bone.matrixWorld)),this._worldSpaceBoneLength=Ly.sub(Ry).length()}_getMatrixCenterToWorld(){return this._center?this._center.matrixWorld:Iy}_getMatrixWorldToCenter(){return this._center?this._center.userData.inverseCacheProxy.inverse:Iy}};function Uy(e,t){let n=[],r=e;for(;r!==null;)n.unshift(r),r=r.parent;n.forEach(e=>{t(e)})}function Wy(e,t){e.children.forEach(e=>{t(e)||Wy(e,t)})}function Gy(e){let t=new Map;for(let n of e){let r=n;do{let n=(t.get(r)??0)+1;if(n===e.size)return r;t.set(r,n),r=r.parent}while(r!==null)}return null}var Ky=class{constructor(){this._joints=new Set,this._sortedJoints=[],this._hasWarnedCircularDependency=!1,this._ancestors=[],this._objectSpringBonesMap=new Map,this._isSortedJointsDirty=!1,this._relevantChildrenUpdated=this._relevantChildrenUpdated.bind(this)}get joints(){return this._joints}get springBones(){return console.warn(`VRMSpringBoneManager: springBones is deprecated. use joints instead.`),this._joints}get colliderGroups(){let e=new Set;return this._joints.forEach(t=>{t.colliderGroups.forEach(t=>{e.add(t)})}),Array.from(e)}get colliders(){let e=new Set;return this.colliderGroups.forEach(t=>{t.colliders.forEach(t=>{e.add(t)})}),Array.from(e)}addJoint(e){this._joints.add(e);let t=this._objectSpringBonesMap.get(e.bone);t??(t=new Set,this._objectSpringBonesMap.set(e.bone,t)),t.add(e),this._isSortedJointsDirty=!0}addSpringBone(e){console.warn(`VRMSpringBoneManager: addSpringBone() is deprecated. use addJoint() instead.`),this.addJoint(e)}deleteJoint(e){this._joints.delete(e),this._objectSpringBonesMap.get(e.bone).delete(e),this._isSortedJointsDirty=!0}deleteSpringBone(e){console.warn(`VRMSpringBoneManager: deleteSpringBone() is deprecated. use deleteJoint() instead.`),this.deleteJoint(e)}setInitState(){this._sortJoints();for(let e=0;e<this._sortedJoints.length;e++){let t=this._sortedJoints[e];t.bone.updateMatrix(),t.bone.updateWorldMatrix(!1,!1),t.setInitState()}}reset(){this._sortJoints();for(let e=0;e<this._sortedJoints.length;e++){let t=this._sortedJoints[e];t.bone.updateMatrix(),t.bone.updateWorldMatrix(!1,!1),t.reset()}}update(e){this._sortJoints();for(let e=0;e<this._ancestors.length;e++)this._ancestors[e].updateWorldMatrix(e===0,!1);for(let t=0;t<this._sortedJoints.length;t++){let n=this._sortedJoints[t];n.bone.updateMatrix(),n.bone.updateWorldMatrix(!1,!1),n.update(e),Wy(n.bone,this._relevantChildrenUpdated)}}_sortJoints(){if(!this._isSortedJointsDirty)return;let e=[],t=new Set,n=new Set,r=new Set;for(let i of this._joints)this._insertJointSort(i,t,n,e,r);this._sortedJoints=e;let i=Gy(r);this._ancestors=[],i&&(this._ancestors.push(i),Wy(i,e=>(this._objectSpringBonesMap.get(e)?.size??0)>0?!0:(this._ancestors.push(e),!1))),this._isSortedJointsDirty=!1}_insertJointSort(e,t,n,r,i){if(n.has(e))return;if(t.has(e)){this._hasWarnedCircularDependency||=(console.warn(`VRMSpringBoneManager: Circular dependency detected`),!0);return}t.add(e);let a=e.dependencies;for(let e of a){let a=!1,o=null;Uy(e,e=>{let s=this._objectSpringBonesMap.get(e);if(s)for(let e of s)a=!0,this._insertJointSort(e,t,n,r,i);else a||(o=e)}),o&&i.add(o)}r.push(e),n.add(e)}_relevantChildrenUpdated(e){return(this._objectSpringBonesMap.get(e)?.size??0)>0?!0:(e.updateWorldMatrix(!1,!1),!1)}},qy=`VRMC_springBone_extended_collider`,Jy=new Set([`1.0`,`1.0-beta`]),Yy=new Set([`1.0`]),Xy=class e{get name(){return e.EXTENSION_NAME}constructor(e,t){this.parser=e,this.jointHelperRoot=t?.jointHelperRoot,this.colliderHelperRoot=t?.colliderHelperRoot,this.useExtendedColliders=t?.useExtendedColliders??!0}afterRoot(e){return fy(this,null,function*(){e.userData.vrmSpringBoneManager=yield this._import(e)})}_import(e){return fy(this,null,function*(){return(yield this._v1Import(e))??(yield this._v0Import(e))??null})}_v1Import(t){return fy(this,null,function*(){var n;let r=t.parser.json;if(r.extensionsUsed?.indexOf(e.EXTENSION_NAME)===-1)return null;let i=new Ky,a=yield t.parser.getDependencies(`node`),o=r.extensions?.[e.EXTENSION_NAME];if(!o)return null;let s=o.specVersion;if(!Jy.has(s))return console.warn(`VRMSpringBoneLoaderPlugin: Unknown ${e.EXTENSION_NAME} specVersion "${s}"`),null;let c=o.colliders?.map((t,n)=>{let r=a[t.node];if(r==null)return console.warn(`VRMSpringBoneLoaderPlugin: The collider #${n} attempted to reference a node #${t.node} but not found. Skipping the collider`),null;let i=t.shape,o=t.extensions?.[qy];if(this.useExtendedColliders&&o!=null){let t=o.specVersion;if(!Yy.has(t))console.warn(`VRMSpringBoneLoaderPlugin: Unknown ${qy} specVersion "${t}". Fallbacking to the ${e.EXTENSION_NAME} definition`);else{let e=o.shape;if(e.sphere)return this._importSphereCollider(r,{offset:new H().fromArray(e.sphere.offset??[0,0,0]),radius:e.sphere.radius??0,inside:e.sphere.inside??!1});if(e.capsule)return this._importCapsuleCollider(r,{offset:new H().fromArray(e.capsule.offset??[0,0,0]),radius:e.capsule.radius??0,tail:new H().fromArray(e.capsule.tail??[0,0,0]),inside:e.capsule.inside??!1});if(e.plane)return this._importPlaneCollider(r,{offset:new H().fromArray(e.plane.offset??[0,0,0]),normal:new H().fromArray(e.plane.normal??[0,0,1])})}}if(i.sphere)return this._importSphereCollider(r,{offset:new H().fromArray(i.sphere.offset??[0,0,0]),radius:i.sphere.radius??0,inside:!1});if(i.capsule)return this._importCapsuleCollider(r,{offset:new H().fromArray(i.capsule.offset??[0,0,0]),radius:i.capsule.radius??0,tail:new H().fromArray(i.capsule.tail??[0,0,0]),inside:!1});console.warn(`VRMSpringBoneLoaderPlugin: The collider #${n} has no valid shape. Skipping the collider`)}),l=o.colliderGroups?.map((e,t)=>({colliders:(e.colliders??[]).map(e=>c?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The collider group #${t} attempted to reference a collider #${e} but not found. Skipping the collider`),null)).filter(e=>e!=null),name:e.name}));return(n=o.springs)==null||n.forEach((e,t)=>{let n=e.joints,r=e.colliderGroups?.map(e=>l?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The spring #${t} attempted to reference a collider group #${e} but not found. Skipping the collider group`),null)).filter(e=>e!=null),o=e.center==null?void 0:a[e.center],s;n.forEach(e=>{if(s){let t=a[s.node],n=a[e.node],c={hitRadius:s.hitRadius,dragForce:s.dragForce,gravityPower:s.gravityPower,stiffness:s.stiffness,gravityDir:s.gravityDir==null?void 0:new H().fromArray(s.gravityDir)},l=this._importJoint(t,n,c,r);o&&(l.center=o),i.addJoint(l)}s=e})}),i.setInitState(),i})}_v0Import(e){return fy(this,null,function*(){let t=e.parser.json;if(t.extensionsUsed?.indexOf(`VRM`)===-1)return null;let n=t.extensions?.VRM?.secondaryAnimation;if(!n)return null;let r=n?.boneGroups;if(!r)return null;let i=new Ky,a=yield e.parser.getDependencies(`node`),o=n.colliderGroups?.map((e,t)=>{let n=a[e.node];return n==null?(console.warn(`VRMSpringBoneLoaderPlugin: The collider group #${t} attempted to reference a node #${e.node} but not found. Skipping the collider group`),null):{colliders:(e.colliders??[]).map((e,t)=>{let r=new H(0,0,0);return e.offset&&r.set(e.offset.x??0,e.offset.y??0,e.offset.z?-e.offset.z:0),this._importSphereCollider(n,{offset:r,radius:e.radius??0,inside:!1})})}});return r?.forEach((e,t)=>{let n=e.bones;n&&n.forEach(n=>{let r=a[n];if(r==null){console.warn(`VRMSpringBoneLoaderPlugin: The spring bone group #${t} attempted to reference a node #${n} but not found. Skipping the node`);return}let s=new H;e.gravityDir?s.set(e.gravityDir.x??0,e.gravityDir.y??0,e.gravityDir.z??0):s.set(0,-1,0);let c=e.center==null?void 0:a[e.center],l={hitRadius:e.hitRadius,dragForce:e.dragForce,gravityPower:e.gravityPower,stiffness:e.stiffiness,gravityDir:s},u=e.colliderGroups?.map(e=>o?.[e]??(console.warn(`VRMSpringBoneLoaderPlugin: The spring #${t} attempted to reference a collider group #${e} but not found. Skipping the collider group`),null)).filter(e=>e!=null);r.traverse(e=>{let t=e.children[0]??null,n=this._importJoint(e,t,l,u);c&&(n.center=c),i.addJoint(n)})})}),e.scene.updateMatrixWorld(),i.setInitState(),i})}_importJoint(e,t,n,r){let i=new Hy(e,t,n,r);if(this.jointHelperRoot){let e=new Ay(i);this.jointHelperRoot.add(e),e.renderOrder=this.jointHelperRoot.renderOrder}return i}_importSphereCollider(e,t){let n=new jy(new xy(t));if(e.add(n),this.colliderHelperRoot){let e=new Dy(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}_importCapsuleCollider(e,t){let n=new jy(new gy(t));if(e.add(n),this.colliderHelperRoot){let e=new Dy(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}_importPlaneCollider(e,t){let n=new jy(new yy(t));if(e.add(n),this.colliderHelperRoot){let e=new Dy(n);this.colliderHelperRoot.add(e),e.renderOrder=this.colliderHelperRoot.renderOrder}return n}};Xy.EXTENSION_NAME=`VRMC_springBone`;var Zy=Xy,Qy=class{get name(){return`VRMLoaderPlugin`}constructor(e,t){this.parser=e;let n=t?.helperRoot,r=t?.autoUpdateHumanBones;this.expressionPlugin=t?.expressionPlugin??new Jg(e),this.firstPersonPlugin=t?.firstPersonPlugin??new Qg(e),this.humanoidPlugin=t?.humanoidPlugin??new __(e,{helperRoot:n,autoUpdateHumanBones:r}),this.lookAtPlugin=t?.lookAtPlugin??new $_(e,{helperRoot:n}),this.metaPlugin=t?.metaPlugin??new nv(e),this.mtoonMaterialPlugin=t?.mtoonMaterialPlugin??new Sv(e),this.materialsHDREmissiveMultiplierPlugin=t?.materialsHDREmissiveMultiplierPlugin??new Tv(e),this.materialsV0CompatPlugin=t?.materialsV0CompatPlugin??new Lv(e),this.springBonePlugin=t?.springBonePlugin??new Zy(e,{colliderHelperRoot:n,jointHelperRoot:n}),this.nodeConstraintPlugin=t?.nodeConstraintPlugin??new dy(e,{helperRoot:n})}beforeRoot(){return Og(this,null,function*(){yield this.materialsV0CompatPlugin.beforeRoot(),yield this.mtoonMaterialPlugin.beforeRoot()})}loadMesh(e){return Og(this,null,function*(){return yield this.mtoonMaterialPlugin.loadMesh(e)})}getMaterialType(e){return this.mtoonMaterialPlugin.getMaterialType(e)??null}extendMaterialParams(e,t){return Og(this,null,function*(){yield this.materialsHDREmissiveMultiplierPlugin.extendMaterialParams(e,t),yield this.mtoonMaterialPlugin.extendMaterialParams(e,t)})}afterRoot(e){return Og(this,null,function*(){yield this.metaPlugin.afterRoot(e),yield this.humanoidPlugin.afterRoot(e),yield this.expressionPlugin.afterRoot(e),yield this.lookAtPlugin.afterRoot(e),yield this.firstPersonPlugin.afterRoot(e),yield this.springBonePlugin.afterRoot(e),yield this.nodeConstraintPlugin.afterRoot(e),yield this.mtoonMaterialPlugin.afterRoot(e);let t=e.userData.vrmMeta,n=e.userData.vrmHumanoid;if(t&&n){let r=new iv({scene:e.scene,expressionManager:e.userData.vrmExpressionManager,firstPerson:e.userData.vrmFirstPerson,humanoid:n,lookAt:e.userData.vrmLookAt,meta:t,materials:e.userData.vrmMToonMaterials,springBoneManager:e.userData.vrmSpringBoneManager,nodeConstraintManager:e.userData.vrmNodeConstraintManager});e.userData.vrm=r}})}};function $y(e){let t=new Set;return e.traverse(e=>{if(!e.isMesh)return;let n=e;t.add(n)}),t}function eb(e,t,n){if(t.size===1){let n=t.values().next().value;if(n.weight===1)return e[n.index]}let r=new Float32Array(e[0].count*3),i=0;if(n)i=1;else for(let e of t)i+=e.weight;for(let n of t){let t=e[n.index],a=n.weight/i;for(let e=0;e<t.count;e++)r[e*3+0]+=t.getX(e)*a,r[e*3+1]+=t.getY(e)*a,r[e*3+2]+=t.getZ(e)*a}return new K(r,3)}function tb(e){let t=$y(e.scene),n=new Map,r=e.expressionManager?.expressionMap;if(r!=null)for(let[e,t]of Object.entries(r)){let r=new Set;for(let i of t.binds)if(i instanceof Hg){if(i.weight!==0)for(let t of i.primitives){let r=n.get(t);r??(r=new Map,n.set(t,r));let a=r.get(e);a??(a=new Set,r.set(e,a)),a.add(i)}r.add(i)}for(let e of r)t.deleteBind(e)}for(let e of t){let t=n.get(e);if(t==null)continue;let i=e.geometry.morphAttributes;e.geometry.morphAttributes={};let a=e.geometry.clone();e.geometry=a;let o=a.morphTargetsRelative,s=i.position!=null,c=i.normal!=null,l={},u={},d=[];if(s||c){s&&(l.position=[]),c&&(l.normal=[]);let n=0;for(let[a,f]of t)s&&(l.position[n]=eb(i.position,f,o)),c&&(l.normal[n]=eb(i.normal,f,o)),r?.[a].addBind(new Hg({index:n,weight:1,primitives:[e]})),u[a]=n,d.push(0),n++}a.morphAttributes=l,e.morphTargetDictionary=u,e.morphTargetInfluences=d}}function nb(e,t,n){if(e.getComponent)return e.getComponent(t,n);{let r=e.array[t*e.itemSize+n];return e.normalized&&(r=ni.denormalize(r,e.array)),r}}function rb(e,t,n,r){e.setComponent?e.setComponent(t,n,r):(e.normalized&&(r=ni.normalize(r,e.array)),e.array[t*e.itemSize+n]=r)}function ib(e){let t=ab(e),n=new Set;for(let e of t)n.has(e.geometry)&&(e.geometry=fb(e.geometry)),n.add(e.geometry);let r=new Map;for(let e of n){let t=e.getAttribute(`skinIndex`),n=r.get(t)??new Map;r.set(t,n);let i=e.getAttribute(`skinWeight`),a=ob(t,i);n.set(i,a)}let i=new Map;for(let e of t){let t=sb(e,r);i.set(e,t)}let a=[];for(let[e,t]of i){let n=!1;for(let r of a)if(cb(t,r.boneInverseMap)){n=!0,r.meshes.add(e);for(let[e,n]of t)r.boneInverseMap.set(e,n);break}n||a.push({boneInverseMap:t,meshes:new Set([e])})}let o=new Map,s=new db,c=new db,l=new db;for(let e of a){let{boneInverseMap:t,meshes:n}=e,r=Array.from(t.keys()),i=new Jo(r,Array.from(t.values())),a=c.getOrCreate(i);for(let e of n){let t=e.geometry.getAttribute(`skinIndex`),n=s.getOrCreate(t),i=e.skeleton.bones,c=`${n};${a};${i.map(e=>l.getOrCreate(e)).join(`,`)}`,u=o.get(c);u??(u=t.clone(),lb(u,i,r),o.set(c,u)),e.geometry.setAttribute(`skinIndex`,u)}for(let e of n)e.bind(i,new W)}}function ab(e){let t=new Set;return e.traverse(e=>{if(!e.isSkinnedMesh)return;let n=e;t.add(n)}),t}function ob(e,t){let n=new Set;for(let r=0;r<e.count;r++)for(let i=0;i<e.itemSize;i++){let a=nb(e,r,i);nb(t,r,i)!==0&&n.add(a)}return n}function sb(e,t){let n=new Map,r=e.skeleton,i=e.geometry,a=i.getAttribute(`skinIndex`),o=i.getAttribute(`skinWeight`),s=t.get(a)?.get(o);if(!s)throw Error(`Unreachable. attributeUsedIndexSetMap does not know the skin index attribute or the skin weight attribute.`);for(let e of s)n.set(r.bones[e],r.boneInverses[e]);return n}function cb(e,t){for(let[n,r]of e.entries()){let e=t.get(n);if(e!=null&&!ub(r,e))return!1}return!0}function lb(e,t,n){let r=new Map;for(let e of t)r.set(e,r.size);let i=new Map;for(let[e,t]of n.entries()){let n=r.get(t);i.set(n,e)}for(let t=0;t<e.count;t++)for(let n=0;n<e.itemSize;n++){let r=nb(e,t,n),a=i.get(r);rb(e,t,n,a)}e.needsUpdate=!0}function ub(e,t,n){if(n||=1e-4,e.elements.length!=t.elements.length)return!1;for(let r=0,i=e.elements.length;r<i;r++)if(Math.abs(e.elements[r]-t.elements[r])>n)return!1;return!0}var db=class{constructor(){this._objectIndexMap=new Map,this._index=0}get(e){return this._objectIndexMap.get(e)}getOrCreate(e){let t=this._objectIndexMap.get(e);return t??(t=this._index,this._objectIndexMap.set(e,t),this._index++),t}};function fb(e){let t=new q;t.name=e.name,t.setIndex(e.index);for(let[n,r]of Object.entries(e.attributes))t.setAttribute(n,r);for(let[n,r]of Object.entries(e.morphAttributes)){let e=n;t.morphAttributes[e]=r.concat()}t.morphTargetsRelative=e.morphTargetsRelative,t.groups=[];for(let n of e.groups)t.addGroup(n.start,n.count,n.materialIndex);return t.boundingSphere=e.boundingSphere?.clone()??null,t.boundingBox=e.boundingBox?.clone()??null,t.drawRange.start=e.drawRange.start,t.drawRange.count=e.drawRange.count,t.userData=e.userData,t}function pb(e){if(Object.values(e).forEach(e=>{e?.isTexture&&e.dispose()}),e.isShaderMaterial){let t=e.uniforms;t&&Object.values(t).forEach(e=>{let t=e.value;t?.isTexture&&t.dispose()})}e.dispose()}function mb(e){let t=e.geometry;t&&t.dispose();let n=e.skeleton;n&&n.dispose();let r=e.material;r&&(Array.isArray(r)?r.forEach(e=>pb(e)):r&&pb(r))}function hb(e){e.traverse(mb)}function gb(e,t){console.warn(`VRMUtils.removeUnnecessaryJoints: removeUnnecessaryJoints is deprecated. Use combineSkeletons instead. combineSkeletons contributes more to the performance improvement. This function will be removed in the next major version.`);let n=t?.experimentalSameBoneCounts??!1,r=[];e.traverse(e=>{e.type===`SkinnedMesh`&&r.push(e)});let i=new Map,a=0;for(let e of r){let t=e.geometry.getAttribute(`skinIndex`);if(i.has(t))continue;let n=new Map,r=new Map;for(let e=0;e<t.count;e++)for(let i=0;i<t.itemSize;i++){let a=nb(t,e,i),o=n.get(a);o??(o=n.size,n.set(a,o),r.set(o,a)),rb(t,e,i,o)}t.needsUpdate=!0,i.set(t,r),a=Math.max(a,n.size)}for(let e of r){let t=e.geometry.getAttribute(`skinIndex`),r=i.get(t),o=[],s=[],c=n?a:r.size;for(let t=0;t<c;t++){let n=r.get(t)??0;o.push(e.skeleton.bones[n]),s.push(e.skeleton.boneInverses[n])}let l=new Jo(o,s);e.bind(l,new W)}}function _b(e,t){let n=e.position.count,r=Array(n),i=0,a=t.array;for(let e=0;e<a.length;e++){let t=a[e];r[t]||(r[t]=!0,i++)}return{isVertexUsed:r,vertexCount:n,verticesUsed:i}}function vb(e){let t=[],n=[],r=0;for(let i=0;i<e.length;i++)if(e[i]){let e=r++;t[i]=e,n[e]=i}return{originalIndexNewIndexMap:t,newIndexOriginalIndexMap:n}}function yb(e,t){t.name=e.name,t.morphTargetsRelative=e.morphTargetsRelative,e.groups.forEach(e=>{t.addGroup(e.start,e.count,e.materialIndex)}),t.boundingBox=e.boundingBox?.clone()??null,t.boundingSphere=e.boundingSphere?.clone()??null,t.setDrawRange(e.drawRange.start,e.drawRange.count),t.userData=e.userData}function bb(e,t,n){let r=t.array,i=new r.constructor(r.length);for(let e=0;e<r.length;e++)i[e]=n[r[e]];e.setIndex(new K(i,t.itemSize,t.normalized))}function xb(e,t,n){let r=e.constructor,i=new r(t.length*n),a=!0;for(let r=0;r<t.length;r++){let o=t[r]*n,s=r*n;for(let t=0;t<n;t++){let n=e[o+t];i[s+t]=n,a&&=n===0}}return[i,a]}function Sb(e){let t=new Map,n=[];for(let[r,i]of Object.entries(e))if(i.isInterleavedBufferAttribute){let e=i,n=e.data,a=t.get(n)??[];t.set(n,a),a.push([r,e])}else{let e=i;n.push([r,e])}return[t,n]}function Cb(e,t,n){let[r,i]=Sb(t);for(let[t,i]of r){let r=t.array,{stride:a}=t,[o,s]=xb(r,n,a),c=new ao(o,a);c.setUsage(t.usage);for(let[t,n]of i){let{itemSize:r,offset:i,normalized:a}=n,o=new so(c,r,i,a);e.setAttribute(t,o)}}for(let[t,r]of i){let i=r.array,{itemSize:a,normalized:o}=r,[s,c]=xb(i,n,a);e.setAttribute(t,new K(s,a,o))}}function wb(e){let t=new Map,n=[];for(let[r,i]of Object.entries(e)){let e=r;for(let r=0;r<i.length;r++){let a=i[r];if(a.isInterleavedBufferAttribute){let n=a,i=n.data,o=t.get(i)??[];t.set(i,o),o.push([e,r,n])}else{let t=a;n.push([e,r,t])}}}return[t,n]}function Tb(e,t,n){let r=!0,[i,a]=wb(t),o={};for(let[e,t]of i){let i=e.array,{stride:a}=e,[s,c]=xb(i,n,a);r&&=c;let l=new ao(s,a);l.setUsage(e.usage);for(let[e,n,r]of t){let{itemSize:t,offset:i,normalized:a}=r,s=new so(l,t,i,a);o[e]??(o[e]=[]),o[e][n]=s}}for(let[e,t,i]of a){let a=i,s=a.array,{itemSize:c,normalized:l}=a,[u,d]=xb(s,n,c);r&&=d,o[e]??(o[e]=[]),o[e][t]=new K(u,c,l)}e.morphAttributes=r?{}:o}function Eb(e){let t=new Map;e.traverse(e=>{if(!e.isMesh)return;let n=e,r=n.geometry,i=r.index;if(i==null)return;let a=t.get(r);if(a!=null){n.geometry=a;return}let{isVertexUsed:o,vertexCount:s,verticesUsed:c}=_b(r.attributes,i);if(c===s)return;let{originalIndexNewIndexMap:l,newIndexOriginalIndexMap:u}=vb(o),d=new q;yb(r,d),t.set(r,d),bb(d,i,l),Cb(d,r.attributes,u),Tb(d,r.morphAttributes,u),n.geometry=d}),Array.from(t.keys()).forEach(e=>{e.dispose()})}function Db(e){e.meta?.metaVersion===`0`&&(e.scene.rotation.y=Math.PI)}var Ob=class{constructor(){}};Ob.combineMorphs=tb,Ob.combineSkeletons=ib,Ob.deepDispose=hb,Ob.removeUnnecessaryJoints=gb,Ob.removeUnnecessaryVertices=Eb,Ob.rotateVRM0=Db;function kb(e,t){if(t===0)return console.warn(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.`),e;if(t===2||t===1){let n=e.getIndex();if(n===null){let t=[],r=e.getAttribute(`position`);if(r!==void 0){for(let e=0;e<r.count;e++)t.push(e);e.setIndex(t),n=e.getIndex()}else return console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.`),e}let r=n.count-2,i=[];if(t===2)for(let e=1;e<=r;e++)i.push(n.getX(0)),i.push(n.getX(e)),i.push(n.getX(e+1));else for(let e=0;e<r;e++)e%2==0?(i.push(n.getX(e)),i.push(n.getX(e+1)),i.push(n.getX(e+2))):(i.push(n.getX(e+2)),i.push(n.getX(e+1)),i.push(n.getX(e)));i.length/3!==r&&console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.`);let a=e.clone();return a.setIndex(i),a.clearGroups(),a}else return console.error(`THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:`,t),e}function Ab(e){let t=new Map,n=new Map,r=e.clone();return jb(e,r,function(e,r){t.set(r,e),n.set(e,r)}),r.traverse(function(e){if(!e.isSkinnedMesh)return;let r=e,i=t.get(e),a=i.skeleton.bones;r.skeleton=i.skeleton.clone(),r.bindMatrix.copy(i.bindMatrix),r.skeleton.bones=a.map(function(e){return n.get(e)}),r.bind(r.skeleton,r.bindMatrix)}),r}function jb(e,t,n){n(e,t);for(let r=0;r<e.children.length;r++)jb(e.children[r],t.children[r],n)}var Mb=class extends kc{constructor(e){super(e),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new zb(e)}),this.register(function(e){return new Bb(e)}),this.register(function(e){return new Yb(e)}),this.register(function(e){return new Xb(e)}),this.register(function(e){return new Zb(e)}),this.register(function(e){return new Hb(e)}),this.register(function(e){return new Ub(e)}),this.register(function(e){return new Wb(e)}),this.register(function(e){return new Gb(e)}),this.register(function(e){return new Rb(e)}),this.register(function(e){return new Kb(e)}),this.register(function(e){return new Vb(e)}),this.register(function(e){return new Jb(e)}),this.register(function(e){return new qb(e)}),this.register(function(e){return new Ib(e)}),this.register(function(e){return new Qb(e,Fb.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new Qb(e,Fb.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new $b(e)})}load(e,t,n,r){let i=this,a;if(this.resourcePath!==``)a=this.resourcePath;else if(this.path!==``){let t=il.extractUrlBase(e);a=il.resolveURL(t,this.path)}else a=il.extractUrlBase(e);this.manager.itemStart(e);let o=function(t){r?r(t):console.error(t),i.manager.itemError(e),i.manager.itemEnd(e)},s=new Mc(this.manager);s.setPath(this.path),s.setResponseType(`arraybuffer`),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(e,function(n){try{i.parse(n,a,function(n){t(n),i.manager.itemEnd(e)},o)}catch(e){o(e)}},n,o)}setDRACOLoader(e){return this.dracoLoader=e,this}setKTX2Loader(e){return this.ktx2Loader=e,this}setMeshoptDecoder(e){return this.meshoptDecoder=e,this}register(e){return this.pluginCallbacks.indexOf(e)===-1&&this.pluginCallbacks.push(e),this}unregister(e){return this.pluginCallbacks.indexOf(e)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(e),1),this}parse(e,t,n,r){let i,a={},o={},s=new TextDecoder;if(typeof e==`string`)i=JSON.parse(e);else if(e instanceof ArrayBuffer)if(s.decode(new Uint8Array(e,0,4))===ex){try{a[Fb.KHR_BINARY_GLTF]=new rx(e)}catch(e){r&&r(e);return}i=JSON.parse(a[Fb.KHR_BINARY_GLTF].content)}else i=JSON.parse(s.decode(e));else i=e;if(i.asset===void 0||i.asset.version[0]<2){r&&r(Error(`THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.`));return}let c=new kx(i,{path:t||this.resourcePath||``,crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let e=0;e<this.pluginCallbacks.length;e++){let t=this.pluginCallbacks[e](c);t.name||console.error(`THREE.GLTFLoader: Invalid plugin found: missing name`),o[t.name]=t,a[t.name]=!0}if(i.extensionsUsed)for(let e=0;e<i.extensionsUsed.length;++e){let t=i.extensionsUsed[e],n=i.extensionsRequired||[];switch(t){case Fb.KHR_MATERIALS_UNLIT:a[t]=new Lb;break;case Fb.KHR_DRACO_MESH_COMPRESSION:a[t]=new ix(i,this.dracoLoader);break;case Fb.KHR_TEXTURE_TRANSFORM:a[t]=new ax;break;case Fb.KHR_MESH_QUANTIZATION:a[t]=new ox;break;default:n.indexOf(t)>=0&&o[t]===void 0&&console.warn(`THREE.GLTFLoader: Unknown extension "`+t+`".`)}}c.setExtensions(a),c.setPlugins(o),c.parse(n,r)}parseAsync(e,t){let n=this;return new Promise(function(r,i){n.parse(e,t,r,i)})}};function Nb(){let e={};return{get:function(t){return e[t]},add:function(t,n){e[t]=n},remove:function(t){delete e[t]},removeAll:function(){e={}}}}function Pb(e,t,n){let r=e.json.materials[t];return r.extensions&&r.extensions[n]?r.extensions[n]:null}var Fb={KHR_BINARY_GLTF:`KHR_binary_glTF`,KHR_DRACO_MESH_COMPRESSION:`KHR_draco_mesh_compression`,KHR_LIGHTS_PUNCTUAL:`KHR_lights_punctual`,KHR_MATERIALS_CLEARCOAT:`KHR_materials_clearcoat`,KHR_MATERIALS_DISPERSION:`KHR_materials_dispersion`,KHR_MATERIALS_IOR:`KHR_materials_ior`,KHR_MATERIALS_SHEEN:`KHR_materials_sheen`,KHR_MATERIALS_SPECULAR:`KHR_materials_specular`,KHR_MATERIALS_TRANSMISSION:`KHR_materials_transmission`,KHR_MATERIALS_IRIDESCENCE:`KHR_materials_iridescence`,KHR_MATERIALS_ANISOTROPY:`KHR_materials_anisotropy`,KHR_MATERIALS_UNLIT:`KHR_materials_unlit`,KHR_MATERIALS_VOLUME:`KHR_materials_volume`,KHR_TEXTURE_BASISU:`KHR_texture_basisu`,KHR_TEXTURE_TRANSFORM:`KHR_texture_transform`,KHR_MESH_QUANTIZATION:`KHR_mesh_quantization`,KHR_MATERIALS_EMISSIVE_STRENGTH:`KHR_materials_emissive_strength`,EXT_MATERIALS_BUMP:`EXT_materials_bump`,EXT_TEXTURE_WEBP:`EXT_texture_webp`,EXT_TEXTURE_AVIF:`EXT_texture_avif`,EXT_MESHOPT_COMPRESSION:`EXT_meshopt_compression`,KHR_MESHOPT_COMPRESSION:`KHR_meshopt_compression`,EXT_MESH_GPU_INSTANCING:`EXT_mesh_gpu_instancing`},Ib=class{constructor(e){this.parser=e,this.name=Fb.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){let e=this.parser,t=this.parser.json.nodes||[];for(let n=0,r=t.length;n<r;n++){let r=t[n];r.extensions&&r.extensions[this.name]&&r.extensions[this.name].light!==void 0&&e._addNodeRef(this.cache,r.extensions[this.name].light)}}_loadLight(e){let t=this.parser,n=`light:`+e,r=t.cache.get(n);if(r)return r;let i=t.json,a=((i.extensions&&i.extensions[this.name]||{}).lights||[])[e],o,s=new G(16777215);a.color!==void 0&&s.setRGB(a.color[0],a.color[1],a.color[2],fr);let c=a.range===void 0?0:a.range;switch(a.type){case`directional`:o=new nl(s),o.target.position.set(0,0,-1),o.add(o.target);break;case`point`:o=new $c(s),o.distance=c;break;case`spot`:o=new Zc(s),o.distance=c,a.spot=a.spot||{},a.spot.innerConeAngle=a.spot.innerConeAngle===void 0?0:a.spot.innerConeAngle,a.spot.outerConeAngle=a.spot.outerConeAngle===void 0?Math.PI/4:a.spot.outerConeAngle,o.angle=a.spot.outerConeAngle,o.penumbra=1-a.spot.innerConeAngle/a.spot.outerConeAngle,o.target.position.set(0,0,-1),o.add(o.target);break;default:throw Error(`THREE.GLTFLoader: Unexpected light type: `+a.type)}return o.position.set(0,0,0),xx(o,a),a.intensity!==void 0&&(o.intensity=a.intensity),o.name=t.createUniqueName(a.name||`light_`+e),r=Promise.resolve(o),t.cache.add(n,r),r}getDependency(e,t){if(e===`light`)return this._loadLight(t)}createNodeAttachment(e){let t=this,n=this.parser,r=n.json.nodes[e],i=(r.extensions&&r.extensions[this.name]||{}).light;return i===void 0?null:this._loadLight(i).then(function(e){return n._getNodeRef(t.cache,i,e)})}},Lb=class{constructor(){this.name=Fb.KHR_MATERIALS_UNLIT}getMaterialType(){return yo}extendParams(e,t,n){let r=[];e.color=new G(1,1,1),e.opacity=1;let i=t.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){let t=i.baseColorFactor;e.color.setRGB(t[0],t[1],t[2],fr),e.opacity=t[3]}i.baseColorTexture!==void 0&&r.push(n.assignTexture(e,`map`,i.baseColorTexture,dr))}return Promise.all(r)}},Rb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);return n===null||n.emissiveStrength!==void 0&&(t.emissiveIntensity=n.emissiveStrength),Promise.resolve()}},zb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_CLEARCOAT}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];if(n.clearcoatFactor!==void 0&&(t.clearcoat=n.clearcoatFactor),n.clearcoatTexture!==void 0&&r.push(this.parser.assignTexture(t,`clearcoatMap`,n.clearcoatTexture)),n.clearcoatRoughnessFactor!==void 0&&(t.clearcoatRoughness=n.clearcoatRoughnessFactor),n.clearcoatRoughnessTexture!==void 0&&r.push(this.parser.assignTexture(t,`clearcoatRoughnessMap`,n.clearcoatRoughnessTexture)),n.clearcoatNormalTexture!==void 0&&(r.push(this.parser.assignTexture(t,`clearcoatNormalMap`,n.clearcoatNormalTexture)),n.clearcoatNormalTexture.scale!==void 0)){let e=n.clearcoatNormalTexture.scale;t.clearcoatNormalScale=new B(e,e)}return Promise.all(r)}},Bb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_DISPERSION}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);return n===null||(t.dispersion=n.dispersion===void 0?0:n.dispersion),Promise.resolve()}},Vb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_IRIDESCENCE}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.iridescenceFactor!==void 0&&(t.iridescence=n.iridescenceFactor),n.iridescenceTexture!==void 0&&r.push(this.parser.assignTexture(t,`iridescenceMap`,n.iridescenceTexture)),n.iridescenceIor!==void 0&&(t.iridescenceIOR=n.iridescenceIor),t.iridescenceThicknessRange===void 0&&(t.iridescenceThicknessRange=[100,400]),n.iridescenceThicknessMinimum!==void 0&&(t.iridescenceThicknessRange[0]=n.iridescenceThicknessMinimum),n.iridescenceThicknessMaximum!==void 0&&(t.iridescenceThicknessRange[1]=n.iridescenceThicknessMaximum),n.iridescenceThicknessTexture!==void 0&&r.push(this.parser.assignTexture(t,`iridescenceThicknessMap`,n.iridescenceThicknessTexture)),Promise.all(r)}},Hb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_SHEEN}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];if(t.sheenColor=new G(0,0,0),t.sheenRoughness=0,t.sheen=1,n.sheenColorFactor!==void 0){let e=n.sheenColorFactor;t.sheenColor.setRGB(e[0],e[1],e[2],fr)}return n.sheenRoughnessFactor!==void 0&&(t.sheenRoughness=n.sheenRoughnessFactor),n.sheenColorTexture!==void 0&&r.push(this.parser.assignTexture(t,`sheenColorMap`,n.sheenColorTexture,dr)),n.sheenRoughnessTexture!==void 0&&r.push(this.parser.assignTexture(t,`sheenRoughnessMap`,n.sheenRoughnessTexture)),Promise.all(r)}},Ub=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_TRANSMISSION}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.transmissionFactor!==void 0&&(t.transmission=n.transmissionFactor),n.transmissionTexture!==void 0&&r.push(this.parser.assignTexture(t,`transmissionMap`,n.transmissionTexture)),Promise.all(r)}},Wb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_VOLUME}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];t.thickness=n.thicknessFactor===void 0?0:n.thicknessFactor,n.thicknessTexture!==void 0&&r.push(this.parser.assignTexture(t,`thicknessMap`,n.thicknessTexture)),t.attenuationDistance=n.attenuationDistance||1/0;let i=n.attenuationColor||[1,1,1];return t.attenuationColor=new G().setRGB(i[0],i[1],i[2],fr),Promise.all(r)}},Gb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_IOR}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);return n===null?Promise.resolve():(t.ior=n.ior===void 0?1.5:n.ior,t.ior===0&&(t.ior=1e3),Promise.resolve())}},Kb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_SPECULAR}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];t.specularIntensity=n.specularFactor===void 0?1:n.specularFactor,n.specularTexture!==void 0&&r.push(this.parser.assignTexture(t,`specularIntensityMap`,n.specularTexture));let i=n.specularColorFactor||[1,1,1];return t.specularColor=new G().setRGB(i[0],i[1],i[2],fr),n.specularColorTexture!==void 0&&r.push(this.parser.assignTexture(t,`specularColorMap`,n.specularColorTexture,dr)),Promise.all(r)}},qb=class{constructor(e){this.parser=e,this.name=Fb.EXT_MATERIALS_BUMP}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return t.bumpScale=n.bumpFactor===void 0?1:n.bumpFactor,n.bumpTexture!==void 0&&r.push(this.parser.assignTexture(t,`bumpMap`,n.bumpTexture)),Promise.all(r)}},Jb=class{constructor(e){this.parser=e,this.name=Fb.KHR_MATERIALS_ANISOTROPY}getMaterialType(e){return Pb(this.parser,e,this.name)===null?null:rc}extendMaterialParams(e,t){let n=Pb(this.parser,e,this.name);if(n===null)return Promise.resolve();let r=[];return n.anisotropyStrength!==void 0&&(t.anisotropy=n.anisotropyStrength),n.anisotropyRotation!==void 0&&(t.anisotropyRotation=n.anisotropyRotation),n.anisotropyTexture!==void 0&&r.push(this.parser.assignTexture(t,`anisotropyMap`,n.anisotropyTexture)),Promise.all(r)}},Yb=class{constructor(e){this.parser=e,this.name=Fb.KHR_TEXTURE_BASISU}loadTexture(e){let t=this.parser,n=t.json,r=n.textures[e];if(!r.extensions||!r.extensions[this.name])return null;let i=r.extensions[this.name],a=t.options.ktx2Loader;if(!a){if(n.extensionsRequired&&n.extensionsRequired.indexOf(this.name)>=0)throw Error(`THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures`);return null}return t.loadTextureImage(e,i.source,a)}},Xb=class{constructor(e){this.parser=e,this.name=Fb.EXT_TEXTURE_WEBP}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return n.loadTextureImage(e,a.source,s)}},Zb=class{constructor(e){this.parser=e,this.name=Fb.EXT_TEXTURE_AVIF}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return n.loadTextureImage(e,a.source,s)}},Qb=class{constructor(e,t){this.name=t,this.parser=e}loadBufferView(e){let t=this.parser.json,n=t.bufferViews[e];if(n.extensions&&n.extensions[this.name]){let e=n.extensions[this.name],r=this.parser.getDependency(`buffer`,e.buffer),i=this.parser.options.meshoptDecoder;if(!i||!i.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw Error(`THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files`);return null}return r.then(function(t){let n=e.byteOffset||0,r=e.byteLength||0,a=e.count,o=e.byteStride,s=new Uint8Array(t,n,r);return i.decodeGltfBufferAsync?i.decodeGltfBufferAsync(a,o,s,e.mode,e.filter).then(function(e){return e.buffer}):i.ready.then(function(){let t=new ArrayBuffer(a*o);return i.decodeGltfBuffer(new Uint8Array(t),a,o,s,e.mode,e.filter),t})})}else return null}},$b=class{constructor(e){this.name=Fb.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){let t=this.parser.json,n=t.nodes[e];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;let r=t.meshes[n.mesh];for(let e of r.primitives)if(e.mode!==ux.TRIANGLES&&e.mode!==ux.TRIANGLE_STRIP&&e.mode!==ux.TRIANGLE_FAN&&e.mode!==void 0)return null;let i=n.extensions[this.name].attributes,a=[],o={};for(let e in i)a.push(this.parser.getDependency(`accessor`,i[e]).then(t=>(o[e]=t,o[e])));return a.length<1?null:(a.push(this.parser.createNodeMesh(e)),Promise.all(a).then(e=>{let t=e.pop(),n=t.isGroup?t.children:[t],r=e[0].count,i=[];for(let e of n){let t=new W,n=new H,a=new V,s=new H(1,1,1),c=new rs(e.geometry,e.material,r);for(let e=0;e<r;e++)o.TRANSLATION&&n.fromBufferAttribute(o.TRANSLATION,e),o.ROTATION&&a.fromBufferAttribute(o.ROTATION,e),o.SCALE&&s.fromBufferAttribute(o.SCALE,e),c.setMatrixAt(e,t.compose(n,a,s));for(let t in o)if(t===`_COLOR_0`){let e=o[t];c.instanceColor=new Yo(e.array,e.itemSize,e.normalized)}else t!==`TRANSLATION`&&t!==`ROTATION`&&t!==`SCALE`&&e.geometry.setAttribute(t,o[t]);Zi.prototype.copy.call(c,e),this.parser.assignFinalMaterial(c),i.push(c)}return t.isGroup?(t.clear(),t.add(...i),t):i[0]}))}},ex=`glTF`,tx=12,nx={JSON:1313821514,BIN:5130562},rx=class{constructor(e){this.name=Fb.KHR_BINARY_GLTF,this.content=null,this.body=null;let t=new DataView(e,0,tx),n=new TextDecoder;if(this.header={magic:n.decode(new Uint8Array(e.slice(0,4))),version:t.getUint32(4,!0),length:t.getUint32(8,!0)},this.header.magic!==ex)throw Error(`THREE.GLTFLoader: Unsupported glTF-Binary header.`);if(this.header.version<2)throw Error(`THREE.GLTFLoader: Legacy binary file detected.`);let r=this.header.length-tx,i=new DataView(e,tx),a=0;for(;a<r;){let t=i.getUint32(a,!0);a+=4;let r=i.getUint32(a,!0);if(a+=4,r===nx.JSON){let r=new Uint8Array(e,tx+a,t);this.content=n.decode(r)}else if(r===nx.BIN){let n=tx+a;this.body=e.slice(n,n+t)}a+=t}if(this.content===null)throw Error(`THREE.GLTFLoader: JSON content not found.`)}},ix=class{constructor(e,t){if(!t)throw Error(`THREE.GLTFLoader: No DRACOLoader instance provided.`);this.name=Fb.KHR_DRACO_MESH_COMPRESSION,this.json=e,this.dracoLoader=t,this.dracoLoader.preload()}decodePrimitive(e,t){let n=this.json,r=this.dracoLoader,i=e.extensions[this.name].bufferView,a=e.extensions[this.name].attributes,o={},s={},c={};for(let e in a){let t=hx[e]||e.toLowerCase();o[t]=a[e]}for(let t in e.attributes){let r=hx[t]||t.toLowerCase();if(a[t]!==void 0){let i=n.accessors[e.attributes[t]];c[r]=dx[i.componentType].name,s[r]=i.normalized===!0}}return t.getDependency(`bufferView`,i).then(function(e){return new Promise(function(t,n){r.decodeDracoFile(e,function(e){for(let t in e.attributes){let n=e.attributes[t],r=s[t];r!==void 0&&(n.normalized=r)}t(e)},o,c,fr,n)})})}},ax=class{constructor(){this.name=Fb.KHR_TEXTURE_TRANSFORM}extendTexture(e,t){return(t.texCoord===void 0||t.texCoord===e.channel)&&t.offset===void 0&&t.rotation===void 0&&t.scale===void 0?e:(e=e.clone(),t.texCoord!==void 0&&(e.channel=t.texCoord),t.offset!==void 0&&e.offset.fromArray(t.offset),t.rotation!==void 0&&(e.rotation=t.rotation),t.scale!==void 0&&e.repeat.fromArray(t.scale),e.needsUpdate=!0,e)}},ox=class{constructor(){this.name=Fb.KHR_MESH_QUANTIZATION}},sx=class extends uc{constructor(e,t,n,r){super(e,t,n,r)}copySampleValue_(e){let t=this.resultBuffer,n=this.sampleValues,r=this.valueSize,i=e*r*3+r;for(let e=0;e!==r;e++)t[e]=n[i+e];return t}interpolate_(e,t,n,r){let i=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=o*2,c=o*3,l=r-t,u=(n-t)/l,d=u*u,f=d*u,p=e*c,m=p-c,h=-2*f+3*d,g=f-d,_=1-h,v=g-d+u;for(let e=0;e!==o;e++){let t=a[m+e+o],n=a[m+e+s]*l,r=a[p+e+o],c=a[p+e]*l;i[e]=_*t+v*n+h*r+g*c}return i}},cx=new V,lx=class extends sx{interpolate_(e,t,n,r){let i=super.interpolate_(e,t,n,r);return cx.fromArray(i).normalize().toArray(i),i}},ux={FLOAT:5126,FLOAT_MAT3:35675,FLOAT_MAT4:35676,FLOAT_VEC2:35664,FLOAT_VEC3:35665,FLOAT_VEC4:35666,LINEAR:9729,REPEAT:10497,SAMPLER_2D:35678,POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6,UNSIGNED_BYTE:5121,UNSIGNED_SHORT:5123},dx={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},fx={9728:zt,9729:Ht,9984:Bt,9985:Ut,9986:Vt,9987:Wt},px={33071:Lt,33648:Rt,10497:It},mx={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},hx={POSITION:`position`,NORMAL:`normal`,TANGENT:`tangent`,TEXCOORD_0:`uv`,TEXCOORD_1:`uv1`,TEXCOORD_2:`uv2`,TEXCOORD_3:`uv3`,COLOR_0:`color`,WEIGHTS_0:`skinWeight`,JOINTS_0:`skinIndex`},gx={scale:`scale`,translation:`position`,rotation:`quaternion`,weights:`morphTargetInfluences`},_x={CUBICSPLINE:void 0,LINEAR:tr,STEP:er},vx={OPAQUE:`OPAQUE`,MASK:`MASK`,BLEND:`BLEND`};function yx(e){return e.DefaultMaterial===void 0&&(e.DefaultMaterial=new nc({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:0})),e.DefaultMaterial}function bx(e,t,n){for(let r in n.extensions)e[r]===void 0&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[r]=n.extensions[r])}function xx(e,t){t.extras!==void 0&&(typeof t.extras==`object`?Object.assign(e.userData,t.extras):console.warn(`THREE.GLTFLoader: Ignoring primitive type .extras, `+t.extras))}function Sx(e,t,n){let r=!1,i=!1,a=!1;for(let e=0,n=t.length;e<n;e++){let n=t[e];if(n.POSITION!==void 0&&(r=!0),n.NORMAL!==void 0&&(i=!0),n.COLOR_0!==void 0&&(a=!0),r&&i&&a)break}if(!r&&!i&&!a)return Promise.resolve(e);let o=[],s=[],c=[];for(let l=0,u=t.length;l<u;l++){let u=t[l];if(r){let t=u.POSITION===void 0?e.attributes.position:n.getDependency(`accessor`,u.POSITION);o.push(t)}if(i){let t=u.NORMAL===void 0?e.attributes.normal:n.getDependency(`accessor`,u.NORMAL);s.push(t)}if(a){let t=u.COLOR_0===void 0?e.attributes.color:n.getDependency(`accessor`,u.COLOR_0);c.push(t)}}return Promise.all([Promise.all(o),Promise.all(s),Promise.all(c)]).then(function(t){let n=t[0],o=t[1],s=t[2];return r&&(e.morphAttributes.position=n),i&&(e.morphAttributes.normal=o),a&&(e.morphAttributes.color=s),e.morphTargetsRelative=!0,e})}function Cx(e,t){if(e.updateMorphTargets(),t.weights!==void 0)for(let n=0,r=t.weights.length;n<r;n++)e.morphTargetInfluences[n]=t.weights[n];if(t.extras&&Array.isArray(t.extras.targetNames)){let n=t.extras.targetNames;if(e.morphTargetInfluences.length===n.length){e.morphTargetDictionary={};for(let t=0,r=n.length;t<r;t++)e.morphTargetDictionary[n[t]]=t}else console.warn(`THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.`)}}function wx(e){let t,n=e.extensions&&e.extensions[Fb.KHR_DRACO_MESH_COMPRESSION];if(t=n?`draco:`+n.bufferView+`:`+n.indices+`:`+Tx(n.attributes):e.indices+`:`+Tx(e.attributes)+`:`+e.mode,e.targets!==void 0)for(let n=0,r=e.targets.length;n<r;n++)t+=`:`+Tx(e.targets[n]);return t}function Tx(e){let t=``,n=Object.keys(e).sort();for(let r=0,i=n.length;r<i;r++)t+=n[r]+`:`+e[n[r]]+`;`;return t}function Ex(e){switch(e){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw Error(`THREE.GLTFLoader: Unsupported normalized accessor component type.`)}}function Dx(e){return e.search(/\.jpe?g($|\?)/i)>0||e.search(/^data\:image\/jpeg/)===0?`image/jpeg`:e.search(/\.webp($|\?)/i)>0||e.search(/^data\:image\/webp/)===0?`image/webp`:e.search(/\.ktx2($|\?)/i)>0||e.search(/^data\:image\/ktx2/)===0?`image/ktx2`:`image/png`}var Ox=new W,kx=class{constructor(e={},t={}){this.json=e,this.extensions={},this.plugins={},this.options=t,this.cache=new Nb,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,r=-1,i=!1,a=-1;if(typeof navigator<`u`&&navigator.userAgent!==void 0){let e=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(e)===!0;let t=e.match(/Version\/(\d+)/);r=n&&t?parseInt(t[1],10):-1,i=e.indexOf(`Firefox`)>-1,a=i?e.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>`u`||n&&r<17||i&&a<98?this.textureLoader=new Ic(this.options.manager):this.textureLoader=new ol(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new Mc(this.options.manager),this.fileLoader.setResponseType(`arraybuffer`),this.options.crossOrigin===`use-credentials`&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){let n=this,r=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(e){return e._markDefs&&e._markDefs()}),Promise.all(this._invokeAll(function(e){return e.beforeRoot&&e.beforeRoot()})).then(function(){return Promise.all([n.getDependencies(`scene`),n.getDependencies(`animation`),n.getDependencies(`camera`)])}).then(function(t){let a={scene:t[0][r.scene||0],scenes:t[0],animations:t[1],cameras:t[2],asset:r.asset,parser:n,userData:{}};return bx(i,a,r),xx(a,r),Promise.all(n._invokeAll(function(e){return e.afterRoot&&e.afterRoot(a)})).then(function(){for(let e of a.scenes)e.updateMatrixWorld();e(a)})}).catch(t)}_markDefs(){let e=this.json.nodes||[],t=this.json.skins||[],n=this.json.meshes||[];for(let n=0,r=t.length;n<r;n++){let r=t[n].joints;for(let t=0,n=r.length;t<n;t++)e[r[t]].isBone=!0}for(let t=0,r=e.length;t<r;t++){let r=e[t];r.mesh!==void 0&&(this._addNodeRef(this.meshCache,r.mesh),r.skin!==void 0&&(n[r.mesh].isSkinnedMesh=!0)),r.camera!==void 0&&this._addNodeRef(this.cameraCache,r.camera)}}_addNodeRef(e,t){t!==void 0&&(e.refs[t]===void 0&&(e.refs[t]=e.uses[t]=0),e.refs[t]++)}_getNodeRef(e,t,n){if(e.refs[t]<=1)return n;let r=n.clone(),i=(e,t)=>{let n=this.associations.get(e);n!=null&&this.associations.set(t,n);for(let[n,r]of e.children.entries())i(r,t.children[n])};return i(n,r),r.name+=`_instance_`+ e.uses[t]++,r}_invokeOne(e){let t=Object.values(this.plugins);t.push(this);for(let n=0;n<t.length;n++){let r=e(t[n]);if(r)return r}return null}_invokeAll(e){let t=Object.values(this.plugins);t.unshift(this);let n=[];for(let r=0;r<t.length;r++){let i=e(t[r]);i&&n.push(i)}return n}getDependency(e,t){let n=e+`:`+t,r=this.cache.get(n);if(!r){switch(e){case`scene`:r=this.loadScene(t);break;case`node`:r=this._invokeOne(function(e){return e.loadNode&&e.loadNode(t)});break;case`mesh`:r=this._invokeOne(function(e){return e.loadMesh&&e.loadMesh(t)});break;case`accessor`:r=this.loadAccessor(t);break;case`bufferView`:r=this._invokeOne(function(e){return e.loadBufferView&&e.loadBufferView(t)});break;case`buffer`:r=this.loadBuffer(t);break;case`material`:r=this._invokeOne(function(e){return e.loadMaterial&&e.loadMaterial(t)});break;case`texture`:r=this._invokeOne(function(e){return e.loadTexture&&e.loadTexture(t)});break;case`skin`:r=this.loadSkin(t);break;case`animation`:r=this._invokeOne(function(e){return e.loadAnimation&&e.loadAnimation(t)});break;case`camera`:r=this.loadCamera(t);break;default:if(r=this._invokeOne(function(n){return n!=this&&n.getDependency&&n.getDependency(e,t)}),!r)throw Error(`Unknown type: `+e);break}this.cache.add(n,r)}return r}getDependencies(e){let t=this.cache.get(e);if(!t){let n=this,r=this.json[e+(e===`mesh`?`es`:`s`)]||[];t=Promise.all(r.map(function(t,r){return n.getDependency(e,r)})),this.cache.add(e,t)}return t}loadBuffer(e){let t=this.json.buffers[e],n=this.fileLoader;if(t.type&&t.type!==`arraybuffer`)throw Error(`THREE.GLTFLoader: `+t.type+` buffer type is not supported.`);if(t.uri===void 0&&e===0)return Promise.resolve(this.extensions[Fb.KHR_BINARY_GLTF].body);let r=this.options;return new Promise(function(e,i){n.load(il.resolveURL(t.uri,r.path),e,void 0,function(){i(Error(`THREE.GLTFLoader: Failed to load buffer "`+t.uri+`".`))})})}loadBufferView(e){let t=this.json.bufferViews[e];return this.getDependency(`buffer`,t.buffer).then(function(e){let n=t.byteLength||0,r=t.byteOffset||0;return e.slice(r,r+n)})}loadAccessor(e){let t=this,n=this.json,r=this.json.accessors[e];if(r.bufferView===void 0&&r.sparse===void 0){let e=mx[r.type],t=dx[r.componentType],n=r.normalized===!0,i=new t(r.count*e);return Promise.resolve(new K(i,e,n))}let i=[];return r.bufferView===void 0?i.push(null):i.push(this.getDependency(`bufferView`,r.bufferView)),r.sparse!==void 0&&(i.push(this.getDependency(`bufferView`,r.sparse.indices.bufferView)),i.push(this.getDependency(`bufferView`,r.sparse.values.bufferView))),Promise.all(i).then(function(e){let i=e[0],a=mx[r.type],o=dx[r.componentType],s=o.BYTES_PER_ELEMENT,c=s*a,l=r.byteOffset||0,u=r.bufferView===void 0?void 0:n.bufferViews[r.bufferView].byteStride,d=r.normalized===!0,f,p;if(u&&u!==c){let e=Math.floor(l/u),n=`InterleavedBuffer:`+r.bufferView+`:`+r.componentType+`:`+e+`:`+r.count,c=t.cache.get(n);c||(f=new o(i,e*u,r.count*u/s),c=new ao(f,u/s),t.cache.add(n,c)),p=new so(c,a,l%u/s,d)}else f=i===null?new o(r.count*a):new o(i,l,r.count*a),p=new K(f,a,d);if(r.sparse!==void 0){let t=mx.SCALAR,n=dx[r.sparse.indices.componentType],s=r.sparse.indices.byteOffset||0,c=r.sparse.values.byteOffset||0,l=new n(e[1],s,r.sparse.count*t),u=new o(e[2],c,r.sparse.count*a);i!==null&&(p=new K(p.array.slice(),p.itemSize,p.normalized)),p.normalized=!1;for(let e=0,t=l.length;e<t;e++){let t=l[e];if(p.setX(t,u[e*a]),a>=2&&p.setY(t,u[e*a+1]),a>=3&&p.setZ(t,u[e*a+2]),a>=4&&p.setW(t,u[e*a+3]),a>=5)throw Error(`THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.`)}p.normalized=d}return p})}loadTexture(e){let t=this.json,n=this.options,r=t.textures[e].source,i=t.images[r],a=this.textureLoader;if(i.uri){let e=n.manager.getHandler(i.uri);e!==null&&(a=e)}return this.loadTextureImage(e,r,a)}loadTextureImage(e,t,n){let r=this,i=this.json,a=i.textures[e],o=i.images[t],s=(o.uri||o.bufferView)+`:`+a.sampler;if(this.textureCache[s])return this.textureCache[s];let c=this.loadImageSource(t,n).then(function(t){t.flipY=!1,t.name=a.name||o.name||``,t.name===``&&typeof o.uri==`string`&&o.uri.startsWith(`data:image/`)===!1&&(t.name=o.uri);let n=(i.samplers||{})[a.sampler]||{};return t.magFilter=fx[n.magFilter]||1006,t.minFilter=fx[n.minFilter]||1008,t.wrapS=px[n.wrapS]||1e3,t.wrapT=px[n.wrapT]||1e3,t.generateMipmaps=!t.isCompressedTexture&&t.minFilter!==1003&&t.minFilter!==1006,r.associations.set(t,{textures:e}),t}).catch(function(){return null});return this.textureCache[s]=c,c}loadImageSource(e,t){let n=this,r=this.json,i=this.options;if(this.sourceCache[e]!==void 0)return this.sourceCache[e].then(e=>e.clone());let a=r.images[e],o=self.URL||self.webkitURL,s=a.uri||``,c=!1;if(a.bufferView!==void 0)s=n.getDependency(`bufferView`,a.bufferView).then(function(e){c=!0;let t=new Blob([e],{type:a.mimeType});return s=o.createObjectURL(t),s});else if(a.uri===void 0)throw Error(`THREE.GLTFLoader: Image `+e+` is missing URI and bufferView`);let l=Promise.resolve(s).then(function(e){return new Promise(function(n,r){let a=n;t.isImageBitmapLoader===!0&&(a=function(e){let t=new yi(e);t.needsUpdate=!0,n(t)}),t.load(il.resolveURL(e,i.path),a,void 0,r)})}).then(function(e){return c===!0&&o.revokeObjectURL(s),xx(e,a),e.userData.mimeType=a.mimeType||Dx(a.uri),e}).catch(function(e){throw console.error(`THREE.GLTFLoader: Couldn't load texture`,s),e});return this.sourceCache[e]=l,l}assignTexture(e,t,n,r){let i=this;return this.getDependency(`texture`,n.index).then(function(a){if(!a)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(a=a.clone(),a.channel=n.texCoord),i.extensions[Fb.KHR_TEXTURE_TRANSFORM]){let e=n.extensions===void 0?void 0:n.extensions[Fb.KHR_TEXTURE_TRANSFORM];if(e){let t=i.associations.get(a);a=i.extensions[Fb.KHR_TEXTURE_TRANSFORM].extendTexture(a,e),i.associations.set(a,t)}}return r!==void 0&&(a.colorSpace=r),e[t]=a,a})}assignFinalMaterial(e){let t=e.geometry,n=e.material,r=t.attributes.tangent===void 0,i=t.attributes.color!==void 0,a=t.attributes.normal===void 0;if(e.isPoints){let e=`PointsMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new Es,lo.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,t.sizeAttenuation=!1,this.cache.add(e,t)),n=t}else if(e.isLine){let e=`LineBasicMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new fs,lo.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,this.cache.add(e,t)),n=t}if(r||i||a){let e=`ClonedMaterial:`+n.uuid+`:`;r&&(e+=`derivative-tangents:`),i&&(e+=`vertex-colors:`),a&&(e+=`flat-shading:`);let t=this.cache.get(e);t||(t=n.clone(),i&&(t.vertexColors=!0),a&&(t.flatShading=!0),r&&(t.normalScale&&(t.normalScale.y*=-1),t.clearcoatNormalScale&&(t.clearcoatNormalScale.y*=-1)),this.cache.add(e,t),this.associations.set(t,this.associations.get(n))),n=t}e.material=n}getMaterialType(){return nc}loadMaterial(e){let t=this,n=this.json,r=this.extensions,i=n.materials[e],a,o={},s=i.extensions||{},c=[];if(s[Fb.KHR_MATERIALS_UNLIT]){let e=r[Fb.KHR_MATERIALS_UNLIT];a=e.getMaterialType(),c.push(e.extendParams(o,i,t))}else{let n=i.pbrMetallicRoughness||{};if(o.color=new G(1,1,1),o.opacity=1,Array.isArray(n.baseColorFactor)){let e=n.baseColorFactor;o.color.setRGB(e[0],e[1],e[2],fr),o.opacity=e[3]}n.baseColorTexture!==void 0&&c.push(t.assignTexture(o,`map`,n.baseColorTexture,dr)),o.metalness=n.metallicFactor===void 0?1:n.metallicFactor,o.roughness=n.roughnessFactor===void 0?1:n.roughnessFactor,n.metallicRoughnessTexture!==void 0&&(c.push(t.assignTexture(o,`metalnessMap`,n.metallicRoughnessTexture)),c.push(t.assignTexture(o,`roughnessMap`,n.metallicRoughnessTexture))),a=this._invokeOne(function(t){return t.getMaterialType&&t.getMaterialType(e)}),c.push(Promise.all(this._invokeAll(function(t){return t.extendMaterialParams&&t.extendMaterialParams(e,o)})))}i.doubleSided===!0&&(o.side=2);let l=i.alphaMode||vx.OPAQUE;if(l===vx.BLEND?(o.transparent=!0,o.depthWrite=!1):(o.transparent=!1,l===vx.MASK&&(o.alphaTest=i.alphaCutoff===void 0?.5:i.alphaCutoff)),i.normalTexture!==void 0&&a!==yo&&(c.push(t.assignTexture(o,`normalMap`,i.normalTexture)),o.normalScale=new B(1,1),i.normalTexture.scale!==void 0)){let e=i.normalTexture.scale;o.normalScale.set(e,e)}if(i.occlusionTexture!==void 0&&a!==yo&&(c.push(t.assignTexture(o,`aoMap`,i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(o.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&a!==yo){let e=i.emissiveFactor;o.emissive=new G().setRGB(e[0],e[1],e[2],fr)}return i.emissiveTexture!==void 0&&a!==yo&&c.push(t.assignTexture(o,`emissiveMap`,i.emissiveTexture,dr)),Promise.all(c).then(function(){let n=new a(o);return i.name&&(n.name=i.name),xx(n,i),t.associations.set(n,{materials:e}),i.extensions&&bx(r,n,i),n})}createUniqueName(e){let t=Cl.sanitizeNodeName(e||``);return t in this.nodeNamesUsed?t+`_`+ ++this.nodeNamesUsed[t]:(this.nodeNamesUsed[t]=0,t)}loadGeometries(e){let t=this,n=this.extensions,r=this.primitiveCache;function i(e){return n[Fb.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(e,t).then(function(n){return jx(n,e,t)})}let a=[];for(let n=0,o=e.length;n<o;n++){let o=e[n],s=wx(o),c=r[s];if(c)a.push(c.promise);else{let e;e=o.extensions&&o.extensions[Fb.KHR_DRACO_MESH_COMPRESSION]?i(o):jx(new q,o,t),r[s]={primitive:o,promise:e},a.push(e)}}return Promise.all(a)}loadMesh(e){let t=this,n=this.json,r=this.extensions,i=n.meshes[e],a=i.primitives,o=[];for(let e=0,t=a.length;e<t;e++){let t=a[e].material===void 0?yx(this.cache):this.getDependency(`material`,a[e].material);o.push(t)}return o.push(t.loadGeometries(a)),Promise.all(o).then(function(n){let o=n.slice(0,n.length-1),s=n[n.length-1],c=[];for(let n=0,l=s.length;n<l;n++){let l=s[n],u=a[n],d,f=o[n];if(u.mode===ux.TRIANGLES||u.mode===ux.TRIANGLE_STRIP||u.mode===ux.TRIANGLE_FAN||u.mode===void 0)d=i.isSkinnedMesh===!0?new Uo(l,f):new jo(l,f),d.isSkinnedMesh===!0&&d.normalizeSkinWeights(),u.mode===ux.TRIANGLE_STRIP?d.geometry=kb(d.geometry,1):u.mode===ux.TRIANGLE_FAN&&(d.geometry=kb(d.geometry,2));else if(u.mode===ux.LINES)d=new ws(l,f);else if(u.mode===ux.LINE_STRIP)d=new bs(l,f);else if(u.mode===ux.LINE_LOOP)d=new Ts(l,f);else if(u.mode===ux.POINTS)d=new js(l,f);else throw Error(`THREE.GLTFLoader: Primitive mode unsupported: `+u.mode);Object.keys(d.geometry.morphAttributes).length>0&&Cx(d,i),d.name=t.createUniqueName(i.name||`mesh_`+e),xx(d,i),u.extensions&&bx(r,d,u),t.assignFinalMaterial(d),c.push(d)}for(let n=0,r=c.length;n<r;n++)t.associations.set(c[n],{meshes:e,primitives:n});if(c.length===1)return i.extensions&&bx(r,c[0],i),c[0];let l=new Qi;i.extensions&&bx(r,l,i),t.associations.set(l,{meshes:e});for(let e=0,t=c.length;e<t;e++)l.add(c[e]);return l})}loadCamera(e){let t,n=this.json.cameras[e],r=n[n.type];if(!r){console.warn(`THREE.GLTFLoader: Missing camera parameters.`);return}return n.type===`perspective`?t=new Yc(ni.radToDeg(r.yfov),r.aspectRatio||1,r.znear||1,r.zfar||2e6):n.type===`orthographic`&&(t=new el(-r.xmag,r.xmag,r.ymag,-r.ymag,r.znear,r.zfar)),n.name&&(t.name=this.createUniqueName(n.name)),xx(t,n),Promise.resolve(t)}loadSkin(e){let t=this.json.skins[e],n=[];for(let e=0,r=t.joints.length;e<r;e++)n.push(this._loadNodeShallow(t.joints[e]));return t.inverseBindMatrices===void 0?n.push(null):n.push(this.getDependency(`accessor`,t.inverseBindMatrices)),Promise.all(n).then(function(e){let n=e.pop(),r=e,i=[],a=[];for(let e=0,o=r.length;e<o;e++){let o=r[e];if(o){i.push(o);let t=new W;n!==null&&t.fromArray(n.array,e*16),a.push(t)}else console.warn(`THREE.GLTFLoader: Joint "%s" could not be found.`,t.joints[e])}return new Jo(i,a)})}loadAnimation(e){let t=this.json,n=this,r=t.animations[e],i=r.name?r.name:`animation_`+e,a=[],o=[],s=[],c=[],l=[];for(let e=0,t=r.channels.length;e<t;e++){let t=r.channels[e],n=r.samplers[t.sampler],i=t.target,u=i.node,d=r.parameters===void 0?n.input:r.parameters[n.input],f=r.parameters===void 0?n.output:r.parameters[n.output];i.node!==void 0&&(a.push(this.getDependency(`node`,u)),o.push(this.getDependency(`accessor`,d)),s.push(this.getDependency(`accessor`,f)),c.push(n),l.push(i))}return Promise.all([Promise.all(a),Promise.all(o),Promise.all(s),Promise.all(c),Promise.all(l)]).then(function(e){let t=e[0],a=e[1],o=e[2],s=e[3],c=e[4],l=[];for(let e=0,r=t.length;e<r;e++){let r=t[e],i=a[e],u=o[e],d=s[e],f=c[e];if(r===void 0)continue;r.updateMatrix&&r.updateMatrix();let p=n._createAnimationTracks(r,i,u,d,f);if(p)for(let e=0;e<p.length;e++)l.push(p[e])}let u=new Cc(i,void 0,l);return xx(u,r),u})}createNodeMesh(e){let t=this.json,n=this,r=t.nodes[e];return r.mesh===void 0?null:n.getDependency(`mesh`,r.mesh).then(function(e){let t=n._getNodeRef(n.meshCache,r.mesh,e);return r.weights!==void 0&&t.traverse(function(e){if(e.isMesh)for(let t=0,n=r.weights.length;t<n;t++)e.morphTargetInfluences[t]=r.weights[t]}),t})}loadNode(e){let t=this.json,n=this,r=t.nodes[e],i=n._loadNodeShallow(e),a=[],o=r.children||[];for(let e=0,t=o.length;e<t;e++)a.push(n.getDependency(`node`,o[e]));let s=r.skin===void 0?Promise.resolve(null):n.getDependency(`skin`,r.skin);return Promise.all([i,Promise.all(a),s]).then(function(e){let t=e[0],n=e[1],r=e[2];r!==null&&t.traverse(function(e){e.isSkinnedMesh&&e.bind(r,Ox)});for(let e=0,r=n.length;e<r;e++)t.add(n[e]);if(t.userData.pivot!==void 0&&n.length>0){let e=t.userData.pivot,r=n[0];t.pivot=new H().fromArray(e),t.position.x-=e[0],t.position.y-=e[1],t.position.z-=e[2],r.position.set(0,0,0),delete t.userData.pivot}return t})}_loadNodeShallow(e){let t=this.json,n=this.extensions,r=this;if(this.nodeCache[e]!==void 0)return this.nodeCache[e];let i=t.nodes[e],a=i.name?r.createUniqueName(i.name):``,o=[],s=r._invokeOne(function(t){return t.createNodeMesh&&t.createNodeMesh(e)});return s&&o.push(s),i.camera!==void 0&&o.push(r.getDependency(`camera`,i.camera).then(function(e){return r._getNodeRef(r.cameraCache,i.camera,e)})),r._invokeAll(function(t){return t.createNodeAttachment&&t.createNodeAttachment(e)}).forEach(function(e){o.push(e)}),this.nodeCache[e]=Promise.all(o).then(function(t){let o;if(o=i.isBone===!0?new Wo:t.length>1?new Qi:t.length===1?t[0]:new Zi,o!==t[0])for(let e=0,n=t.length;e<n;e++)o.add(t[e]);if(i.name&&(o.userData.name=i.name,o.name=a),xx(o,i),i.extensions&&bx(n,o,i),i.matrix!==void 0){let e=new W;e.fromArray(i.matrix),o.applyMatrix4(e)}else i.translation!==void 0&&o.position.fromArray(i.translation),i.rotation!==void 0&&o.quaternion.fromArray(i.rotation),i.scale!==void 0&&o.scale.fromArray(i.scale);if(!r.associations.has(o))r.associations.set(o,{});else if(i.mesh!==void 0&&r.meshCache.refs[i.mesh]>1){let e=r.associations.get(o);r.associations.set(o,{...e})}return r.associations.get(o).nodes=e,o}),this.nodeCache[e]}loadScene(e){let t=this.extensions,n=this.json.scenes[e],r=this,i=new Qi;n.name&&(i.name=r.createUniqueName(n.name)),xx(i,n),n.extensions&&bx(t,i,n);let a=n.nodes||[],o=[];for(let e=0,t=a.length;e<t;e++)o.push(r.getDependency(`node`,a[e]));return Promise.all(o).then(function(e){for(let t=0,n=e.length;t<n;t++){let n=e[t];n.parent===null?i.add(n):i.add(Ab(n))}return r.associations=(e=>{let t=new Map;for(let[e,n]of r.associations)(e instanceof lo||e instanceof yi)&&t.set(e,n);return e.traverse(e=>{let n=r.associations.get(e);n!=null&&t.set(e,n)}),t})(i),i})}_createAnimationTracks(e,t,n,r,i){let a=[],o=e.name?e.name:e.uuid,s=[];function c(e){e.morphTargetInfluences&&s.push(e.name?e.name:e.uuid)}gx[i.path]===gx.weights?(c(e),e.isGroup&&e.children.forEach(c)):s.push(o);let l;switch(gx[i.path]){case gx.weights:l=vc;break;case gx.rotation:l=bc;break;case gx.translation:case gx.scale:l=Sc;break;default:switch(n.itemSize){case 1:l=vc;break;default:l=Sc;break}break}let u=r.interpolation===void 0?tr:_x[r.interpolation],d=this._getArrayFromAccessor(n);for(let e=0,n=s.length;e<n;e++){let n=new l(s[e]+`.`+gx[i.path],t.array,d,u);r.interpolation===`CUBICSPLINE`&&this._createCubicSplineTrackInterpolant(n),a.push(n)}return a}_getArrayFromAccessor(e){let t=e.array;if(e.normalized){let e=Ex(t.constructor),n=new Float32Array(t.length);for(let r=0,i=t.length;r<i;r++)n[r]=t[r]*e;t=n}return t}_createCubicSplineTrackInterpolant(e){e.createInterpolant=function(e){return new(this instanceof bc?lx:sx)(this.times,this.values,this.getValueSize()/3,e)},e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}};function Ax(e,t,n){let r=t.attributes,i=new Sa;if(r.POSITION!==void 0){let e=n.json.accessors[r.POSITION],t=e.min,a=e.max;if(t!==void 0&&a!==void 0){if(i.set(new H(t[0],t[1],t[2]),new H(a[0],a[1],a[2])),e.normalized){let t=Ex(dx[e.componentType]);i.min.multiplyScalar(t),i.max.multiplyScalar(t)}}else{console.warn(`THREE.GLTFLoader: Missing min/max properties for accessor POSITION.`);return}}else return;let a=t.targets;if(a!==void 0){let e=new H,t=new H;for(let r=0,i=a.length;r<i;r++){let i=a[r];if(i.POSITION!==void 0){let r=n.json.accessors[i.POSITION],a=r.min,o=r.max;if(a!==void 0&&o!==void 0){if(t.setX(Math.max(Math.abs(a[0]),Math.abs(o[0]))),t.setY(Math.max(Math.abs(a[1]),Math.abs(o[1]))),t.setZ(Math.max(Math.abs(a[2]),Math.abs(o[2]))),r.normalized){let e=Ex(dx[r.componentType]);t.multiplyScalar(e)}e.max(t)}else console.warn(`THREE.GLTFLoader: Missing min/max properties for accessor POSITION.`)}}i.expandByVector(e)}e.boundingBox=i;let o=new Za;i.getCenter(o.center),o.radius=i.min.distanceTo(i.max)/2,e.boundingSphere=o}function jx(e,t,n){let r=t.attributes,i=[];function a(t,r){return n.getDependency(`accessor`,t).then(function(t){e.setAttribute(r,t)})}for(let t in r){let n=hx[t]||t.toLowerCase();n in e.attributes||i.push(a(r[t],n))}if(t.indices!==void 0&&!e.index){let r=n.getDependency(`accessor`,t.indices).then(function(t){e.setIndex(t)});i.push(r)}return li.workingColorSpace!==`srgb-linear`&&`COLOR_0`in r&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${li.workingColorSpace}" not supported.`),xx(e,t),Ax(e,t,n),Promise.all(i).then(function(){return t.targets===void 0?e:Sx(e,t.targets,n)})}var Mx=class{models=new Map;animations=new Map;modelKeys=new Map;animationKeys=new Map;loader;constructor(){this.loader=new Mb,this.loader.register(e=>new Qy(e))}load(e){for(let[t,n]of Object.entries(e)){let e=n;typeof e.url==`string`&&(e.type===`model`?this.modelKeys.set(`$${t}`,e.url):e.type===`animation`&&this.animationKeys.set(`$${t}`,{url:e.url,clip:e.clip}))}}animationRefs(){return[...this.animationKeys.keys()]}modelRefs(){return[...this.modelKeys.keys()]}getModel(e){let t=this.modelKeys.get(e)??e,n=this.models.get(t);return n||(n={status:`loading`,scene:null,animations:[],isVrm:!1,vrm:null,claimedBy:null,retargeted:new Map},this.models.set(t,n),this.loader.load(t,e=>{let t=e.userData.vrm;t?(Ob.removeUnnecessaryVertices(e.scene),Ob.combineSkeletons(e.scene),Ob.rotateVRM0(t),n.scene=t.scene,n.vrm=t,n.isVrm=!0):n.scene=e.scene,n.animations=e.animations??[],n.status=`ready`},void 0,e=>{n.status=`error`,n.error=e instanceof Error?e.message:String(e),console.error(`incanto: failed to load model '${t}':`,e)}),n)}getAnimation(e){let t=this.animationKeys.get(e)??{url:e},n=this.animations.get(t.url);return n||(n={status:`loading`,clips:[],scene:null,clip:t.clip},this.animations.set(t.url,n),this.loader.load(t.url,e=>{n.clips=e.animations??[],n.scene=e.scene,n.status=`ready`,n.clips.length===0&&console.warn(`incanto: animation asset '${t.url}' contains no clips`)},void 0,e=>{n.status=`error`,n.error=e instanceof Error?e.message:String(e),console.error(`incanto: failed to load animation '${t.url}':`,e)}),n)}dispose(){for(let e of this.models.values())e.scene?.traverse(e=>{let t=e;t.geometry?.dispose();let n=Array.isArray(t.material)?t.material:[t.material];for(let e of n)if(e){for(let t of Object.values(e))t?.isTexture&&t.dispose();e.dispose()}});this.models.clear(),this.animations.clear()}},Nx=Math.atan(1/Math.SQRT2);function Px(e,t,n,r,i,a){let o=[t[0],t[1]+n,t[2]];if(e===`firstPerson`)return{position:o,rotation:[-i,r,0]};if(e===`quarter`){let e=Nx;return{position:[o[0],o[1]+a*Math.sin(e),o[2]+a*Math.cos(e)],rotation:[-e,0,0]}}if(e===`side`)return{position:[o[0],o[1],o[2]+a],rotation:[0,0,0]};let s=Math.cos(i);return{position:[o[0]+Math.sin(r)*s*a,o[1]+Math.sin(i)*a,o[2]+Math.cos(r)*s*a],rotation:[-i,r,0]}}function Fx(e,t,n,r,i){let a=t[0]-e[0],o=t[1]-e[1],s=t[2]-e[2],c=Math.hypot(a,o,s);if(c<1e-4)return[t[0],t[1],t[2]];let l=[a/c,o/c,s/c],u=n(e,l,c);if(u===null)return[t[0],t[1],t[2]];let d=Math.min(c,Math.max(i,u-r));return[e[0]+l[0]*d,e[1]+l[1]*d,e[2]+l[2]*d]}function Ix(e,t,n){let r=t(e,n);return r===null||r>=n?[e[0],e[1],e[2]]:[e[0],e[1]+(n-r),e[2]]}function Lx(e,t,n){let r=Math.sin(n),i=Math.cos(n);return[e*i-t*r,0,-e*r-t*i]}function Rx(e,t){return e?Math.min(.6+(t?.4:0),1):0}function zx(e,t){return e?t<=0?`idle`:t<.3?`walk`:t<.7?`run`:`fastRun`:`airborne`}var Bx=class extends qp{static typeName=`Joint3D`;static props={type:{default:`spherical`,options:[`fixed`,`spherical`,`rope`,`spring`]},target:{default:``},anchor:{default:[0,0,0]},targetAnchor:{default:[0,0,0]},length:{default:0},stiffness:{default:50},damping:{default:5}};type=`spherical`;target=``;anchor=[0,0,0];targetAnchor=[0,0,0];length=0;stiffness=50;damping=5;onEnterTree(){if(!(this.parent instanceof Jp))throw new y(`TREE_VIOLATION`,`Joint3D '${this.name}' must be a child of a physics body (its body A); parent is '${this.parent?.name??`none`}'.`);if(this.target===``)throw new y(`BAD_FORMAT`,`Joint3D '${this.name}' needs a "target" node path to the body it links to.`)}_resolveBodies(){let e=this.parent,t=this.getNodeOrNull(this.target);if(!(t instanceof Jp))throw new y(`NODE_NOT_FOUND`,`Joint3D '${this.name}': target '${this.target}' is not a physics body.`);return{a:e,b:t}}},Vx=256,Hx=.3,Ux=.6,Wx=45;function Gx(e){let{width:t,depth:n,segsX:r,segsZ:i,maxHeight:a,seed:o}=e,s=e.roughness??.5,c=e.detail??4,l=e.flatThreshold??.95,u=e.islandEdge??!1,d=Math.max(0,Math.min(e.edgeWrapRadius??20,Wx)),f=e.edgeBottom??-50,p=e.edgeCornerSmoothness??1,m=(e.basins??[]).map(e=>({cx:e.x+t/2,cz:e.z+n/2,radius:e.radius,depth:e.depth})),h=(e.channels??[]).map(e=>({half:Math.max(e.width,0)/2,taper:Math.max(e.taper??e.width,.001),depth:e.depth,segs:e.path.map(e=>({x:(e[0]??0)+t/2,z:(e[1]??0)+n/2})).flatMap((e,t,n)=>t===0?[]:[{ax:n[t-1].x,az:n[t-1].z,bx:e.x,bz:e.z}])})).filter(e=>e.segs.length>0&&e.depth!==0),g=et(o),_=(e,t)=>(g(e,t)+1)*.5,v=(e,t)=>{let n=e/Vx,r=t/Vx,i=0,o=.2,u=5;for(let e=0;e<5;e++)i+=_(n*o,r*o)*u,u*=.5,o*=2;let d=0;o=.5,u=.1;for(let e=0;e<c;e++)d+=_(n*o,r*o)*u,u*=s,o*=2;i=Math.abs(i)**1.5*Math.sign(i),i<Hx&&(i*=.3);let f=a*(i+d*(i*.5+.5)+1)/2,p=a*l;if(Math.abs(f-p)<Ux&&(f=p),m.length>0){let n=0,r=0;for(let i of m){let a=Math.hypot(e-i.cx,t-i.cz);if(a<i.radius){let e=a/i.radius,t=1-e*e*(3-2*e);i.depth>=0?n=Math.max(n,i.depth*t):r=Math.max(r,-i.depth*t)}}f+=r-n}if(h.length>0){let n=0;for(let r of h){let i=1/0;for(let n of r.segs){let a=n.bx-n.ax,o=n.bz-n.az,s=a*a+o*o,c=s>1e-9?Math.min(1,Math.max(0,((e-n.ax)*a+(t-n.az)*o)/s)):0,l=n.ax+a*c,u=n.az+o*c,d=Math.hypot(e-l,t-u);if(d<i&&(i=d),i<=r.half)break}if(i>=r.half+r.taper)continue;let a=Math.min(1,Math.max(0,(i-r.half)/r.taper));n=Math.max(n,r.depth*(1-a*a*(3-2*a)))}f-=n}return f},y=(e,a,o)=>{if(!u||d<=0)return o;let s=d,c=Math.min(e,t-e),l=Math.min(a,n-a),m=(t/r+n/i)*.002,h=Math.max(0,s-c+m),g=Math.max(0,s-l+m);if(h<=0&&g<=0)return o;let _=2+(1-Math.min(1,Math.max(0,p)))*30,v=(h**_+g**_)**(1/_),y=o-(s-Math.sqrt(Math.max(0,s*s-v*v)));return v>=s&&(y=Math.min(y,f)),y},b=r+1,x=i+1,S=new Float32Array(b*x),C=1/0,w=-1/0;for(let e=0;e<x;e++){let a=e/i*n;for(let n=0;n<b;n++){let i=n/r*t,o=v(i,a);o<C&&(C=o),o>w&&(w=o),S[e*b+n]=y(i,a,o)}}let T=(e,a)=>{let o=Math.min(Math.max((e+t/2)/t*r,0),r),s=Math.min(Math.max((a+n/2)/n*i,0),i),c=Math.min(Math.floor(o),r-1),l=Math.min(Math.floor(s),i-1),u=o-c,d=s-l,f=S[l*b+c],p=S[l*b+c+1],m=S[(l+1)*b+c],h=S[(l+1)*b+c+1];return(f*(1-u)+p*u)*(1-d)+(m*(1-u)+h*u)*d},E=(e,r)=>v(e+t/2,r+n/2);return{width:t,depth:n,segsX:r,segsZ:i,heights:S,minHeight:C,maxHeight:w,heightAt:T,baseHeight:E,slopeAt:(e,t)=>{let n=(E(e+1,t)-E(e-1,t))/2,r=(E(e,t+1)-E(e,t-1))/2;return Math.atan(Math.sqrt(n*n+r*r))}}}function Kx(e,t,n,r){return e<t-r||e>n+r?0:e>=t&&e<=n?1:e<t?(e-(t-r))/r:(n+r-e)/r}function qx(e,t,n,r=1.2){let i=[0,0,0,0],a=Math.min(n.length,4),o=0;for(let s=0;s<a;s++){let a=n[s],[c,l]=a.heightRange??[0,1],[u,d]=a.slopeRange??[0,Math.PI/2],f=Kx(e,c,l,a.heightBlendRange??.1)*Kx(t,u,d,a.slopeBlendRange??.1);f**=1/r,i[s]=f,o+=f}if(o===0)return[1,0,0,0];for(let e=0;e<4;e++)i[e]=i[e]/o;return i}function Jx(e,t,n){let r=e.indexOf(t);if(r===-1)throw new y(`BAD_FORMAT`,`Terrain3D shader patch: marker '${t}' not found in the three.js shader — the installed three version moved its chunks.`);let i=r+t.length;return`${e.slice(0,i)}\n${n}${e.slice(i)}`}var Yx=`
|
|
6611
6640
|
varying vec3 vSplatColor;
|
|
6612
6641
|
varying vec3 vWorldPosition;
|
|
6613
6642
|
varying vec2 vUvSplat;
|
|
6614
|
-
`,
|
|
6643
|
+
`,Xx=`
|
|
6615
6644
|
vSplatColor = color;
|
|
6616
6645
|
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
|
6617
6646
|
vUvSplat = uv;
|
|
6618
|
-
`,
|
|
6647
|
+
`,Zx=`
|
|
6619
6648
|
uniform sampler2D splatTexture1;
|
|
6620
6649
|
uniform sampler2D splatTexture2;
|
|
6621
6650
|
uniform sampler2D splatTexture3;
|
|
@@ -6736,7 +6765,7 @@ vec3 perturbSplatNormal(vec3 normal, vec3 viewPos, vec2 uv, vec3 normalSample) {
|
|
|
6736
6765
|
|
|
6737
6766
|
return normalize(TBN * normalMap);
|
|
6738
6767
|
}
|
|
6739
|
-
`,
|
|
6768
|
+
`,Qx=`
|
|
6740
6769
|
// World-based UVs per layer (texture repeat baked in)
|
|
6741
6770
|
vec2 baseWorldUV1 = vec2(vWorldPosition.x, vWorldPosition.z) * (splatTextureRepeat1 * 0.1);
|
|
6742
6771
|
vec2 baseWorldUV2 = vec2(vWorldPosition.x, vWorldPosition.z) * (splatTextureRepeat2 * 0.1);
|
|
@@ -6842,14 +6871,14 @@ if (uWetlineY > -1.0e8) {
|
|
|
6842
6871
|
}
|
|
6843
6872
|
|
|
6844
6873
|
diffuseColor = vec4(splatColor.rgb, diffuseColor.a);
|
|
6845
|
-
|
|
6874
|
+
`,$x=`
|
|
6846
6875
|
roughnessFactor = blendedRoughness;
|
|
6847
|
-
`,
|
|
6876
|
+
`,eS=`
|
|
6848
6877
|
iblIrradiance *= splatEnvCut;
|
|
6849
6878
|
radiance *= splatEnvCut;
|
|
6850
|
-
`,
|
|
6879
|
+
`,tS=`
|
|
6851
6880
|
metalnessFactor = blendedMetalness;
|
|
6852
|
-
`,
|
|
6881
|
+
`,nS=`
|
|
6853
6882
|
#ifdef USE_TERRAIN_NORMALMAP
|
|
6854
6883
|
vec3 normalSample1 = vec3(0.5, 0.5, 1.0);
|
|
6855
6884
|
vec3 normalSample2 = vec3(0.5, 0.5, 1.0);
|
|
@@ -6894,7 +6923,7 @@ if (splatDetailAmount > 0.001) {
|
|
|
6894
6923
|
|
|
6895
6924
|
normal = perturbSplatNormal(normal, vViewPosition, vUvSplat, blendedNormalSample);
|
|
6896
6925
|
#endif
|
|
6897
|
-
`;function qx(e,t){for(let n=0;n<4;n++){let r=n+1;e.uniforms[`splatTexture${r}`]={value:t.textures[n]??t.textures[0]??null},e.uniforms[`splatNormalMap${r}`]={value:t.normalMaps[n]??null},e.uniforms[`splatTextureRepeat${r}`]={value:t.repeats[n]??1},e.uniforms[`splatRoughness${r}`]={value:t.roughness[n]??1},e.uniforms[`splatMetalness${r}`]={value:t.metalness[n]??0},e.uniforms[`uvNoiseIntensity${r}`]={value:t.uvNoiseIntensity[n]??.15}}e.uniforms.splatTextureCount={value:Math.min(4,t.layerCount)},e.uniforms.uWetlineY={value:-1e9},e.uniforms.uWetlineBand={value:1.1},e.uniforms.uWetTime={value:0},e.uniforms.splatEnvCut={value:t.envCut},e.vertexShader=Rx(e.vertexShader,`#include <common>`,zx),e.vertexShader=Rx(e.vertexShader,`#include <begin_vertex>`,Bx);let n=e.fragmentShader;n=Rx(n,`#include <common>`,Vx),n=Rx(n,`#include <color_fragment>`,Hx),n=Rx(n,`#include <roughnessmap_fragment>`,Ux),n=Rx(n,`#include <metalnessmap_fragment>`,Gx),n=Rx(n,`#include <normal_fragment_maps>`,Kx),n=Rx(n,`#include <lights_fragment_maps>`,Wx),t.hasNormalMaps&&(n=`#define USE_TERRAIN_NORMALMAP\n${n}`),e.fragmentShader=n}var Jx=[`island`,`alpine`,`plains`,`desert`,`grassland`,`forest`,`savanna`,`snow`,`wetland`,`volcanic`,`custom`],Yx=`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,Xx=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground`,Zx=1/3,Qx=Math.PI/4;function $x(e,t,n){return{texture:`${e}/${t}.png`,normalMap:`${e}/${t}_normal.png`,...n}}function eS(e,t){let n=t.replace(/\/$/,``);switch(e){case`island`:return[$x(n,`sand`,{heightRange:[0,.12],slopeRange:[0,Math.PI/2],heightBlendRange:.05,roughness:.9}),$x(n,`grass`,{heightRange:[.1,.7],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.1,roughness:.8}),$x(n,`stone`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.5,roughness:.85}),$x(n,`snow`,{heightRange:[.8,1],slopeRange:[0,Math.PI/3],heightBlendRange:.1,roughness:.6})];case`alpine`:return[$x(n,`grass`,{heightRange:[0,.45],slopeRange:[0,Math.PI/5],heightBlendRange:.1,roughness:.8}),$x(n,`stone`,{heightRange:[.3,1],slopeRange:[0,Math.PI],heightBlendRange:.25,slopeBlendRange:.5,roughness:.85}),$x(n,`gravel`,{heightRange:[0,1],slopeRange:[Math.PI/5,Math.PI],heightBlendRange:.5,slopeBlendRange:.15,roughness:.9}),$x(n,`snow`,{heightRange:[.55,1],slopeRange:[0,Math.PI/3],heightBlendRange:.12,roughness:.55})];case`plains`:return[$x(n,`grass`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.1,roughness:.8}),$x(n,`dirt`,{heightRange:[.35,.65],slopeRange:[0,Math.PI/5],heightBlendRange:.2,roughness:.9}),$x(n,`gravel`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.9})];case`desert`:return[$x(n,`sand`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),$x(n,`gravel`,{heightRange:[0,.15],slopeRange:[0,Math.PI/3],heightBlendRange:.08,roughness:.9}),$x(n,`stone`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.4,roughness:.85})];case`grassland`:return n===`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`?[{texture:`${Xx}/grass.jpg`,heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.15,roughness:1,repeat:Zx,uvNoiseIntensity:0},{texture:`${Xx}/dirt_color.jpg`,heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:1,repeat:Zx,uvNoiseIntensity:0}]:[$x(n,`grass`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.15,roughness:.8}),$x(n,`dirt`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.9})];case`forest`:return n===`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`?[{texture:`${Xx}/dirt_color.jpg`,heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:1,repeat:Zx,uvNoiseIntensity:0},{texture:`${Xx}/grass.jpg`,heightRange:[-2,-1],roughness:1,repeat:Zx,uvNoiseIntensity:0}]:[$x(n,`dirt`,{heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:.9}),$x(n,`grass`,{heightRange:[-2,-1],roughness:.8})];case`savanna`:return[$x(n,`grass`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),$x(n,`sand`,{heightRange:[0,.22],slopeRange:[0,Math.PI/4],heightBlendRange:.12,roughness:.95}),$x(n,`dirt`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.95})];case`snow`:return[$x(n,`snow`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.18,roughness:.55}),$x(n,`stone`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.35,roughness:.85})];case`wetland`:return[$x(n,`grass`,{heightRange:[0,1],slopeRange:[0,Qx],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),$x(n,`dirt`,{heightRange:[0,1],slopeRange:[Qx,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.95})];case`volcanic`:return[$x(n,`stone`,{heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:.95}),$x(n,`gravel`,{heightRange:[0,.28],slopeRange:[0,Math.PI/3],heightBlendRange:.14,slopeBlendRange:.2,roughness:.95})];case`custom`:return[]}}var tS={scale:100,threshold:.7,blend:.1},nS={scale:55,threshold:.58,blend:.12},rS={scale:85,threshold:.62,blend:.12},iS={scale:48,threshold:.5,blend:.14};function aS(e,t){let n=et(e+27927);return(e,r)=>{let i=(.5+.5*n(e/t.scale,r/t.scale)-(t.threshold-t.blend))/(2*t.blend),a=Math.min(1,Math.max(0,i));return a*a*(3-2*a)}}function oS(e,t){return e===`grassland`?aS(t,tS):e===`forest`?aS(t,nS):e===`savanna`?aS(t,rS):e===`wetland`?aS(t,iS):null}function sS(e){return e===`savanna`?{from:0,to:2}:e===`grassland`||e===`forest`||e===`wetland`?{from:0,to:1}:null}var cS=128,lS=class extends qp{orderGroup=`terrain`;static typeName=`Terrain3D`;static props={orderGroup:{default:`terrain`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},size:{default:[200,200]},maxHeight:{default:28},seed:{default:1},resolution:{default:128},theme:{default:`island`,options:Jx},roughness:{default:.5},detail:{default:4},flatThreshold:{default:.95},islandEdge:{default:null},layers:{default:[]},textureBase:{default:Yx},basins:{default:[]},channels:{default:[]},wetline:{default:null}};size=[200,200];maxHeight=28;seed=1;resolution=128;theme=`island`;roughness=.5;detail=4;flatThreshold=.95;islandEdge=null;layers=[];textureBase=Yx;basins=[];channels=[];wetline=null;splatUniforms=null;wetTime=0;update(e){this.wetTime+=e;let t=this.splatUniforms;if(!t)return;let n=this.wetline;t.uWetlineY&&(t.uWetlineY.value=typeof n?.y==`number`?n.y:-1e9),t.uWetlineBand&&(t.uWetlineBand.value=typeof n?.band==`number`?n.band:1.1),t.uWetTime&&(t.uWetTime.value=this.wetTime)}static validateJson(e){let t=e;if(!Jx.includes(t.theme))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' theme must be one of [${Jx.join(`, `)}], got '${t.theme}'.`,{prop:`theme`,validOptions:Jx});if(!((t.size[0]??0)>0)||!((t.size[1]??0)>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' size must be positive [width, depth] meters, got ${JSON.stringify(t.size)}.`,{prop:`size`});if(!(t.maxHeight>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' maxHeight must be > 0, got ${t.maxHeight}.`,{prop:`maxHeight`});if(!Number.isInteger(t.resolution)||t.resolution<2||t.resolution>cS)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' resolution must be an integer in [2, ${cS}] (grid segments per side), got ${t.resolution}.`,{prop:`resolution`});if(!(t.roughness>0)||!Number.isFinite(t.roughness))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' roughness must be a finite number > 0, got ${t.roughness}.`,{prop:`roughness`});if(!Number.isInteger(t.detail)||t.detail<0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' detail must be an integer ≥ 0 (octave count), got ${t.detail}.`,{prop:`detail`});if(!(t.flatThreshold>=0)||!Number.isFinite(t.flatThreshold))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' flatThreshold must be a finite number ≥ 0, got ${t.flatThreshold}.`,{prop:`flatThreshold`});if(t.islandEdge!==null&&typeof t.islandEdge!=`boolean`)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' islandEdge must be true, false or null (null = theme default), got ${JSON.stringify(t.islandEdge)}.`,{prop:`islandEdge`});let n=t.wetline;if(n!==null){if(typeof n!=`object`||Array.isArray(n)||!Number.isFinite(n.y))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' wetline must be null or { y, band? } with a finite y, got ${JSON.stringify(t.wetline)}.`,{prop:`wetline`});if(n.band!==void 0&&!(n.band>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' wetline.band must be > 0 meters, got ${JSON.stringify(n.band)}.`,{prop:`wetline`})}if(!Array.isArray(t.basins))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' basins must be an array of { x, z, radius, depth }, got ${JSON.stringify(t.basins)}.`,{prop:`basins`});if(t.basins.forEach((t,n)=>{if(!t||typeof t!=`object`||!Number.isFinite(t.x)||!Number.isFinite(t.z)||!(t.radius>0)||!Number.isFinite(t.depth)||t.depth===0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' basins[${n}] needs finite x, z, positive radius and nonzero depth (negative = mound), got ${JSON.stringify(t)}.`,{prop:`basins`})}),!Array.isArray(t.channels))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' channels must be an array of { path, width, depth, taper? }, got ${JSON.stringify(t.channels)}.`,{prop:`channels`});if(t.channels.forEach((t,n)=>{let r=t.path;if(!(t&&typeof t==`object`&&Array.isArray(r)&&r.length>=2&&r.every(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1]))&&t.width>0&&t.depth>0&&(t.taper===void 0||t.taper>0)))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' channels[${n}] needs a path of 2+ [x, z] points plus positive width and depth, got ${JSON.stringify(t)}.`,{prop:`channels`})}),t.theme===`custom`){if(!Array.isArray(t.layers)||t.layers.length<1||t.layers.length>4)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' theme 'custom' needs 1–4 layers, got ${Array.isArray(t.layers)?t.layers.length:typeof t.layers}.`,{prop:`layers`});t.layers.forEach((t,n)=>{fS(e.name,t,n)})}else if(Array.isArray(t.layers)&&t.layers.length>0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' layers is only read with theme 'custom' — preset theme '${t.theme}' defines its own. Drop layers or switch to theme: 'custom'.`,{prop:`layers`})}heightmap=null;heightmapKey=``;builtKey=``;loadedTextures=[];_createObject3D(){let e=new q;return e.setAttribute(`position`,new K(new Float32Array,3)),new jo(e,new nc({vertexColors:!0}))}heightAt(e,t){let n=0,r=0,i=0;for(let e=this;e;e=e.parent)e instanceof qp&&(n+=e.position[0]??0,r+=e.position[1]??0,i+=e.position[2]??0);return this._heightmap().heightAt(e-n,t-i)+r}_heightmap(){let e=this.segments(),t=JSON.stringify([this.size,this.maxHeight,this.seed,e,this.roughness,this.detail,this.flatThreshold,this.effectiveIslandEdge(),this.basins,this.channels]);return(!this.heightmap||t!==this.heightmapKey)&&(this.heightmap=Fx({width:this.size[0]??1,depth:this.size[1]??1,segsX:e,segsZ:e,maxHeight:this.maxHeight,seed:this.seed,roughness:this.roughness,detail:this.detail,flatThreshold:this.flatThreshold,islandEdge:this.effectiveIslandEdge(),basins:this.basins,channels:this.channels}),this.heightmapKey=t),this.heightmap}resolvedLayers(){return this.theme===`custom`?this.layers:eS(this.theme,this.textureBase)}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded()}effectiveIslandEdge(){return this.islandEdge??this.theme===`island`}segments(){return Math.max(2,Math.min(Math.floor(this.resolution),cS))}rebuildIfNeeded(){let e=JSON.stringify([this.size,this.maxHeight,this.seed,this.segments(),this.theme,this.roughness,this.detail,this.flatThreshold,this.islandEdge,this.layers,this.textureBase,this.basins]);if(e===this.builtKey)return;this.builtKey=e;let t=this._ensureObject3D();t.geometry.dispose(),t.geometry=this.buildGeometry(),t.material.dispose(),this.disposeTextures(),t.material=this.buildMaterial(),t.receiveShadow=!0,t.castShadow=!0}buildGeometry(){let e=this._heightmap(),t=new Ws(e.width,e.depth,e.segsX,e.segsZ);t.rotateX(-Math.PI/2);let n=t.getAttribute(`position`);for(let t=0;t<n.count;t++)n.setY(t,e.heights[t]);n.needsUpdate=!0,t.computeVertexNormals();let r=this.resolvedLayers(),i=e.maxHeight-e.minHeight||1,a=new Float32Array(n.count*3),o=this.theme===`custom`?null:sS(this.theme),s=o?oS(this.theme,this.seed):null;for(let t=0;t<n.count;t++){let c=n.getX(t),l=n.getZ(t),u=Lx(Math.min(1,Math.max(0,(n.getY(t)-e.minHeight)/i)),e.slopeAt(c,l),r);if(s&&o){let e=(u[o.from]??0)*s(c,l);u[o.from]=(u[o.from]??0)-e,u[o.to]=(u[o.to]??0)+e}a[t*3]=u[0],a[t*3+1]=u[1],a[t*3+2]=u[2]}return t.setAttribute(`color`,new K(a,3)),t}buildMaterial(){let e=this.resolvedLayers(),t=new nc({vertexColors:!0}),n=typeof document<`u`?new Ic:null,r=(e,t)=>{if(!n||!e)return null;let r=n.load(e);return r.wrapS=It,r.wrapT=It,r.anisotropy=8,t&&(r.colorSpace=dr),this.loadedTextures.push(r),r},i=e.map(e=>r(e.texture,!0)),a=e.map(e=>r(e.normalMap,!1)),o=a.some(e=>e!==null);if(o)for(let e=0;e<a.length;e++)a[e]||(a[e]=dS());let s={textures:i,normalMaps:a,repeats:e.map(e=>e.repeat??2),roughness:e.map(e=>e.roughness??1),metalness:e.map(e=>e.metalness??0),uvNoiseIntensity:e.map(e=>e.uvNoiseIntensity??.15),envCut:.45,layerCount:Math.min(4,e.length),hasNormalMaps:o};return t.onBeforeCompile=e=>{qx(e,s),this.splatUniforms=e.uniforms},t.customProgramCacheKey=()=>`incanto-terrain-splat:${+!!o}`,t}disposeTextures(){for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[]}free(){let e=this._ensureObject3D();e.geometry.dispose(),e.material.dispose(),this.disposeTextures(),this.heightmap=null,super.free()}},uS=null;function dS(){return uS||(uS=new Go(new Uint8Array([128,128,255,255]),1,1),uS.needsUpdate=!0),uS}function fS(e,t,n){let r=`layers[${n}]`;if(typeof t!=`object`||!t||Array.isArray(t))throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r} must be an object ({texture, heightRange?, slopeRange?, …}).`,{prop:`layers`});let i=t;if(typeof i.texture!=`string`||i.texture.length===0)throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r} needs "texture": a texture URL string.`,{prop:`layers`});for(let t of[`heightRange`,`slopeRange`]){let n=i[t];if(n!==void 0&&(!Array.isArray(n)||n.length!==2||n.some(e=>typeof e!=`number`||!Number.isFinite(e))))throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r}.${t} must be [min, max] numbers, got ${JSON.stringify(n)}.`,{prop:`layers`})}}var pS=Math.PI/180;async function mS(e,t){let n=await _h(()=>import(`./rapier-DE6a0vmv.js`),[],import.meta.url);return await n.init({}),new hS(n,e,t)}var hS=class{R;engine;debugDraw=!1;dimension=`3d`;unregisterDebug;warnedNoCollider=new WeakSet;entries=new Map;byColliderHandle=new Map;world;events;kcc;disconnect;lastDt=1/60;optsGravity;lastScene=null;constructor(e,t,n){this.R=e,this.engine=t,this.optsGravity=n?.gravity,this.lastScene=t.scene;let r=t.scene?.physics?.gravity,i=n?.gravity??r??[0,-9.81,0];this.world=new e.World({x:i[0]??0,y:i[1]??0,z:i[2]??0}),this.kcc=this.world.createCharacterController(.01),this.events=new e.EventQueue(!0),this.unregisterDebug=dh(this),this.disconnect=t.fixedUpdated.connect(e=>this.step(e)),this.syncBodies()}step(e){if(this.lastDt=e,this.engine.scene!==this.lastScene&&(this.lastScene=this.engine.scene,!this.optsGravity)){let e=this.engine.scene?.physics?.gravity??[0,-9.81,0];this.world.gravity={x:e[0]??0,y:e[1]??0,z:e[2]??0}}this.syncBodies(),this.world.timestep=e,this.world.step(this.events);for(let[e,t]of this.entries){let n=t.body.translation();if(!t.body.isFixed()){let[t,r,i]=CS(e),a=[n.x-t,n.y-r,n.z-i];e._interpPrev=e._interpCurr??a,e._interpCurr=a;let o=e.position;o[0]=a[0],o[1]=a[1],o[2]=a[2]}if(e instanceof Zp){if(!e.fixedRotation){let n=t.body.rotation();_S.setFromQuaternion(gS.set(n.x,n.y,n.z,n.w),`XYZ`);let r=e.rotation;r[0]=_S.x/pS,r[1]=_S.y/pS,r[2]=_S.z/pS}let n=t.body.linvel(),r=e.linearVelocity;r[0]=n.x,r[1]=n.y,r[2]=n.z,t.lastV[0]=n.x,t.lastV[1]=n.y,t.lastV[2]=n.z}let r=xS(e);t.last[0]=r[0],t.last[1]=r[1],t.last[2]=r[2]}this.events.drainCollisionEvents((e,t,n)=>{let r=this.byColliderHandle.get(e),i=this.byColliderHandle.get(t);if(!r||!i)return;let a=n?`triggerEnter`:`triggerExit`;try{r.emit(a,i),i.emit(a,r)}catch(e){console.error(`incanto: error in a '${a}' handler (${r.name} ↔ ${i.name}):`,e)}})}moveAndSlide(e){let t=this.ensureEntry(e),n=e.velocity[1]??0;e.snapToGround&&n<=0?this.kcc.enableSnapToGround(.1):this.kcc.disableSnapToGround(),this.kcc.setMaxSlopeClimbAngle(e.slopeLimitDeg*pS);let r={x:(e.velocity[0]??0)*this.lastDt,y:n*this.lastDt,z:(e.velocity[2]??0)*this.lastDt};this.kcc.computeColliderMovement(t.collider,r,this.R.QueryFilterFlags.EXCLUDE_SENSORS);let i=this.kcc.computedMovement(),a=t.body.translation();t.body.setNextKinematicTranslation({x:a.x+i.x,y:a.y+i.y,z:a.z+i.z}),e._grounded=this.kcc.computedGrounded()}debugLines(){return this.debugDraw?this.world.debugRender().vertices:null}dispose(){this.disconnect(),this.unregisterDebug(),this.world.free()}lastStructure=-1;lastRoot=null;jointSet=new Set;joints=new Map;bodySet=new Set;syncBodies(){let e=this.engine.scene;if(!e)return;let t=e.tree._structureVersion,n=t!==this.lastStructure||e.root!==this.lastRoot;n&&(this.lastStructure=t,this.lastRoot=e.root,this.bodySet.clear(),yS(e.root,this.bodySet)),n&&(this.jointSet.clear(),vS(e.root,this.jointSet));let r=this.bodySet;for(let e of r){if(e.collider.shape===void 0){let t=this.entries.get(e);t&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null),this.warnedNoCollider.has(e)||(this.warnedNoCollider.add(e),console.warn(`[incanto] '${e.name}' has no collider — physics skips it.`));continue}let t=this.entries.get(e);t&&e._colliderChanged&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null),this.ensureEntry(e)}if(this.syncJoints(n),n)for(let[e,t]of this.entries)r.has(e)||(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null)}ensureEntry(e){let t=this.entries.get(e),n=this.R;if(!t){let r;r=e instanceof Zp?n.RigidBodyDesc.dynamic():e instanceof Qp||e instanceof Xp?n.RigidBodyDesc.kinematicPositionBased():n.RigidBodyDesc.fixed();let[i,a,o]=xS(e);r.setTranslation(i,a,o),gS.setFromEuler(_S.set((e.rotation[0]??0)*pS,(e.rotation[1]??0)*pS,(e.rotation[2]??0)*pS,`XYZ`)),r.setRotation({x:gS.x,y:gS.y,z:gS.z,w:gS.w}),e instanceof Zp&&(r.setGravityScale(e.gravityScale),r.setLinvel(e.linearVelocity[0]??0,e.linearVelocity[1]??0,e.linearVelocity[2]??0),e.fixedRotation&&r.lockRotations());let s=this.world.createRigidBody(r),c=wS(n,e);c.setActiveEvents(n.ActiveEvents.COLLISION_EVENTS),c.setActiveCollisionTypes(n.ActiveCollisionTypes.ALL),e instanceof Xp&&c.setSensor(!0),e instanceof Zp&&c.setMass(e.mass).setFriction(e.friction).setRestitution(e.restitution);let l=this.world.createCollider(c,s);return t={body:s,collider:l,last:[i,a,o],lastV:[0,0,0]},this.entries.set(e,t),this.byColliderHandle.set(l.handle,e),e._colliderChanged=!1,e._physics=this,e instanceof Zp&&(e._physics3d=this),t}let r=xS(e);if((r[0]!==t.last[0]||r[1]!==t.last[1]||r[2]!==t.last[2])&&(t.body.setTranslation({x:r[0],y:r[1],z:r[2]},!0),t.last[0]=r[0],t.last[1]=r[1],t.last[2]=r[2],e._interpPrev=e._interpCurr=null),e instanceof Zp){let n=[e.linearVelocity[0]??0,e.linearVelocity[1]??0,e.linearVelocity[2]??0];(n[0]!==t.lastV[0]||n[1]!==t.lastV[1]||n[2]!==t.lastV[2])&&(t.body.setLinvel({x:n[0],y:n[1],z:n[2]},!0),t.lastV=n),e.gravityScale!==t.body.gravityScale()&&t.body.setGravityScale(e.gravityScale,!0)}return t}applyImpulse(e,t){this.entries.get(e)?.body.applyImpulse({x:t[0],y:t[1],z:t[2]},!0)}massOf(e){return this.entries.get(e)?.body.mass()??1}velocityOf(e){let t=this.entries.get(e)?.body.linvel();return t?[t.x,t.y,t.z]:[0,0,0]}syncJoints(e){let t=this.R;if(e)for(let[e,t]of this.joints)this.jointSet.has(e)||(this.world.removeImpulseJoint(t,!0),this.joints.delete(e));for(let e of this.jointSet){if(this.joints.has(e))continue;let{a:n,b:r}=e._resolveBodies(),i=this.entries.get(n),a=this.entries.get(r);if(!i||!a)continue;let o={x:e.anchor[0]??0,y:e.anchor[1]??0,z:e.anchor[2]??0},s={x:e.targetAnchor[0]??0,y:e.targetAnchor[1]??0,z:e.targetAnchor[2]??0},c=e.length;if(e.length===0&&(e.type===`rope`||e.type===`spring`)){let e=i.body.translation(),t=a.body.translation();c=Math.hypot(t.x-e.x,t.y-e.y,t.z-e.z)}let l={x:0,y:0,z:0,w:1},u;u=e.type===`fixed`?t.JointData.fixed(o,l,s,l):e.type===`rope`?t.JointData.rope(c,o,s):e.type===`spring`?t.JointData.spring(c,e.stiffness,e.damping,o,s):t.JointData.spherical(o,s),this.joints.set(e,this.world.createImpulseJoint(u,i.body,a.body,!0))}}castRay(e,t,n,r,i){let a=new this.R.Ray({x:e[0],y:e[1],z:e[2]},{x:t[0],y:t[1],z:t[2]}),o=r?this.entries.get(r)?.collider:void 0,s=i?.staticOnly?this.R.QueryFilterFlags.EXCLUDE_DYNAMIC|this.R.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,c=this.world.castRayAndGetNormal(a,n,!0,s,void 0,o,void 0,e=>!e.isSensor());return c?{distance:c.timeOfImpact,normal:[c.normal.x,c.normal.y,c.normal.z],node:this.byColliderHandle.get(c.collider.handle)??null}:null}castSphere(e,t,n,r,i,a){let o=this.R,s=i?this.entries.get(i):void 0,c=a?.staticOnly?o.QueryFilterFlags.EXCLUDE_DYNAMIC|o.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,l=this.world.castShape({x:e[0],y:e[1],z:e[2]},{x:0,y:0,z:0,w:1},{x:t[0],y:t[1],z:t[2]},new o.Ball(n),0,r,!0,c,void 0,s?.collider,s?.body,e=>!e.isSensor());return l?{distance:l.time_of_impact,node:this.byColliderHandle.get(l.collider.handle)??null}:null}},gS=new V,_S=new Pi;function vS(e,t){e instanceof Ax&&t.add(e);for(let n of e.children)vS(n,t)}function yS(e,t){e instanceof Jp&&t.add(e);for(let n of e.children)yS(n,t)}var bS=[0,0,0];function xS(e){let t=0,n=0,r=0;for(let i=e;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return bS[0]=t,bS[1]=n,bS[2]=r,bS}var SS=[0,0,0];function CS(e){let t=0,n=0,r=0;for(let i=e.parent;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return SS[0]=t,SS[1]=n,SS[2]=r,SS}function wS(e,t){let n=t.collider;if(Kp(n,t.name),n.shape===`heightfield`)return TS(e,t);let r=ES(e,n,t.name),i=n.offset;return Array.isArray(i)&&r.setTranslation(i[0]??0,i[1]??0,i[2]??0),r}function TS(e,t){let n=t.children.find(e=>e instanceof lS);if(!n)throw new y(`BAD_FORMAT`,`Collider on '${t.name}': heightfield needs a Terrain3D CHILD of this body — add { "type": "Terrain3D" } under the StaticBody3D; the collider reads its height grid.`,{prop:`collider`});let r=n._heightmap(),i=r.segsZ,a=r.segsX,o=new Float32Array((i+1)*(a+1));for(let e=0;e<=a;e++)for(let t=0;t<=i;t++)o[e*(i+1)+t]=r.heights[t*(a+1)+e];let s=e.ColliderDesc.heightfield(i,a,o,{x:r.width,y:1,z:r.depth}),c=Array.isArray(t.collider.offset)?t.collider.offset:[];return s.setTranslation((n.position[0]??0)+(c[0]??0),(n.position[1]??0)+(c[1]??0),(n.position[2]??0)+(c[2]??0)),s}function ES(e,t,n){let r=t.shape;if(r===`box`){let r=t.size;if(!Array.isArray(r)||r.length!==3||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${n}': box needs "size": [x, y, z].`);return e.ColliderDesc.cuboid(r[0]/2,r[1]/2,r[2]/2)}if(r===`sphere`){if(typeof t.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': sphere needs "radius".`);return e.ColliderDesc.ball(t.radius)}if(r===`capsule`){if(typeof t.radius!=`number`||typeof t.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': capsule needs "radius" and "height".`);return e.ColliderDesc.capsule(t.height/2,t.radius)}if(r===`trimesh`){let r=t.vertices,i=t.indices;if(!Array.isArray(r)||!Array.isArray(i))throw new y(`BAD_FORMAT`,`Collider on '${n}': trimesh needs "vertices" (flat xyz) and "indices" (triangles).`);return e.ColliderDesc.trimesh(new Float32Array(r),new Uint32Array(i))}throw new y(`BAD_FORMAT`,`Collider on '${n}': "shape" must be 'box', 'sphere', 'capsule', 'trimesh', or 'heightfield', got ${JSON.stringify(r)}.`)}var DS=new Ws(1,1),OS=null;function kS(){if(OS)return OS;if(typeof document>`u`)return null;let e=document.createElement(`canvas`);e.width=64,e.height=64;let t=e.getContext(`2d`);if(!t)return null;let n=t.createRadialGradient(32,32,0,32,32,31);return n.addColorStop(0,`rgba(0,0,0,0.55)`),n.addColorStop(.55,`rgba(0,0,0,0.34)`),n.addColorStop(1,`rgba(0,0,0,0)`),t.fillStyle=n,t.fillRect(0,0,64,64),OS=new Ps(e),OS}var AS=new H(0,0,1),jS=new H,MS=new H,NS=new V,PS=new V,FS=new H,IS=.5,LS=class extends qp{static typeName=`Sprite3D`;static props={texture:{default:``},size:{default:[1,1]},billboard:{default:`y`,options:[`y`,`full`,`none`]},anchor:{default:[.5,0]},tint:{default:`#ffffff`},opacity:{default:1},flipX:{default:!1},pixelArt:{default:!0},alphaTest:{default:.5},castShadow:{default:!1},shadowMode:{default:`silhouette`,options:[`silhouette`,`blob`]}};texture=``;size=[1,1];billboard=`y`;anchor=[.5,0];tint=`#ffffff`;opacity=1;flipX=!1;pixelArt=!0;alphaTest=.5;castShadow=!1;shadowMode=`silhouette`;quadMesh=null;textureRef=``;loadedTexture=null;shadowMesh=null;blobMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(DS,new yo({transparent:!1,depthWrite:!0,side:2})),this._ensureObject3D().add(this.quadMesh)),this.quadMesh}resolveTexture(){if(!this.texture)return null;if(this.textureRef!==this.texture&&(this.loadedTexture?.dispose(),this.loadedTexture=null,this.textureRef=this.texture,typeof document<`u`)){let e=new Ic().load(this.texture);e.colorSpace=dr;let t=this.pixelArt?zt:Ht;e.magFilter=t,e.minFilter=t,this.loadedTexture=e}return this.loadedTexture}_syncObject3D(e=1){super._syncObject3D(e);let t=this._quad(),n=t.material,r=this.size[0]??1,i=this.size[1]??1;t.scale.set(this.flipX?-r:r,i,1);let a=this.anchor[0]??.5,o=this.anchor[1]??0;t.position.set((.5-a)*r,(.5-o)*i,0);let s=this.resolveTexture();n.map!==s&&(n.map=s,n.needsUpdate=!0),t.visible=s!==null,n.color.set(this.tint),n.opacity=this.opacity,n.transparent=this.opacity<1,n.alphaTest=this.alphaTest,t.renderOrder=this.renderOrder;let c=this.castShadow&&s!==null;if(t.castShadow=!1,c&&this.shadowMode===`silhouette`){let e=this._shadowCaster();e.visible=!0,e.castShadow=!0,e.scale.set(this.flipX?-r:r,i,1),e.position.set((.5-a)*r,(.5-o)*i,0);let t=e.material;t.map!==s&&(t.map=s,t.needsUpdate=!0);let n=e.customDepthMaterial;n.map!==s&&(n.map=s,n.needsUpdate=!0),t.alphaTest=this.alphaTest,n.alphaTest=this.alphaTest}else this.shadowMesh&&(this.shadowMesh.visible=!1,this.shadowMesh.castShadow=!1);if(c&&this.shadowMode===`blob`){let e=this._blob();e.visible=!0,e.scale.set(r*.52,r*.52,1)}else this.blobMesh&&(this.blobMesh.visible=!1)}_shadowCaster(){return this.shadowMesh||(this.shadowMesh=new jo(DS,new yo({colorWrite:!1,depthWrite:!1,side:2})),this.shadowMesh.customDepthMaterial=new ic({depthPacking:ur,side:2}),this._ensureObject3D().add(this.shadowMesh)),this.shadowMesh}_blob(){return this.blobMesh||(this.blobMesh=new jo(DS,new yo({map:kS(),color:0,transparent:!0,depthWrite:!1})),this.blobMesh.rotation.x=-Math.PI/2,this.blobMesh.position.y=.02,this.blobMesh.renderOrder=-1,this._ensureObject3D().add(this.blobMesh)),this.blobMesh}_onRender3D(e){this.billboard===`y`?(e.camera.getWorldDirection(MS),MS.y=0,MS.lengthSq()>=1e-6&&this._faceDir(this._quad(),MS.negate())):this.billboard===`full`&&this._faceToward(this._quad(),e.camera.position);let t=this.shadowMesh;t?.castShadow&&e.sunDir&&(this._faceDir(t,e.sunDir),t.parent?.getWorldQuaternion(PS),FS.copy(e.sunDir).applyQuaternion(PS.invert()),t.position.addScaledVector(FS,IS))}_faceToward(e,t){e.getWorldPosition(jS),MS.copy(t).sub(jS),this.billboard===`y`&&(MS.y=0),!(MS.lengthSq()<1e-12)&&(MS.normalize(),NS.setFromUnitVectors(AS,MS),e.parent?.getWorldQuaternion(PS),e.quaternion.copy(PS.invert()).multiply(NS))}_faceDir(e,t){MS.copy(t),this.billboard===`y`&&(MS.y=0),!(MS.lengthSq()<1e-12)&&(MS.normalize(),NS.setFromUnitVectors(AS,MS),e.parent?.getWorldQuaternion(PS),e.quaternion.copy(PS.invert()).multiply(NS))}free(){this.loadedTexture?.dispose(),this.loadedTexture=null,this.shadowMesh&&(this.shadowMesh.material.dispose(),this.shadowMesh.customDepthMaterial?.dispose()),this.blobMesh&&this.blobMesh.material.dispose(),super.free()}},RS=class extends LS{static typeName=`AnimatedSprite3D`;static signals=[`animationFinished`];static props={sheet:{default:``},frameWidth:{default:0},frameHeight:{default:0},animations:{default:{}},autoplay:{default:``}};sheet=``;frameWidth=0;frameHeight=0;animations={};autoplay=``;playing=!1;currentFrame=0;currentAnimation=``;frameList=[];frameIndex=0;frameTime=0;sheetTexture=null;loadedSheetRef=``;play(e){let t=this.animations[e];if(!t)throw new y(`UNKNOWN_ANIMATION`,`No animation '${e}' on '${this.name}'. Available: [${Object.keys(this.animations).join(`, `)}].`);this.currentAnimation=e,this.frameList=zS(t.frames,e),this.frameIndex=0,this.currentFrame=this.frameList[0]??0,this.frameTime=0,this.playing=!0}stop(){this.playing=!1}onReady(){this.autoplay&&this.play(this.autoplay)}update(e){if(!this.playing||this.currentAnimation===``)return;let t=this.animations[this.currentAnimation];if(!t||!Number.isFinite(t.fps)||t.fps<=0)return;let n=1/t.fps;for(this.frameTime+=e;this.frameTime>=n;)if(this.frameTime-=n,this.frameIndex+=1,this.frameIndex>=this.frameList.length)if(t.loop)this.frameIndex=0;else{this.frameIndex=this.frameList.length-1,this.playing=!1,this.emit(`animationFinished`,this.currentAnimation);break}this.currentFrame=this.frameList[this.frameIndex]??0}resolveTexture(){if(!this.sheet||this.frameWidth<=0||this.frameHeight<=0)return null;if(this.loadedSheetRef!==this.sheet&&(this.sheetTexture?.dispose(),this.sheetTexture=null,this.loadedSheetRef=this.sheet,typeof document<`u`)){let e=new Ic().load(this.sheet);e.colorSpace=dr;let t=this.pixelArt?zt:Ht;e.magFilter=t,e.minFilter=t,this.sheetTexture=e}let e=this.sheetTexture;if(!e)return null;let t=e.image;if(!t?.width||!t.height)return e;let n=Math.max(1,Math.floor(t.width/this.frameWidth)),r=this.currentFrame%n,i=Math.floor(this.currentFrame/n);return e.repeat.set(this.frameWidth/t.width,this.frameHeight/t.height),e.offset.set(r*this.frameWidth/t.width,1-(i+1)*this.frameHeight/t.height),e}free(){this.sheetTexture?.dispose(),this.sheetTexture=null,super.free()}};function zS(e,t){if(!Array.isArray(e)||e.length===0)throw new y(`BAD_FORMAT`,`Animation '${t}': "frames" must be a non-empty array.`);if(e.length===2){let[t,n]=e;if(n>=t){let e=[];for(let r=t;r<=n;r++)e.push(r);return e}}return[...e]}var BS=new V,VS=new V,HS=new H,US=new H(0,0,1),WS=[`screen`,`y`,`none`],GS=class extends qp{static typeName=`Billboard3D`;static props={mode:{default:`screen`,options:WS}};mode=`screen`;_lastDesired=null;static validateJson(e){let t=e;if(!WS.includes(t.mode))throw new y(`BAD_FORMAT`,`Billboard3D '${e.name}' mode must be one of [${WS.join(`, `)}], got '${t.mode}'.`,{prop:`mode`,validOptions:WS})}_onRender3D(e){if(this.mode===`none`)return;let t=this._ensureObject3D();if(this.mode===`screen`)e.camera.getWorldQuaternion(VS);else if(e.camera.getWorldDirection(HS),HS.y=0,HS.lengthSq()>=1e-6)VS.setFromUnitVectors(US,HS.negate().normalize());else if(this._lastDesired)VS.copy(this._lastDesired);else return;this._lastDesired||=new V,this._lastDesired.copy(VS),t.parent?.getWorldQuaternion(BS),t.parent?t.quaternion.copy(BS.invert()).multiply(VS):t.quaternion.copy(VS)}},KS=class extends qp{static typeName=`BoneAttachment3D`;static props={target:{default:``},bone:{default:``}};target=``;bone=``;boneObj=null;lookedUpFor=``;get attachedBone(){return this.boneObj}_onRender3D(e){if(this.target===``||this.bone===``)return;let t=`${this.target} ${this.bone}`;if(this.lookedUpFor!==t||this.boneObj===null||!this.boneObj.parent){this.lookedUpFor=t,this.boneObj=null;let e=this.getNodeOrNull(this.target);e&&typeof e.findBone==`function`&&(this.boneObj=e.findBone(this.bone))}let n=this.boneObj;if(!n)return;let r=this._ensureObject3D(),i=r.parent;i&&(n.updateWorldMatrix(!0,!1),i.updateWorldMatrix(!0,!1),r.matrixAutoUpdate=!1,n.matrixWorld.decompose(YS,XS,ZS),JS.compose(YS,XS,QS),r.updateMatrix(),qS.copy(r.matrix),r.matrix.copy(i.matrixWorld).invert().multiply(JS).multiply(qS))}free(){this.boneObj=null,super.free()}},qS=new W,JS=new W,YS=new H,XS=new V,ZS=new H,QS=new H(1,1,1),$S=class extends qp{static typeName=`BoneLookAt3D`;static props={target:{default:``},bone:{default:`Head`},lookAt:{default:``},maxAngleDeg:{default:75},weight:{default:.85},forwardAxis:{default:`+z`,options:[`+x`,`-x`,`+y`,`-y`,`+z`,`-z`]}};target=``;bone=`Head`;lookAt=``;maxAngleDeg=75;weight=.85;forwardAxis=`+z`;boneObj=null;lookedUpFor=``;engage=0;get attachedBone(){return this.boneObj}_onRender3D(e){if(this.target===``||this.bone===``)return;let t=`${this.target} ${this.bone}`;if(this.lookedUpFor!==t||this.boneObj===null||!this.boneObj.parent){this.lookedUpFor=t,this.boneObj=null;let e=this.getNodeOrNull(this.target);e&&typeof e.findBone==`function`&&(this.boneObj=e.findBone(this.bone))}let n=this.boneObj;if(!n?.parent)return;let r=this.lookAt===``?null:this.getNodeOrNull(this.lookAt),i=!1;if(r&&Array.isArray(r.position)&&(n.updateWorldMatrix(!0,!1),n.getWorldPosition(aC),oC.set(r.position[0]??0,r.position[1]??0,r.position[2]??0),sC.copy(oC).sub(aC),sC.lengthSq()>1e-6&&(sC.normalize(),cC.copy(tC[this.forwardAxis]??rC),lC.copy(cC).applyQuaternion(n.getWorldQuaternion(mC)),lC.angleTo(sC)<this.maxAngleDeg*Math.PI/180))){i=!0,uC.lookAt(aC,oC,nC),dC.setFromRotationMatrix(uC),fC.setFromUnitVectors(cC,iC),dC.multiply(fC),n.parent.getWorldQuaternion(pC).invert(),dC.premultiply(pC);let e=this.weight*this.engage;n.quaternion.slerp(dC,e)}this.engage+=(+!!i-this.engage)*eC}},eC=.18,tC={"+x":new H(1,0,0),"-x":new H(-1,0,0),"+y":new H(0,1,0),"-y":new H(0,-1,0),"+z":new H(0,0,1),"-z":new H(0,0,-1)},nC=new H(0,1,0),rC=new H(0,0,1),iC=new H(0,0,-1),aC=new H,oC=new H,sC=new H,cC=new H,lC=new H,uC=new W,dC=new V,fC=new V,pC=new V,mC=new V,hC=class extends qp{static typeName=`Camera3D`;static props={fov:{default:60},near:{default:.1},far:{default:1e3},current:{default:!1}};fov=60;near=.1;far=1e3;current=!1;_createObject3D(){return new Yc(this.fov,1,this.near,this.far)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();(e.fov!==this.fov||e.near!==this.near||e.far!==this.far)&&(e.fov=this.fov,e.near=this.near,e.far=this.far,e.updateProjectionMatrix())}},gC=8,_C=.2,vC=.15,yC=1.2,bC=.08,xC=2.5,SC=-20,CC=.002,wC=180/Math.PI,TC=.3,EC=.4,DC=.3,OC=.25,kC=new Pi,AC=new V,jC=new W,MC=new H,NC=new H,PC=new H(0,1,0),FC=class extends qp{static typeName=`CharacterController3D`;static signals=[`movementStateChanged`];static props={view:{default:`free`,options:[`free`,`firstPerson`,`quarter`,`side`]},camDistance:{default:4},eyeHeight:{default:.64},maxSpeed:{default:2.5},sprintMultiplier:{default:2},jumpVelocity:{default:4},sprintJumpMultiplier:{default:1.2},floatHeight:{default:.01},mouseLook:{default:!0},zoomMin:{default:0},zoomMax:{default:0},pitchMin:{default:-1.3},pitchMax:{default:1.5},cameraCollision:{default:!0},turnSpeed:{default:100},camLerp:{default:25},moveAction:{default:`move`},jumpAction:{default:`jump`},sprintAction:{default:`sprint`},skinPath:{default:`../Skin`},skinYawOffset:{default:0},animations:{default:{}}};view=`free`;camDistance=4;eyeHeight=.64;maxSpeed=2.5;sprintMultiplier=2;jumpVelocity=4;sprintJumpMultiplier=1.2;floatHeight=.01;mouseLook=!0;zoomMin=0;zoomMax=0;pitchMin=-1.3;pitchMax=1.5;cameraCollision=!0;turnSpeed=100;camLerp=25;moveAction=`move`;jumpAction=`jump`;sprintAction=`sprint`;skinPath=`../Skin`;skinYawOffset=0;animations={};yaw=0;pitch=0;state=`idle`;grounded=!1;get body(){let e=this.parent;if(!(e instanceof Zp))throw new y(`TREE_VIOLATION`,`CharacterController3D '${this.name}' must be a child of a RigidBody3D (parent is '${e?.name??`none`}').`);return e}onEnterTree(){if(this.body,this.skinPath!==``){let e=this.getNodeOrNull(this.skinPath);e&&(e.rotation=[e.rotation[0]??0,180+this.skinYawOffset,e.rotation[2]??0])}}fixedUpdate(e){let t=this.body,n=t._physics3d,r=this.tree?.engine?.input;if(!n||!r)return;let i=t.collider.radius??.32,a=(t.collider.height??1)/2,o=LC(t),s=n.velocityOf(t),c=n.massOf(t),l=i+this.floatHeight,u=i+2,d=o[1]-a,f=null;for(let[e,r]of[[0,0],[i,0],[-i,0],[0,i],[0,-i]]){let i=n.castRay([o[0]+e,d,o[2]+r],[0,-1,0],u,t);if(i){let t=i.distance;if(f=f===null?t:Math.min(f,t),e===0&&r===0)break}}this.grounded=f!==null&&f<l*2;let p=0,m=0,h=!1;try{let e=r.getVector(this.moveAction);h=e.x!==0||e.y!==0;let t=this.view===`free`||this.view===`firstPerson`?this.yaw:0,n=this.view===`side`?[e.x,0,0]:Dx(e.x,-e.y,t),i=Math.hypot(n[0],n[2])||1;p=n[0]/i,m=n[2]/i}catch{}let g=RC(r,this.sprintAction),_=Ox(h,g),v=1+(this.sprintMultiplier-1)*_,y=h?this.maxSpeed*v:0,b=this.grounded?1:_C,x=(p*y-s[0])/gC*b,S=(m*y-s[2])/gC*b;if(t.applyImpulse([x*c,0,S*c]),!h&&this.grounded&&t.applyImpulse([-s[0]*vC*c,0,-s[2]*vC*c]),f!==null&&f<l*2){let e=yC*(l-f)-s[1]*bC;t.applyImpulse([0,e*c,0])}if(this.grounded&&RC(r,this.jumpAction)){let e=this.jumpVelocity*(1+(this.sprintJumpMultiplier-1)*_);t.linearVelocity=[s[0],e,s[2]],this.grounded=!1}s[1]<SC?t.gravityScale=0:s[1]<0&&!this.grounded?t.gravityScale=xC:t.gravityScale=1,this.view===`side`&&Math.abs(o[2])>.01&&(t.position=[t.position[0]??0,t.position[1]??0,0]);let C=kx(this.grounded,h?_:0);if(C!==this.state){this.state=C;let e=this.animations[C];if(e&&this.skinPath!==``){let t=this.getNodeOrNull(this.skinPath);t&&`animation`in t&&(t.animation=e)}this.emit(`movementStateChanged`,C)}if(h&&this.skinPath!==``){let t=this.getNodeOrNull(this.skinPath);if(t){let n=Math.atan2(p,m)*wC+this.skinYawOffset,r=t.rotation[1]??0,i=(n-r+540)%360-180,a=this.turnSpeed*e*wC;Math.abs(i)>a&&(i=Math.sign(i)*a),t.rotation=[t.rotation[0]??0,r+i,t.rotation[2]??0]}}}update(e){let t=this.tree?.engine?.input;if(!t)return;if(this.mouseLook){let e=t.pointerDelta();this.yaw-=e.x*CC,this.pitch=IC(this.pitch+e.y*CC,-this.pitchMax,-this.pitchMin);let n=t.wheelDelta();n!==0&&this.zoomMax>this.zoomMin&&(this.camDistance=IC(this.camDistance+n*CC,this.zoomMin,this.zoomMax))}let n=this.findCamera();if(!n)return;let r=this.parent instanceof Zp?this.parent:null;if(!r)return;let i=LC(r),a=this.view===`free`?11:1e3,o=1-Math.exp(-a*e),s=this.pivot??[i[0],i[1],i[2]];this.pivot=s,s[0]+=(i[0]-s[0])*o,s[1]+=(i[1]-s[1])*o,s[2]+=(i[2]-s[2])*o;let c=wx(this.view,s,this.eyeHeight,this.yaw,this.pitch,this.camDistance),l=[s[0],s[1]+this.eyeHeight,s[2]],u=[c.position[0],c.position[1],c.position[2]];if(this.cameraCollision&&this.view!==`firstPerson`){let e=r._physics3d;e&&(u=Tx(l,u,(t,n,i)=>e.castSphere(t,n,OC,i,r,{staticOnly:!0})?.distance??null,TC,EC),u=Ex(u,(t,n)=>e.castRay(t,[0,-1,0],n,r,{staticOnly:!0})?.distance??null,DC))}let d=this.view===`firstPerson`?1e3:this.camLerp,f=1-Math.exp(-d*e),p=n.position;n.position=[(p[0]??0)+(u[0]-(p[0]??0))*f,(p[1]??0)+(u[1]-(p[1]??0))*f,(p[2]??0)+(u[2]-(p[2]??0))*f],this.view===`free`?(MC.set(n.position[0]??0,n.position[1]??0,n.position[2]??0),NC.set(l[0],l[1],l[2]),jC.lookAt(MC,NC,PC),AC.setFromRotationMatrix(jC),kC.setFromQuaternion(AC,`XYZ`)):(kC.set(c.rotation[0],c.rotation[1],c.rotation[2],`YXZ`),AC.setFromEuler(kC),kC.setFromQuaternion(AC,`XYZ`)),n.rotation=[kC.x*wC,kC.y*wC,kC.z*wC]}pivot=null;cameraCache=null;findCamera(){if(this.cameraCache?.tree===this.tree&&this.cameraCache.current)return this.cameraCache;this.cameraCache=null;let e=this.tree?.root;if(!e)return null;let t=e=>{if(!this.cameraCache){if(e instanceof hC&&e.current){this.cameraCache=e;return}for(let n of e.children)t(n)}};return t(e),this.cameraCache}};function IC(e,t,n){return Math.min(n,Math.max(t,e))}function LC(e){let t=0,n=0,r=0;for(let i=e;i&&i instanceof qp;i=i.parent)t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0;return[t,n,r]}function RC(e,t){try{return e.isPressed(t)}catch{return!1}}var zC=.15,BC=.7,VC=.5,HC=.7,UC=.5;function WC(e,t,n=3){let r=0,i=1,a=1,o=.65;for(let s=0;s<n;s++){let n=e*a,s=t*a,c=Math.sin(n*.1+s*.2)*.5+.5,l=Math.cos(n*.3+s*.1)*.5+.5,u=Math.sin((n+s)*.15)*.5+.5,d=Math.cos(n*n*.01+s*.2)*.5+.5,f=c*l*.7+u*d*.3;r+=f*i,i*=o,a*=2}return r/((1-o**n)/(1-o))}function GC(e,t){let n=WC(e*zC,t*zC,4),r=WC(e*zC*.2,t*zC*.2,2);return n>VC-BC*.5-r*UC}var KC=.9;function qC(e,t,n){let r=(Math.imul(e,2246822507)^Math.imul(t,3266489909)^Math.imul(n+1,668265263))>>>0;return r=Math.imul(r^r>>>15,739982445)>>>0,r=Math.imul(r^r>>>12,695872825)>>>0,r^=r>>>15,(r>>>0)/4294967296}function JC(e,t,n=KC){let r=Math.floor(e/n),i=Math.floor(t/n),a=1/0,o=r,s=i;for(let c=-1;c<=1;c++)for(let l=-1;l<=1;l++){let u=r+l,d=i+c,f=(u+qC(u,d,0))*n,p=(d+qC(u,d,1))*n,m=(e-f)*(e-f)+(t-p)*(t-p);m<a&&(a=m,o=u,s=d)}return{id:Math.imul(o,2654435761)^Math.imul(s,2246822519)|0,hue:qC(o,s,2)*2-1,leanDir:qC(o,s,3)*Math.PI*2,lean:qC(o,s,4)}}function YC(e,t,n,r){let i=e*r,a=t*r,o=Math.floor(i),s=Math.floor(a),c=i-o,l=a-s,u=c*c*(3-2*c),d=l*l*(3-2*l),f=qC(o,s,n),p=qC(o+1,s,n),m=qC(o,s+1,n),h=qC(o+1,s+1,n),g=f+(p-f)*u;return g+(m+(h-m)*u-g)*d}var XC=[.55,1.7],ZC=.17,QC=.23,$C=.28;function ew(e,t,n){let r=YC(e,t,n^6877377|0,ZC),i=r*r*(3-2*r);return XC[0]+(XC[1]-XC[0])*i}function tw(e,t,n){return YC(e,t,n^3001105|0,QC)}function nw(e,t,n){let r=YC(e,t,n^7840757|0,$C)*.72+YC(e,t,n^1688295|0,$C*3.1)*.28,i=Math.min(1,Math.max(0,(r-.18)/.64));return i*i*(3-2*i)}function rw(e){let{seed:t,areaX:n,areaZ:r,count:i,density:a}=e,o=new b(t),s=n/2,c=r/2,l=[],u=Math.floor(i*HC);for(let e=0;e<u&&l.length<i;e++){let e=o.range(-s,s),t=o.range(-c,c),n=o.next()<.3,r=GC(e,t);if(!n&&!r&&o.next()>.15)continue;let i=o.next()*Math.PI*2,a=.5+o.next()*.7,u=r?a*(1+o.next()*.2):a*(.9+o.next()*.2);l.push({x:e,z:t,rotY:i,scale:u})}let d=Math.min(3,Math.max(1,a*10)),f=Math.ceil(Math.sqrt(i*d)),p=n/f,m=r/f,h=Math.floor((i-l.length)*.8),g=0;for(let e=0;e<f&&l.length<i;e++)for(let t=0;t<f&&l.length<i;t++){let i=t/f*n-s+p/2,a=e/f*r-c+m/2,u=i+(o.next()-.5)*p*1.5,d=a+(o.next()-.5)*m*1.5;if(u<-s||u>s||d<-c||d>c)continue;let _=GC(u,d);if(g<h){if(!_&&o.next()>.05)continue}else if(_){if(o.next()>.2)continue}else if(o.next()>.4)continue;if(o.next()<.2)continue;let v=o.next()*Math.PI*2,y=_?.5:.3;l.push({x:u,z:d,rotY:v,scale:.5+o.next()*y}),g++}for(;l.length<i;)l.push({x:o.range(-s,s),z:o.range(-c,c),rotY:o.next()*Math.PI*2,scale:.4+o.next()*.6});return l.sort((e,t)=>t.z-e.z),l}var iw=[`daisy`,`cosmos`,`bellflower`],aw={daisy:{petals:8,blooms:3,leaves:3,petalLength:.1,petalWidth:.052,cupDeg:16,nodDeg:14,centerRadius:.024,centerColor:`#e0a72e`},cosmos:{petals:8,blooms:2,leaves:2,petalLength:.12,petalWidth:.064,cupDeg:26,nodDeg:18,centerRadius:.023,centerColor:`#d2941f`},bellflower:{petals:5,blooms:3,leaves:2,petalLength:.088,petalWidth:.058,cupDeg:46,nodDeg:52,centerRadius:.015,centerColor:`#cfe06a`}},ow=[1,.78,.62],sw=[0,.07,.11],cw=[.6,2.7,4.9],lw=.07,uw=.011,dw=.17,fw=.05,pw=[.12,.2,.28],mw=new G(`#3e6a26`),hw=new G(`#548331`);function gw(e){let t=aw[e],n=new _w(!0),r=new _w(!1),i=new G(t.centerColor);for(let e=0;e<t.blooms;e++){let a=ow[e],o=cw[e],s=sw[e]*Math.cos(o),c=sw[e]*Math.sin(o),l=lw*Math.cos(o),u=lw*Math.sin(o),d=new H(s,0,c),f=new H(s+l,a,c+u),p=new H(s+l*.25,a*.55,c+u*.25);n.addStem(d,p,f,uw,mw);let m=t.nodDeg*Math.PI/180,h=new H(Math.sin(m)*Math.cos(o),Math.cos(m),Math.sin(m)*Math.sin(o)),g=new H(-Math.sin(o),0,Math.cos(o)),_=new H().crossVectors(h,g).normalize(),v=f.clone().addScaledVector(h,.012),y=t.cupDeg*Math.PI/180,b=e*.45;for(let e=0;e<t.petals;e++){let n=e/t.petals*Math.PI*2+b,i=g.clone().multiplyScalar(Math.cos(n)).addScaledVector(_,Math.sin(n)).normalize();r.addPetal(v,i,h,t,y)}n.addDisc(v.clone().addScaledVector(h,.004),g,_,t.centerRadius,i)}for(let e=0;e<t.leaves;e++){let t=pw[e%pw.length],r=1.1+e*2.3;n.addLeaf(new H(0,t,0),r,hw)}return{structure:n.build(),petals:r.build()}}var _w=class{positions=[];colors;indices=[];constructor(e){this.colors=e?[]:null}vertex(e,t){let n=this.positions.length/3;return this.positions.push(e.x,e.y,e.z),this.colors&&t&&this.colors.push(t.r,t.g,t.b),n}addStem(e,t,n,r,i){for(let a of[0,Math.PI/2]){let o=new H(Math.cos(a),0,Math.sin(a)),s=[];for(let a=0;a<=5;a++){let c=a/5,l=1-c,u=new H(l*l*e.x+2*l*c*t.x+c*c*n.x,l*l*e.y+2*l*c*t.y+c*c*n.y,l*l*e.z+2*l*c*t.z+c*c*n.z),d=r/2*(1-.4*c);s.push(this.vertex(u.clone().addScaledVector(o,-d),i),this.vertex(u.clone().addScaledVector(o,d),i))}for(let e=0;e<5;e++){let t=s[e*2],n=s[e*2+1],r=s[e*2+2],i=s[e*2+3];this.indices.push(t,n,r,r,n,i)}}}addPetal(e,t,n,r,i){let a=new H().crossVectors(n,t).normalize(),o=r.centerRadius*.85,s=Math.sin(i)*r.petalLength*.45,c=Math.sin(i)*r.petalLength*.95,l=Math.cos(i),u=e.clone().addScaledVector(t,o),d=o+r.petalLength*l*.55,f=o+r.petalLength*l,p=e.clone().addScaledVector(t,d).addScaledVector(a,r.petalWidth/2).addScaledVector(n,s),m=e.clone().addScaledVector(t,d).addScaledVector(a,-r.petalWidth/2).addScaledVector(n,s),h=e.clone().addScaledVector(t,f).addScaledVector(n,c),g=this.vertex(u,null),_=this.vertex(p,null),v=this.vertex(m,null),y=this.vertex(h,null);this.indices.push(g,_,y,g,y,v)}addDisc(e,t,n,r,i){let a=this.vertex(e,i),o=[];for(let a=0;a<6;a++){let s=a/6*Math.PI*2;o.push(this.vertex(e.clone().addScaledVector(t,Math.cos(s)*r).addScaledVector(n,Math.sin(s)*r),i))}for(let e=0;e<6;e++)this.indices.push(a,o[e],o[(e+1)%6])}addLeaf(e,t,n){let r=new H(Math.cos(t),0,Math.sin(t)),i=new H(-Math.sin(t),0,Math.cos(t)),a=Math.sin(.6),o=Math.cos(.6),s=e.clone().addScaledVector(r,dw*o*.5).add(new H(0,dw*a*.5,0)),c=e.clone().addScaledVector(r,dw*o).add(new H(0,dw*a*.8,0)),l=this.vertex(e,n),u=this.vertex(s.clone().addScaledVector(i,fw/2),n),d=this.vertex(s.clone().addScaledVector(i,-.05/2),n),f=this.vertex(c,n);this.indices.push(l,u,f,l,f,d)}build(){let e=new q;return e.setAttribute(`position`,new K(new Float32Array(this.positions),3)),this.colors&&e.setAttribute(`color`,new K(new Float32Array(this.colors),3)),e.setIndex(this.indices),e.computeVertexNormals(),e}},vw=2.6;function yw(e){let{seed:t,areaX:n,areaZ:r,count:i,clustering:a}=e,o=new b(t),s=n/2,c=r/2,l=1-.74*Math.min(Math.max(a,0),1),u=[];for(let e=0;e<i*16&&u.length<i;e++){let e=o.range(-s,s),t=o.range(-c,c),n=JC(e,t,vw);n.lean>l&&o.next()>.06||u.push({x:e,z:t,rotY:o.next()*Math.PI*2,scale:.75+o.next()*.5,variety01:(n.hue+1)/2,color01:n.leanDir/(Math.PI*2)})}return u}var bw=1.05,xw=1;function Sw(e,t=xw){e.computeBoundingSphere();let n=e.boundingSphere;n&&n.radius>=0&&(n.radius=n.radius*bw+t),e.frustumCulled=!0}function Cw(e){let t=0,n=0,r=0;for(let i=e;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return[t,n,r]}function ww(e,t){if(t!==``){let n=e.getNodeOrNull(t);return n instanceof lS?n:null}return Tw(e.getRoot())}function Tw(e){if(e instanceof lS)return e;for(let t of e.children){let e=Tw(t);if(e)return e}return null}var Ew={lush:2.2,sparse:.35,none:0},Dw=[`lush`,`sparse`,`none`];function Ow(e){if(typeof e==`number`)return e;let t=Ew[e];if(t===void 0)throw new y(`BAD_FORMAT`,`Flowers3D density must be one of [${Dw.join(`, `)}] or a number (plants/m²), got '${e}'.`,{prop:`density`,validOptions:Dw});return t}var kw=1e4,Aw=[`#f5f1e2`,`#e9d052`,`#8d7bd9`],jw=/^#[0-9a-fA-F]{6}$/,Mw=class extends qp{static typeName=`Flowers3D`;static props={density:{default:`sparse`,options:Dw},area:{default:[20,20]},seed:{default:1},varieties:{default:[]},palette:{default:[]},height:{default:.45},clustering:{default:.6},sway:{default:.5},drape:{default:null},terrain:{default:``}};density=`sparse`;area=[20,20];seed=1;varieties=[];palette=[];height=.45;clustering=.6;sway=.5;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(typeof t.density==`string`)Ow(t.density);else if(!(Number.isFinite(t.density)&&t.density>=0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' density must be one of [${Dw.join(`, `)}] or a number >= 0 (plants/m²), got ${t.density}.`,{prop:`density`,validOptions:Dw});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});let n=Math.floor((t.area[0]??0)*(t.area[1]??0)*Ow(t.density));if(n>kw)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' blows the plant budget: area ${t.area[0]}×${t.area[1]} m × density ${Ow(t.density)} = ${n} plants > ${kw}. Lower the density or split the field into multiple nodes.`,{prop:`density`});if(!Array.isArray(t.varieties)||new Set(t.varieties).size!==t.varieties.length||!t.varieties.every(e=>iw.includes(e)))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' varieties must be a unique subset of [${iw.join(`, `)}] ([] = all three), got ${JSON.stringify(t.varieties)}.`,{prop:`varieties`,validOptions:[...iw]});if(!Array.isArray(t.palette)||!t.palette.every(e=>typeof e==`string`&&jw.test(e)))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' palette must be an array of '#rrggbb' head colors ([] = white/yellow/violet), got ${JSON.stringify(t.palette)}.`,{prop:`palette`});if(!(t.height>0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' height must be > 0 meters, got ${t.height}.`,{prop:`height`});if(!(t.clustering>=0)||!(t.clustering<=1))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' clustering must be in [0, 1] (0 uniform … 1 tight patches), got ${t.clustering}.`,{prop:`clustering`});if(!(t.sway>=0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' sway must be >= 0, got ${t.sway}.`,{prop:`sway`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`})}time=0;field=null;varietyMeshes=[];fieldKey=``;timeUniform={value:0};swayUniform={value:.5};_createObject3D(){return new Qi}_varietyMeshes(){return this.rebuildIfNeeded(),this.varietyMeshes}update(e){this.time+=e,this.timeUniform.value=this.time}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded(),this.swayUniform.value=this.sway}rebuildIfNeeded(){this.field||(this.field=new Qi,this._ensureObject3D().add(this.field));let e=JSON.stringify([this.density,this.area,this.seed,this.varieties,this.palette,this.height,this.clustering,this.drape,this.terrain]);e!==this.fieldKey&&(this.fieldKey=e,this.disposeMeshes(),this.resolveDrape(),this.buildField())}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=ww(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Cw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Flowers3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildField(){let e=Ow(this.density),t=Math.min(Math.floor((this.area[0]??0)*(this.area[1]??0)*e),kw);if(t<=0)return;let n=yw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:t,clustering:this.clustering}),r=this.varieties.length>0?this.varieties:iw,i=r.map(()=>[]);for(let e of n)i[Math.min(Math.floor(e.variety01*r.length),r.length-1)].push(e);let a=this.palette.length>0?this.palette:Aw,o=new b(this.seed+15797765);for(let e=0;e<r.length;e++){let t=i[e];if(t.length===0)continue;let{structure:n,petals:s}=gw(r[e]),c=new nc({vertexColors:!0,roughness:1,side:2}),l=new nc({roughness:.85,side:2});Nw(c,this.timeUniform,this.swayUniform),Nw(l,this.timeUniform,this.swayUniform);let u=new rs(n,c,t.length),d=new rs(s,l,t.length);u.receiveShadow=!0,d.receiveShadow=!0;for(let e=0;e<t.length;e++){let n=t[e];Iw.set(n.x,this.bedY(n.x,n.z),n.z),Lw.setFromAxisAngle(Pw,n.rotY),Rw.setScalar(this.height*n.scale),Fw.compose(Iw,Lw,Rw),u.setMatrixAt(e,Fw),d.setMatrixAt(e,Fw);let r=Math.min(Math.floor(n.color01*a.length),a.length-1);zw.set(a[r]).offsetHSL(o.range(-.02,.02),0,o.range(-.05,.05)),d.setColorAt(e,zw),zw.setRGB(1,1,1).offsetHSL(o.range(-.02,.02),0,o.range(-.06,.04)),u.setColorAt(e,zw)}u.instanceMatrix.needsUpdate=!0,d.instanceMatrix.needsUpdate=!0,u.instanceColor&&(u.instanceColor.needsUpdate=!0),d.instanceColor&&(d.instanceColor.needsUpdate=!0),Sw(u),Sw(d),this.varietyMeshes.push({variety:r[e],structure:u,petals:d}),this.field.add(u),this.field.add(d)}}disposeMeshes(){for(let{structure:e,petals:t}of this.varietyMeshes)for(let n of[e,t])n.removeFromParent(),n.geometry.dispose(),n.material.dispose(),n.dispose();this.varietyMeshes=[]}free(){this.disposeMeshes(),this.field=null,super.free()}};function Nw(e,t,n){e.userData.sway=!0,e.userData.timeUniform=t,e.onBeforeCompile=e=>{e.uniforms.uFlowerTime=t,e.uniforms.uFlowerSway=n,e.vertexShader=`uniform float uFlowerTime;\nuniform float uFlowerSway;\n${e.vertexShader}`.replace(`#include <project_vertex>`,`
|
|
6926
|
+
`;function rS(e,t){for(let n=0;n<4;n++){let r=n+1;e.uniforms[`splatTexture${r}`]={value:t.textures[n]??t.textures[0]??null},e.uniforms[`splatNormalMap${r}`]={value:t.normalMaps[n]??null},e.uniforms[`splatTextureRepeat${r}`]={value:t.repeats[n]??1},e.uniforms[`splatRoughness${r}`]={value:t.roughness[n]??1},e.uniforms[`splatMetalness${r}`]={value:t.metalness[n]??0},e.uniforms[`uvNoiseIntensity${r}`]={value:t.uvNoiseIntensity[n]??.15}}e.uniforms.splatTextureCount={value:Math.min(4,t.layerCount)},e.uniforms.uWetlineY={value:-1e9},e.uniforms.uWetlineBand={value:1.1},e.uniforms.uWetTime={value:0},e.uniforms.splatEnvCut={value:t.envCut},e.vertexShader=Jx(e.vertexShader,`#include <common>`,Yx),e.vertexShader=Jx(e.vertexShader,`#include <begin_vertex>`,Xx);let n=e.fragmentShader;n=Jx(n,`#include <common>`,Zx),n=Jx(n,`#include <color_fragment>`,Qx),n=Jx(n,`#include <roughnessmap_fragment>`,$x),n=Jx(n,`#include <metalnessmap_fragment>`,tS),n=Jx(n,`#include <normal_fragment_maps>`,nS),n=Jx(n,`#include <lights_fragment_maps>`,eS),t.hasNormalMaps&&(n=`#define USE_TERRAIN_NORMALMAP\n${n}`),e.fragmentShader=n}var iS=[`island`,`alpine`,`plains`,`desert`,`grassland`,`forest`,`savanna`,`snow`,`wetland`,`volcanic`,`custom`],aS=`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,oS=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground`,sS=1/3,cS=Math.PI/4;function lS(e,t,n){return{texture:`${e}/${t}.png`,normalMap:`${e}/${t}_normal.png`,...n}}function uS(e,t){let n=t.replace(/\/$/,``);switch(e){case`island`:return[lS(n,`sand`,{heightRange:[0,.12],slopeRange:[0,Math.PI/2],heightBlendRange:.05,roughness:.9}),lS(n,`grass`,{heightRange:[.1,.7],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.1,roughness:.8}),lS(n,`stone`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.5,roughness:.85}),lS(n,`snow`,{heightRange:[.8,1],slopeRange:[0,Math.PI/3],heightBlendRange:.1,roughness:.6})];case`alpine`:return[lS(n,`grass`,{heightRange:[0,.45],slopeRange:[0,Math.PI/5],heightBlendRange:.1,roughness:.8}),lS(n,`stone`,{heightRange:[.3,1],slopeRange:[0,Math.PI],heightBlendRange:.25,slopeBlendRange:.5,roughness:.85}),lS(n,`gravel`,{heightRange:[0,1],slopeRange:[Math.PI/5,Math.PI],heightBlendRange:.5,slopeBlendRange:.15,roughness:.9}),lS(n,`snow`,{heightRange:[.55,1],slopeRange:[0,Math.PI/3],heightBlendRange:.12,roughness:.55})];case`plains`:return[lS(n,`grass`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.1,roughness:.8}),lS(n,`dirt`,{heightRange:[.35,.65],slopeRange:[0,Math.PI/5],heightBlendRange:.2,roughness:.9}),lS(n,`gravel`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.9})];case`desert`:return[lS(n,`sand`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),lS(n,`gravel`,{heightRange:[0,.15],slopeRange:[0,Math.PI/3],heightBlendRange:.08,roughness:.9}),lS(n,`stone`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.4,roughness:.85})];case`grassland`:return n===`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`?[{texture:`${oS}/grass.jpg`,heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.15,roughness:1,repeat:sS,uvNoiseIntensity:0},{texture:`${oS}/dirt_color.jpg`,heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:1,repeat:sS,uvNoiseIntensity:0}]:[lS(n,`grass`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.15,roughness:.8}),lS(n,`dirt`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.9})];case`forest`:return n===`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`?[{texture:`${oS}/dirt_color.jpg`,heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:1,repeat:sS,uvNoiseIntensity:0},{texture:`${oS}/grass.jpg`,heightRange:[-2,-1],roughness:1,repeat:sS,uvNoiseIntensity:0}]:[lS(n,`dirt`,{heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:.9}),lS(n,`grass`,{heightRange:[-2,-1],roughness:.8})];case`savanna`:return[lS(n,`grass`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),lS(n,`sand`,{heightRange:[0,.22],slopeRange:[0,Math.PI/4],heightBlendRange:.12,roughness:.95}),lS(n,`dirt`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.95})];case`snow`:return[lS(n,`snow`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.18,roughness:.55}),lS(n,`stone`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.35,roughness:.85})];case`wetland`:return[lS(n,`grass`,{heightRange:[0,1],slopeRange:[0,cS],heightBlendRange:.1,slopeBlendRange:.15,roughness:.95}),lS(n,`dirt`,{heightRange:[0,1],slopeRange:[cS,Math.PI],heightBlendRange:.5,slopeBlendRange:.3,roughness:.95})];case`volcanic`:return[lS(n,`stone`,{heightRange:[0,1],slopeRange:[0,Math.PI],heightBlendRange:.1,roughness:.95}),lS(n,`gravel`,{heightRange:[0,.28],slopeRange:[0,Math.PI/3],heightBlendRange:.14,slopeBlendRange:.2,roughness:.95})];case`custom`:return[]}}var dS={scale:100,threshold:.7,blend:.1},fS={scale:55,threshold:.58,blend:.12},pS={scale:85,threshold:.62,blend:.12},mS={scale:48,threshold:.5,blend:.14};function hS(e,t){let n=et(e+27927);return(e,r)=>{let i=(.5+.5*n(e/t.scale,r/t.scale)-(t.threshold-t.blend))/(2*t.blend),a=Math.min(1,Math.max(0,i));return a*a*(3-2*a)}}function gS(e,t){return e===`grassland`?hS(t,dS):e===`forest`?hS(t,fS):e===`savanna`?hS(t,pS):e===`wetland`?hS(t,mS):null}function _S(e){return e===`savanna`?{from:0,to:2}:e===`grassland`||e===`forest`||e===`wetland`?{from:0,to:1}:null}var vS=256,yS=class extends qp{orderGroup=`terrain`;static typeName=`Terrain3D`;static props={orderGroup:{default:`terrain`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},size:{default:[200,200]},maxHeight:{default:28},seed:{default:1},resolution:{default:128},theme:{default:`island`,options:iS},roughness:{default:.5},detail:{default:4},flatThreshold:{default:.95},islandEdge:{default:null},layers:{default:[]},textureBase:{default:aS},basins:{default:[]},channels:{default:[]},wetline:{default:null}};size=[200,200];maxHeight=28;seed=1;resolution=128;theme=`island`;roughness=.5;detail=4;flatThreshold=.95;islandEdge=null;layers=[];textureBase=aS;basins=[];channels=[];externalChannels=new Map;wetline=null;splatUniforms=null;wetTime=0;update(e){this.wetTime+=e;let t=this.splatUniforms;if(!t)return;let n=this.wetline;t.uWetlineY&&(t.uWetlineY.value=typeof n?.y==`number`?n.y:-1e9),t.uWetlineBand&&(t.uWetlineBand.value=typeof n?.band==`number`?n.band:1.1),t.uWetTime&&(t.uWetTime.value=this.wetTime)}static validateJson(e){let t=e;if(!iS.includes(t.theme))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' theme must be one of [${iS.join(`, `)}], got '${t.theme}'.`,{prop:`theme`,validOptions:iS});if(!((t.size[0]??0)>0)||!((t.size[1]??0)>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' size must be positive [width, depth] meters, got ${JSON.stringify(t.size)}.`,{prop:`size`});if(!(t.maxHeight>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' maxHeight must be > 0, got ${t.maxHeight}.`,{prop:`maxHeight`});if(!Number.isInteger(t.resolution)||t.resolution<2||t.resolution>vS)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' resolution must be an integer in [2, ${vS}] (grid segments per side), got ${t.resolution}.`,{prop:`resolution`});if(!(t.roughness>0)||!Number.isFinite(t.roughness))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' roughness must be a finite number > 0, got ${t.roughness}.`,{prop:`roughness`});if(!Number.isInteger(t.detail)||t.detail<0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' detail must be an integer ≥ 0 (octave count), got ${t.detail}.`,{prop:`detail`});if(!(t.flatThreshold>=0)||!Number.isFinite(t.flatThreshold))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' flatThreshold must be a finite number ≥ 0, got ${t.flatThreshold}.`,{prop:`flatThreshold`});if(t.islandEdge!==null&&typeof t.islandEdge!=`boolean`)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' islandEdge must be true, false or null (null = theme default), got ${JSON.stringify(t.islandEdge)}.`,{prop:`islandEdge`});let n=t.wetline;if(n!==null){if(typeof n!=`object`||Array.isArray(n)||!Number.isFinite(n.y))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' wetline must be null or { y, band? } with a finite y, got ${JSON.stringify(t.wetline)}.`,{prop:`wetline`});if(n.band!==void 0&&!(n.band>0))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' wetline.band must be > 0 meters, got ${JSON.stringify(n.band)}.`,{prop:`wetline`})}if(!Array.isArray(t.basins))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' basins must be an array of { x, z, radius, depth }, got ${JSON.stringify(t.basins)}.`,{prop:`basins`});if(t.basins.forEach((t,n)=>{if(!t||typeof t!=`object`||!Number.isFinite(t.x)||!Number.isFinite(t.z)||!(t.radius>0)||!Number.isFinite(t.depth)||t.depth===0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' basins[${n}] needs finite x, z, positive radius and nonzero depth (negative = mound), got ${JSON.stringify(t)}.`,{prop:`basins`})}),!Array.isArray(t.channels))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' channels must be an array of { path, width, depth, taper? }, got ${JSON.stringify(t.channels)}.`,{prop:`channels`});if(t.channels.forEach((t,n)=>{let r=t.path;if(!(t&&typeof t==`object`&&Array.isArray(r)&&r.length>=2&&r.every(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1]))&&t.width>0&&t.depth>0&&(t.taper===void 0||t.taper>0)))throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' channels[${n}] needs a path of 2+ [x, z] points plus positive width and depth, got ${JSON.stringify(t)}.`,{prop:`channels`})}),t.theme===`custom`){if(!Array.isArray(t.layers)||t.layers.length<1||t.layers.length>4)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' theme 'custom' needs 1–4 layers, got ${Array.isArray(t.layers)?t.layers.length:typeof t.layers}.`,{prop:`layers`});t.layers.forEach((t,n)=>{SS(e.name,t,n)})}else if(Array.isArray(t.layers)&&t.layers.length>0)throw new y(`BAD_FORMAT`,`Terrain3D '${e.name}' layers is only read with theme 'custom' — preset theme '${t.theme}' defines its own. Drop layers or switch to theme: 'custom'.`,{prop:`layers`})}heightmap=null;heightmapKey=``;builtKey=``;loadedTextures=[];_createObject3D(){let e=new q;return e.setAttribute(`position`,new K(new Float32Array,3)),new jo(e,new nc({vertexColors:!0}))}heightAt(e,t){let n=0,r=0,i=0;for(let e=this;e;e=e.parent)e instanceof qp&&(n+=e.position[0]??0,r+=e.position[1]??0,i+=e.position[2]??0);return this._heightmap().heightAt(e-n,t-i)+r}_setExternalChannel(e,t){t===null||t.length===0?this.externalChannels.delete(e):this.externalChannels.set(e,t)}allChannels(){return this.externalChannels.size===0?this.channels:[...this.channels,...[...this.externalChannels.values()].flat()]}_heightmap(){let e=this.segments(),t=JSON.stringify([this.size,this.maxHeight,this.seed,e,this.roughness,this.detail,this.flatThreshold,this.effectiveIslandEdge(),this.basins,this.allChannels()]);return(!this.heightmap||t!==this.heightmapKey)&&(this.heightmap=Gx({width:this.size[0]??1,depth:this.size[1]??1,segsX:e,segsZ:e,maxHeight:this.maxHeight,seed:this.seed,roughness:this.roughness,detail:this.detail,flatThreshold:this.flatThreshold,islandEdge:this.effectiveIslandEdge(),basins:this.basins,channels:this.allChannels()}),this.heightmapKey=t),this.heightmap}resolvedLayers(){return this.theme===`custom`?this.layers:uS(this.theme,this.textureBase)}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded()}effectiveIslandEdge(){return this.islandEdge??this.theme===`island`}segments(){return Math.max(2,Math.min(Math.floor(this.resolution),vS))}rebuildIfNeeded(){let e=JSON.stringify([this.size,this.maxHeight,this.seed,this.segments(),this.theme,this.roughness,this.detail,this.flatThreshold,this.islandEdge,this.layers,this.textureBase,this.basins,this.allChannels()]);if(e===this.builtKey)return;this.builtKey=e;let t=this._ensureObject3D();t.geometry.dispose(),t.geometry=this.buildGeometry(),t.material.dispose(),this.disposeTextures(),t.material=this.buildMaterial(),t.receiveShadow=!0,t.castShadow=!0}buildGeometry(){let e=this._heightmap(),t=new Ws(e.width,e.depth,e.segsX,e.segsZ);t.rotateX(-Math.PI/2);let n=t.getAttribute(`position`);for(let t=0;t<n.count;t++)n.setY(t,e.heights[t]);n.needsUpdate=!0,t.computeVertexNormals();let r=this.resolvedLayers(),i=e.maxHeight-e.minHeight||1,a=new Float32Array(n.count*3),o=this.theme===`custom`?null:_S(this.theme),s=o?gS(this.theme,this.seed):null;for(let t=0;t<n.count;t++){let c=n.getX(t),l=n.getZ(t),u=qx(Math.min(1,Math.max(0,(n.getY(t)-e.minHeight)/i)),e.slopeAt(c,l),r);if(s&&o){let e=(u[o.from]??0)*s(c,l);u[o.from]=(u[o.from]??0)-e,u[o.to]=(u[o.to]??0)+e}a[t*3]=u[0],a[t*3+1]=u[1],a[t*3+2]=u[2]}return t.setAttribute(`color`,new K(a,3)),t}buildMaterial(){let e=this.resolvedLayers(),t=new nc({vertexColors:!0}),n=typeof document<`u`?new Ic:null,r=(e,t)=>{if(!n||!e)return null;let r=n.load(e);return r.wrapS=It,r.wrapT=It,r.anisotropy=8,t&&(r.colorSpace=dr),this.loadedTextures.push(r),r},i=e.map(e=>r(e.texture,!0)),a=e.map(e=>r(e.normalMap,!1)),o=a.some(e=>e!==null);if(o)for(let e=0;e<a.length;e++)a[e]||(a[e]=xS());let s={textures:i,normalMaps:a,repeats:e.map(e=>e.repeat??2),roughness:e.map(e=>e.roughness??1),metalness:e.map(e=>e.metalness??0),uvNoiseIntensity:e.map(e=>e.uvNoiseIntensity??.15),envCut:.45,layerCount:Math.min(4,e.length),hasNormalMaps:o};return t.onBeforeCompile=e=>{rS(e,s),this.splatUniforms=e.uniforms},t.customProgramCacheKey=()=>`incanto-terrain-splat:${+!!o}`,t}disposeTextures(){for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[]}free(){let e=this._ensureObject3D();e.geometry.dispose(),e.material.dispose(),this.disposeTextures(),this.heightmap=null,super.free()}},bS=null;function xS(){return bS||(bS=new Go(new Uint8Array([128,128,255,255]),1,1),bS.needsUpdate=!0),bS}function SS(e,t,n){let r=`layers[${n}]`;if(typeof t!=`object`||!t||Array.isArray(t))throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r} must be an object ({texture, heightRange?, slopeRange?, …}).`,{prop:`layers`});let i=t;if(typeof i.texture!=`string`||i.texture.length===0)throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r} needs "texture": a texture URL string.`,{prop:`layers`});for(let t of[`heightRange`,`slopeRange`]){let n=i[t];if(n!==void 0&&(!Array.isArray(n)||n.length!==2||n.some(e=>typeof e!=`number`||!Number.isFinite(e))))throw new y(`BAD_FORMAT`,`Terrain3D '${e}' ${r}.${t} must be [min, max] numbers, got ${JSON.stringify(n)}.`,{prop:`layers`})}}var CS=Math.PI/180;async function wS(e,t){let n=await Dh(()=>import(`./rapier-DE6a0vmv.js`),[],import.meta.url);return await n.init({}),new TS(n,e,t)}var TS=class{R;engine;debugDraw=!1;dimension=`3d`;unregisterDebug;warnedNoCollider=new WeakSet;entries=new Map;byColliderHandle=new Map;world;events;kcc;disconnect;lastDt=1/60;optsGravity;lastScene=null;constructor(e,t,n){this.R=e,this.engine=t,this.optsGravity=n?.gravity,this.lastScene=t.scene;let r=t.scene?.physics?.gravity,i=n?.gravity??r??[0,-9.81,0];this.world=new e.World({x:i[0]??0,y:i[1]??0,z:i[2]??0}),this.kcc=this.world.createCharacterController(.01),this.events=new e.EventQueue(!0),this.unregisterDebug=xh(this),this.disconnect=t.fixedUpdated.connect(e=>this.step(e)),this.syncBodies()}step(e){if(this.lastDt=e,this.engine.scene!==this.lastScene&&(this.lastScene=this.engine.scene,!this.optsGravity)){let e=this.engine.scene?.physics?.gravity??[0,-9.81,0];this.world.gravity={x:e[0]??0,y:e[1]??0,z:e[2]??0}}this.syncBodies(),this.world.timestep=e,this.world.step(this.events);for(let[e,t]of this.entries){let n=t.body.translation();if(!t.body.isFixed()){let[t,r,i]=NS(e),a=[n.x-t,n.y-r,n.z-i];e._interpPrev=e._interpCurr??a,e._interpCurr=a;let o=e.position;o[0]=a[0],o[1]=a[1],o[2]=a[2]}if(e instanceof Zp){if(!e.fixedRotation){let n=t.body.rotation();DS.setFromQuaternion(ES.set(n.x,n.y,n.z,n.w),`XYZ`);let r=e.rotation;r[0]=DS.x/CS,r[1]=DS.y/CS,r[2]=DS.z/CS}let n=t.body.linvel(),r=e.linearVelocity;r[0]=n.x,r[1]=n.y,r[2]=n.z,t.lastV[0]=n.x,t.lastV[1]=n.y,t.lastV[2]=n.z}let r=jS(e);t.last[0]=r[0],t.last[1]=r[1],t.last[2]=r[2]}this.events.drainCollisionEvents((e,t,n)=>{let r=this.byColliderHandle.get(e),i=this.byColliderHandle.get(t);if(!r||!i)return;let a=n?`triggerEnter`:`triggerExit`;try{r.emit(a,i),i.emit(a,r)}catch(e){console.error(`incanto: error in a '${a}' handler (${r.name} ↔ ${i.name}):`,e)}})}moveAndSlide(e){let t=this.ensureEntry(e),n=e.velocity[1]??0;e.snapToGround&&n<=0?this.kcc.enableSnapToGround(.1):this.kcc.disableSnapToGround(),this.kcc.setMaxSlopeClimbAngle(e.slopeLimitDeg*CS);let r={x:(e.velocity[0]??0)*this.lastDt,y:n*this.lastDt,z:(e.velocity[2]??0)*this.lastDt};this.kcc.computeColliderMovement(t.collider,r,this.R.QueryFilterFlags.EXCLUDE_SENSORS);let i=this.kcc.computedMovement(),a=t.body.translation();t.body.setNextKinematicTranslation({x:a.x+i.x,y:a.y+i.y,z:a.z+i.z}),e._grounded=this.kcc.computedGrounded()}debugLines(){return this.debugDraw?this.world.debugRender().vertices:null}dispose(){this.disconnect(),this.unregisterDebug(),this.world.free()}lastStructure=-1;lastRoot=null;jointSet=new Set;joints=new Map;bodySet=new Set;syncBodies(){let e=this.engine.scene;if(!e)return;let t=e.tree._structureVersion,n=t!==this.lastStructure||e.root!==this.lastRoot;n&&(this.lastStructure=t,this.lastRoot=e.root,this.bodySet.clear(),kS(e.root,this.bodySet)),n&&(this.jointSet.clear(),OS(e.root,this.jointSet));let r=this.bodySet;for(let e of r){if(e.collider.shape===void 0){let t=this.entries.get(e);t&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null),this.warnedNoCollider.has(e)||(this.warnedNoCollider.add(e),console.warn(`[incanto] '${e.name}' has no collider — physics skips it.`));continue}let t=this.entries.get(e);t&&e._colliderChanged&&(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null),this.ensureEntry(e)}if(this.syncJoints(n),n)for(let[e,t]of this.entries)r.has(e)||(this.byColliderHandle.delete(t.collider.handle),this.world.removeRigidBody(t.body),this.entries.delete(e),e._physics=null,e._interpPrev=e._interpCurr=null)}ensureEntry(e){let t=this.entries.get(e),n=this.R;if(!t){let r;r=e instanceof Zp?n.RigidBodyDesc.dynamic():e instanceof Qp||e instanceof Xp?n.RigidBodyDesc.kinematicPositionBased():n.RigidBodyDesc.fixed();let[i,a,o]=jS(e);r.setTranslation(i,a,o),ES.setFromEuler(DS.set((e.rotation[0]??0)*CS,(e.rotation[1]??0)*CS,(e.rotation[2]??0)*CS,`XYZ`)),r.setRotation({x:ES.x,y:ES.y,z:ES.z,w:ES.w}),e instanceof Zp&&(r.setGravityScale(e.gravityScale),r.setLinvel(e.linearVelocity[0]??0,e.linearVelocity[1]??0,e.linearVelocity[2]??0),e.fixedRotation&&r.lockRotations());let s=this.world.createRigidBody(r),c=PS(n,e);c.setActiveEvents(n.ActiveEvents.COLLISION_EVENTS),c.setActiveCollisionTypes(n.ActiveCollisionTypes.ALL),e instanceof Xp&&c.setSensor(!0),e instanceof Zp&&c.setMass(e.mass).setFriction(e.friction).setRestitution(e.restitution);let l=this.world.createCollider(c,s);return t={body:s,collider:l,last:[i,a,o],lastV:[0,0,0]},this.entries.set(e,t),this.byColliderHandle.set(l.handle,e),e._colliderChanged=!1,e._physics=this,e instanceof Zp&&(e._physics3d=this),t}let r=jS(e);if((r[0]!==t.last[0]||r[1]!==t.last[1]||r[2]!==t.last[2])&&(t.body.setTranslation({x:r[0],y:r[1],z:r[2]},!0),t.last[0]=r[0],t.last[1]=r[1],t.last[2]=r[2],e._interpPrev=e._interpCurr=null),e instanceof Zp){let n=[e.linearVelocity[0]??0,e.linearVelocity[1]??0,e.linearVelocity[2]??0];(n[0]!==t.lastV[0]||n[1]!==t.lastV[1]||n[2]!==t.lastV[2])&&(t.body.setLinvel({x:n[0],y:n[1],z:n[2]},!0),t.lastV=n),e.gravityScale!==t.body.gravityScale()&&t.body.setGravityScale(e.gravityScale,!0)}return t}applyImpulse(e,t){this.entries.get(e)?.body.applyImpulse({x:t[0],y:t[1],z:t[2]},!0)}massOf(e){return this.entries.get(e)?.body.mass()??1}velocityOf(e){let t=this.entries.get(e)?.body.linvel();return t?[t.x,t.y,t.z]:[0,0,0]}syncJoints(e){let t=this.R;if(e)for(let[e,t]of this.joints)this.jointSet.has(e)||(this.world.removeImpulseJoint(t,!0),this.joints.delete(e));for(let e of this.jointSet){if(this.joints.has(e))continue;let{a:n,b:r}=e._resolveBodies(),i=this.entries.get(n),a=this.entries.get(r);if(!i||!a)continue;let o={x:e.anchor[0]??0,y:e.anchor[1]??0,z:e.anchor[2]??0},s={x:e.targetAnchor[0]??0,y:e.targetAnchor[1]??0,z:e.targetAnchor[2]??0},c=e.length;if(e.length===0&&(e.type===`rope`||e.type===`spring`)){let e=i.body.translation(),t=a.body.translation();c=Math.hypot(t.x-e.x,t.y-e.y,t.z-e.z)}let l={x:0,y:0,z:0,w:1},u;u=e.type===`fixed`?t.JointData.fixed(o,l,s,l):e.type===`rope`?t.JointData.rope(c,o,s):e.type===`spring`?t.JointData.spring(c,e.stiffness,e.damping,o,s):t.JointData.spherical(o,s),this.joints.set(e,this.world.createImpulseJoint(u,i.body,a.body,!0))}}castRay(e,t,n,r,i){let a=new this.R.Ray({x:e[0],y:e[1],z:e[2]},{x:t[0],y:t[1],z:t[2]}),o=r?this.entries.get(r)?.collider:void 0,s=i?.staticOnly?this.R.QueryFilterFlags.EXCLUDE_DYNAMIC|this.R.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,c=this.world.castRayAndGetNormal(a,n,!0,s,void 0,o,void 0,e=>!e.isSensor());return c?{distance:c.timeOfImpact,normal:[c.normal.x,c.normal.y,c.normal.z],node:this.byColliderHandle.get(c.collider.handle)??null}:null}castSphere(e,t,n,r,i,a){let o=this.R,s=i?this.entries.get(i):void 0,c=a?.staticOnly?o.QueryFilterFlags.EXCLUDE_DYNAMIC|o.QueryFilterFlags.EXCLUDE_KINEMATIC:void 0,l=this.world.castShape({x:e[0],y:e[1],z:e[2]},{x:0,y:0,z:0,w:1},{x:t[0],y:t[1],z:t[2]},new o.Ball(n),0,r,!0,c,void 0,s?.collider,s?.body,e=>!e.isSensor());return l?{distance:l.time_of_impact,node:this.byColliderHandle.get(l.collider.handle)??null}:null}},ES=new V,DS=new Pi;function OS(e,t){e instanceof Bx&&t.add(e);for(let n of e.children)OS(n,t)}function kS(e,t){e instanceof Jp&&t.add(e);for(let n of e.children)kS(n,t)}var AS=[0,0,0];function jS(e){let t=0,n=0,r=0;for(let i=e;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return AS[0]=t,AS[1]=n,AS[2]=r,AS}var MS=[0,0,0];function NS(e){let t=0,n=0,r=0;for(let i=e.parent;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return MS[0]=t,MS[1]=n,MS[2]=r,MS}function PS(e,t){let n=t.collider;if(Kp(n,t.name),n.shape===`heightfield`)return FS(e,t);let r=IS(e,n,t.name),i=n.offset;return Array.isArray(i)&&r.setTranslation(i[0]??0,i[1]??0,i[2]??0),r}function FS(e,t){let n=t.children.find(e=>e instanceof yS);if(!n)throw new y(`BAD_FORMAT`,`Collider on '${t.name}': heightfield needs a Terrain3D CHILD of this body — add { "type": "Terrain3D" } under the StaticBody3D; the collider reads its height grid.`,{prop:`collider`});let r=n._heightmap(),i=r.segsZ,a=r.segsX,o=new Float32Array((i+1)*(a+1));for(let e=0;e<=a;e++)for(let t=0;t<=i;t++)o[e*(i+1)+t]=r.heights[t*(a+1)+e];let s=e.ColliderDesc.heightfield(i,a,o,{x:r.width,y:1,z:r.depth}),c=Array.isArray(t.collider.offset)?t.collider.offset:[];return s.setTranslation((n.position[0]??0)+(c[0]??0),(n.position[1]??0)+(c[1]??0),(n.position[2]??0)+(c[2]??0)),s}function IS(e,t,n){let r=t.shape;if(r===`box`){let r=t.size;if(!Array.isArray(r)||r.length!==3||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`Collider on '${n}': box needs "size": [x, y, z].`);return e.ColliderDesc.cuboid(r[0]/2,r[1]/2,r[2]/2)}if(r===`sphere`){if(typeof t.radius!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': sphere needs "radius".`);return e.ColliderDesc.ball(t.radius)}if(r===`capsule`){if(typeof t.radius!=`number`||typeof t.height!=`number`)throw new y(`BAD_FORMAT`,`Collider on '${n}': capsule needs "radius" and "height".`);return e.ColliderDesc.capsule(t.height/2,t.radius)}if(r===`trimesh`){let r=t.vertices,i=t.indices;if(!Array.isArray(r)||!Array.isArray(i))throw new y(`BAD_FORMAT`,`Collider on '${n}': trimesh needs "vertices" (flat xyz) and "indices" (triangles).`);return e.ColliderDesc.trimesh(new Float32Array(r),new Uint32Array(i))}throw new y(`BAD_FORMAT`,`Collider on '${n}': "shape" must be 'box', 'sphere', 'capsule', 'trimesh', or 'heightfield', got ${JSON.stringify(r)}.`)}var LS=new Ws(1,1),RS=null;function zS(){if(RS)return RS;if(typeof document>`u`)return null;let e=document.createElement(`canvas`);e.width=64,e.height=64;let t=e.getContext(`2d`);if(!t)return null;let n=t.createRadialGradient(32,32,0,32,32,31);return n.addColorStop(0,`rgba(0,0,0,0.55)`),n.addColorStop(.55,`rgba(0,0,0,0.34)`),n.addColorStop(1,`rgba(0,0,0,0)`),t.fillStyle=n,t.fillRect(0,0,64,64),RS=new Ps(e),RS}var BS=new H(0,0,1),VS=new H,HS=new H,US=new V,WS=new V,GS=new H,KS=.5,qS=class extends qp{static typeName=`Sprite3D`;static props={texture:{default:``},size:{default:[1,1]},billboard:{default:`y`,options:[`y`,`full`,`none`]},anchor:{default:[.5,0]},tint:{default:`#ffffff`},opacity:{default:1},flipX:{default:!1},pixelArt:{default:!0},alphaTest:{default:.5},castShadow:{default:!1},shadowMode:{default:`silhouette`,options:[`silhouette`,`blob`]}};texture=``;size=[1,1];billboard=`y`;anchor=[.5,0];tint=`#ffffff`;opacity=1;flipX=!1;pixelArt=!0;alphaTest=.5;castShadow=!1;shadowMode=`silhouette`;quadMesh=null;textureRef=``;loadedTexture=null;shadowMesh=null;blobMesh=null;_quad(){return this.quadMesh||(this.quadMesh=new jo(LS,new yo({transparent:!1,depthWrite:!0,side:2})),this._ensureObject3D().add(this.quadMesh)),this.quadMesh}resolveTexture(){if(!this.texture)return null;if(this.textureRef!==this.texture&&(this.loadedTexture?.dispose(),this.loadedTexture=null,this.textureRef=this.texture,typeof document<`u`)){let e=new Ic().load(this.texture);e.colorSpace=dr;let t=this.pixelArt?zt:Ht;e.magFilter=t,e.minFilter=t,this.loadedTexture=e}return this.loadedTexture}_syncObject3D(e=1){super._syncObject3D(e);let t=this._quad(),n=t.material,r=this.size[0]??1,i=this.size[1]??1;t.scale.set(this.flipX?-r:r,i,1);let a=this.anchor[0]??.5,o=this.anchor[1]??0;t.position.set((.5-a)*r,(.5-o)*i,0);let s=this.resolveTexture();n.map!==s&&(n.map=s,n.needsUpdate=!0),t.visible=s!==null,n.color.set(this.tint),n.opacity=this.opacity,n.transparent=this.opacity<1,n.alphaTest=this.alphaTest,t.renderOrder=this.renderOrder;let c=this.castShadow&&s!==null;if(t.castShadow=!1,c&&this.shadowMode===`silhouette`){let e=this._shadowCaster();e.visible=!0,e.castShadow=!0,e.scale.set(this.flipX?-r:r,i,1),e.position.set((.5-a)*r,(.5-o)*i,0);let t=e.material;t.map!==s&&(t.map=s,t.needsUpdate=!0);let n=e.customDepthMaterial;n.map!==s&&(n.map=s,n.needsUpdate=!0),t.alphaTest=this.alphaTest,n.alphaTest=this.alphaTest}else this.shadowMesh&&(this.shadowMesh.visible=!1,this.shadowMesh.castShadow=!1);if(c&&this.shadowMode===`blob`){let e=this._blob();e.visible=!0,e.scale.set(r*.52,r*.52,1)}else this.blobMesh&&(this.blobMesh.visible=!1)}_shadowCaster(){return this.shadowMesh||(this.shadowMesh=new jo(LS,new yo({colorWrite:!1,depthWrite:!1,side:2})),this.shadowMesh.customDepthMaterial=new ic({depthPacking:ur,side:2}),this._ensureObject3D().add(this.shadowMesh)),this.shadowMesh}_blob(){return this.blobMesh||(this.blobMesh=new jo(LS,new yo({map:zS(),color:0,transparent:!0,depthWrite:!1})),this.blobMesh.rotation.x=-Math.PI/2,this.blobMesh.position.y=.02,this.blobMesh.renderOrder=-1,this._ensureObject3D().add(this.blobMesh)),this.blobMesh}_onRender3D(e){this.billboard===`y`?(e.camera.getWorldDirection(HS),HS.y=0,HS.lengthSq()>=1e-6&&this._faceDir(this._quad(),HS.negate())):this.billboard===`full`&&this._faceToward(this._quad(),e.camera.position);let t=this.shadowMesh;t?.castShadow&&e.sunDir&&(this._faceDir(t,e.sunDir),t.parent?.getWorldQuaternion(WS),GS.copy(e.sunDir).applyQuaternion(WS.invert()),t.position.addScaledVector(GS,KS))}_faceToward(e,t){e.getWorldPosition(VS),HS.copy(t).sub(VS),this.billboard===`y`&&(HS.y=0),!(HS.lengthSq()<1e-12)&&(HS.normalize(),US.setFromUnitVectors(BS,HS),e.parent?.getWorldQuaternion(WS),e.quaternion.copy(WS.invert()).multiply(US))}_faceDir(e,t){HS.copy(t),this.billboard===`y`&&(HS.y=0),!(HS.lengthSq()<1e-12)&&(HS.normalize(),US.setFromUnitVectors(BS,HS),e.parent?.getWorldQuaternion(WS),e.quaternion.copy(WS.invert()).multiply(US))}free(){this.loadedTexture?.dispose(),this.loadedTexture=null,this.shadowMesh&&(this.shadowMesh.material.dispose(),this.shadowMesh.customDepthMaterial?.dispose()),this.blobMesh&&this.blobMesh.material.dispose(),super.free()}},JS=class extends qS{static typeName=`AnimatedSprite3D`;static signals=[`animationFinished`];static props={sheet:{default:``},frameWidth:{default:0},frameHeight:{default:0},animations:{default:{}},autoplay:{default:``}};sheet=``;frameWidth=0;frameHeight=0;animations={};autoplay=``;playing=!1;currentFrame=0;currentAnimation=``;frameList=[];frameIndex=0;frameTime=0;sheetTexture=null;loadedSheetRef=``;play(e){let t=this.animations[e];if(!t)throw new y(`UNKNOWN_ANIMATION`,`No animation '${e}' on '${this.name}'. Available: [${Object.keys(this.animations).join(`, `)}].`);this.currentAnimation=e,this.frameList=YS(t.frames,e),this.frameIndex=0,this.currentFrame=this.frameList[0]??0,this.frameTime=0,this.playing=!0}stop(){this.playing=!1}onReady(){this.autoplay&&this.play(this.autoplay)}update(e){if(!this.playing||this.currentAnimation===``)return;let t=this.animations[this.currentAnimation];if(!t||!Number.isFinite(t.fps)||t.fps<=0)return;let n=1/t.fps;for(this.frameTime+=e;this.frameTime>=n;)if(this.frameTime-=n,this.frameIndex+=1,this.frameIndex>=this.frameList.length)if(t.loop)this.frameIndex=0;else{this.frameIndex=this.frameList.length-1,this.playing=!1,this.emit(`animationFinished`,this.currentAnimation);break}this.currentFrame=this.frameList[this.frameIndex]??0}resolveTexture(){if(!this.sheet||this.frameWidth<=0||this.frameHeight<=0)return null;if(this.loadedSheetRef!==this.sheet&&(this.sheetTexture?.dispose(),this.sheetTexture=null,this.loadedSheetRef=this.sheet,typeof document<`u`)){let e=new Ic().load(this.sheet);e.colorSpace=dr;let t=this.pixelArt?zt:Ht;e.magFilter=t,e.minFilter=t,this.sheetTexture=e}let e=this.sheetTexture;if(!e)return null;let t=e.image;if(!t?.width||!t.height)return e;let n=Math.max(1,Math.floor(t.width/this.frameWidth)),r=this.currentFrame%n,i=Math.floor(this.currentFrame/n);return e.repeat.set(this.frameWidth/t.width,this.frameHeight/t.height),e.offset.set(r*this.frameWidth/t.width,1-(i+1)*this.frameHeight/t.height),e}free(){this.sheetTexture?.dispose(),this.sheetTexture=null,super.free()}};function YS(e,t){if(!Array.isArray(e)||e.length===0)throw new y(`BAD_FORMAT`,`Animation '${t}': "frames" must be a non-empty array.`);if(e.length===2){let[t,n]=e;if(n>=t){let e=[];for(let r=t;r<=n;r++)e.push(r);return e}}return[...e]}var XS=new V,ZS=new V,QS=new H,$S=new H(0,0,1),eC=[`screen`,`y`,`none`],tC=class extends qp{static typeName=`Billboard3D`;static props={mode:{default:`screen`,options:eC}};mode=`screen`;_lastDesired=null;static validateJson(e){let t=e;if(!eC.includes(t.mode))throw new y(`BAD_FORMAT`,`Billboard3D '${e.name}' mode must be one of [${eC.join(`, `)}], got '${t.mode}'.`,{prop:`mode`,validOptions:eC})}_onRender3D(e){if(this.mode===`none`)return;let t=this._ensureObject3D();if(this.mode===`screen`)e.camera.getWorldQuaternion(ZS);else if(e.camera.getWorldDirection(QS),QS.y=0,QS.lengthSq()>=1e-6)ZS.setFromUnitVectors($S,QS.negate().normalize());else if(this._lastDesired)ZS.copy(this._lastDesired);else return;this._lastDesired||=new V,this._lastDesired.copy(ZS),t.parent?.getWorldQuaternion(XS),t.parent?t.quaternion.copy(XS.invert()).multiply(ZS):t.quaternion.copy(ZS)}},nC=class extends qp{static typeName=`BoneAttachment3D`;static props={target:{default:``},bone:{default:``}};target=``;bone=``;boneObj=null;lookedUpFor=``;get attachedBone(){return this.boneObj}_onRender3D(e){if(this.target===``||this.bone===``)return;let t=`${this.target} ${this.bone}`;if(this.lookedUpFor!==t||this.boneObj===null||!this.boneObj.parent){this.lookedUpFor=t,this.boneObj=null;let e=this.getNodeOrNull(this.target);e&&typeof e.findBone==`function`&&(this.boneObj=e.findBone(this.bone))}let n=this.boneObj;if(!n)return;let r=this._ensureObject3D(),i=r.parent;i&&(n.updateWorldMatrix(!0,!1),i.updateWorldMatrix(!0,!1),r.matrixAutoUpdate=!1,n.matrixWorld.decompose(aC,oC,sC),iC.compose(aC,oC,cC),r.updateMatrix(),rC.copy(r.matrix),r.matrix.copy(i.matrixWorld).invert().multiply(iC).multiply(rC))}free(){this.boneObj=null,super.free()}},rC=new W,iC=new W,aC=new H,oC=new V,sC=new H,cC=new H(1,1,1),lC=class extends qp{static typeName=`BoneLookAt3D`;static props={target:{default:``},bone:{default:`Head`},lookAt:{default:``},maxAngleDeg:{default:75},weight:{default:.85},forwardAxis:{default:`+z`,options:[`+x`,`-x`,`+y`,`-y`,`+z`,`-z`]}};target=``;bone=`Head`;lookAt=``;maxAngleDeg=75;weight=.85;forwardAxis=`+z`;boneObj=null;lookedUpFor=``;engage=0;get attachedBone(){return this.boneObj}_onRender3D(e){if(this.target===``||this.bone===``)return;let t=`${this.target} ${this.bone}`;if(this.lookedUpFor!==t||this.boneObj===null||!this.boneObj.parent){this.lookedUpFor=t,this.boneObj=null;let e=this.getNodeOrNull(this.target);e&&typeof e.findBone==`function`&&(this.boneObj=e.findBone(this.bone))}let n=this.boneObj;if(!n?.parent)return;let r=this.lookAt===``?null:this.getNodeOrNull(this.lookAt),i=!1;if(r&&Array.isArray(r.position)&&(n.updateWorldMatrix(!0,!1),n.getWorldPosition(hC),gC.set(r.position[0]??0,r.position[1]??0,r.position[2]??0),_C.copy(gC).sub(hC),_C.lengthSq()>1e-6&&(_C.normalize(),vC.copy(dC[this.forwardAxis]??pC),yC.copy(vC).applyQuaternion(n.getWorldQuaternion(wC)),yC.angleTo(_C)<this.maxAngleDeg*Math.PI/180))){i=!0,bC.lookAt(hC,gC,fC),xC.setFromRotationMatrix(bC),SC.setFromUnitVectors(vC,mC),xC.multiply(SC),n.parent.getWorldQuaternion(CC).invert(),xC.premultiply(CC);let e=this.weight*this.engage;n.quaternion.slerp(xC,e)}this.engage+=(+!!i-this.engage)*uC}},uC=.18,dC={"+x":new H(1,0,0),"-x":new H(-1,0,0),"+y":new H(0,1,0),"-y":new H(0,-1,0),"+z":new H(0,0,1),"-z":new H(0,0,-1)},fC=new H(0,1,0),pC=new H(0,0,1),mC=new H(0,0,-1),hC=new H,gC=new H,_C=new H,vC=new H,yC=new H,bC=new W,xC=new V,SC=new V,CC=new V,wC=new V,TC=class extends qp{static typeName=`Camera3D`;static props={fov:{default:60},near:{default:.1},far:{default:1e3},current:{default:!1}};fov=60;near=.1;far=1e3;current=!1;_createObject3D(){return new Yc(this.fov,1,this.near,this.far)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();(e.fov!==this.fov||e.near!==this.near||e.far!==this.far)&&(e.fov=this.fov,e.near=this.near,e.far=this.far,e.updateProjectionMatrix())}},EC=8,DC=.2,OC=.15,kC=1.2,AC=.08,jC=2.5,MC=-20,NC=.002,PC=180/Math.PI,FC=.3,IC=.4,LC=.3,RC=.25,zC=new Pi,BC=new V,VC=new W,HC=new H,UC=new H,WC=new H(0,1,0),GC=class extends qp{static typeName=`CharacterController3D`;static signals=[`movementStateChanged`];static props={view:{default:`free`,options:[`free`,`firstPerson`,`quarter`,`side`]},camDistance:{default:4},eyeHeight:{default:.64},maxSpeed:{default:2.5},sprintMultiplier:{default:2},jumpVelocity:{default:4},sprintJumpMultiplier:{default:1.2},floatHeight:{default:.01},mouseLook:{default:!0},zoomMin:{default:0},zoomMax:{default:0},pitchMin:{default:-1.3},pitchMax:{default:1.5},cameraCollision:{default:!0},turnSpeed:{default:100},camLerp:{default:25},moveAction:{default:`move`},jumpAction:{default:`jump`},sprintAction:{default:`sprint`},skinPath:{default:`../Skin`},skinYawOffset:{default:0},animations:{default:{}}};view=`free`;camDistance=4;eyeHeight=.64;maxSpeed=2.5;sprintMultiplier=2;jumpVelocity=4;sprintJumpMultiplier=1.2;floatHeight=.01;mouseLook=!0;zoomMin=0;zoomMax=0;pitchMin=-1.3;pitchMax=1.5;cameraCollision=!0;turnSpeed=100;camLerp=25;moveAction=`move`;jumpAction=`jump`;sprintAction=`sprint`;skinPath=`../Skin`;skinYawOffset=0;animations={};yaw=0;pitch=0;state=`idle`;grounded=!1;get body(){let e=this.parent;if(!(e instanceof Zp))throw new y(`TREE_VIOLATION`,`CharacterController3D '${this.name}' must be a child of a RigidBody3D (parent is '${e?.name??`none`}').`);return e}onEnterTree(){if(this.body,this.skinPath!==``){let e=this.getNodeOrNull(this.skinPath);e&&(e.rotation=[e.rotation[0]??0,180+this.skinYawOffset,e.rotation[2]??0])}}fixedUpdate(e){let t=this.body,n=t._physics3d,r=this.tree?.engine?.input;if(!n||!r)return;let i=t.collider.radius??.32,a=(t.collider.height??1)/2,o=qC(t),s=n.velocityOf(t),c=n.massOf(t),l=i+this.floatHeight,u=i+2,d=o[1]-a,f=null;for(let[e,r]of[[0,0],[i,0],[-i,0],[0,i],[0,-i]]){let i=n.castRay([o[0]+e,d,o[2]+r],[0,-1,0],u,t);if(i){let t=i.distance;if(f=f===null?t:Math.min(f,t),e===0&&r===0)break}}this.grounded=f!==null&&f<l*2;let p=0,m=0,h=!1;try{let e=r.getVector(this.moveAction);h=e.x!==0||e.y!==0;let t=this.view===`free`||this.view===`firstPerson`?this.yaw:0,n=this.view===`side`?[e.x,0,0]:Lx(e.x,-e.y,t),i=Math.hypot(n[0],n[2])||1;p=n[0]/i,m=n[2]/i}catch{}let g=JC(r,this.sprintAction),_=Rx(h,g),v=1+(this.sprintMultiplier-1)*_,y=h?this.maxSpeed*v:0,b=this.grounded?1:DC,x=(p*y-s[0])/EC*b,S=(m*y-s[2])/EC*b;if(t.applyImpulse([x*c,0,S*c]),!h&&this.grounded&&t.applyImpulse([-s[0]*OC*c,0,-s[2]*OC*c]),f!==null&&f<l*2){let e=kC*(l-f)-s[1]*AC;t.applyImpulse([0,e*c,0])}if(this.grounded&&JC(r,this.jumpAction)){let e=this.jumpVelocity*(1+(this.sprintJumpMultiplier-1)*_);t.linearVelocity=[s[0],e,s[2]],this.grounded=!1}s[1]<MC?t.gravityScale=0:s[1]<0&&!this.grounded?t.gravityScale=jC:t.gravityScale=1,this.view===`side`&&Math.abs(o[2])>.01&&(t.position=[t.position[0]??0,t.position[1]??0,0]);let C=zx(this.grounded,h?_:0);if(C!==this.state){this.state=C;let e=this.animations[C];if(e&&this.skinPath!==``){let t=this.getNodeOrNull(this.skinPath);t&&`animation`in t&&(t.animation=e)}this.emit(`movementStateChanged`,C)}if(h&&this.skinPath!==``){let t=this.getNodeOrNull(this.skinPath);if(t){let n=Math.atan2(p,m)*PC+this.skinYawOffset,r=t.rotation[1]??0,i=(n-r+540)%360-180,a=this.turnSpeed*e*PC;Math.abs(i)>a&&(i=Math.sign(i)*a),t.rotation=[t.rotation[0]??0,r+i,t.rotation[2]??0]}}}update(e){let t=this.tree?.engine?.input;if(!t)return;if(this.mouseLook){let e=t.pointerDelta();this.yaw-=e.x*NC,this.pitch=KC(this.pitch+e.y*NC,-this.pitchMax,-this.pitchMin);let n=t.wheelDelta();n!==0&&this.zoomMax>this.zoomMin&&(this.camDistance=KC(this.camDistance+n*NC,this.zoomMin,this.zoomMax))}let n=this.findCamera();if(!n)return;let r=this.parent instanceof Zp?this.parent:null;if(!r)return;let i=qC(r),a=this.view===`free`?11:1e3,o=1-Math.exp(-a*e),s=this.pivot??[i[0],i[1],i[2]];this.pivot=s,s[0]+=(i[0]-s[0])*o,s[1]+=(i[1]-s[1])*o,s[2]+=(i[2]-s[2])*o;let c=Px(this.view,s,this.eyeHeight,this.yaw,this.pitch,this.camDistance),l=[s[0],s[1]+this.eyeHeight,s[2]],u=[c.position[0],c.position[1],c.position[2]];if(this.cameraCollision&&this.view!==`firstPerson`){let e=r._physics3d;e&&(u=Fx(l,u,(t,n,i)=>e.castSphere(t,n,RC,i,r,{staticOnly:!0})?.distance??null,FC,IC),u=Ix(u,(t,n)=>e.castRay(t,[0,-1,0],n,r,{staticOnly:!0})?.distance??null,LC))}let d=this.view===`firstPerson`?1e3:this.camLerp,f=1-Math.exp(-d*e),p=n.position;n.position=[(p[0]??0)+(u[0]-(p[0]??0))*f,(p[1]??0)+(u[1]-(p[1]??0))*f,(p[2]??0)+(u[2]-(p[2]??0))*f],this.view===`free`?(HC.set(n.position[0]??0,n.position[1]??0,n.position[2]??0),UC.set(l[0],l[1],l[2]),VC.lookAt(HC,UC,WC),BC.setFromRotationMatrix(VC),zC.setFromQuaternion(BC,`XYZ`)):(zC.set(c.rotation[0],c.rotation[1],c.rotation[2],`YXZ`),BC.setFromEuler(zC),zC.setFromQuaternion(BC,`XYZ`)),n.rotation=[zC.x*PC,zC.y*PC,zC.z*PC]}pivot=null;cameraCache=null;findCamera(){if(this.cameraCache?.tree===this.tree&&this.cameraCache.current)return this.cameraCache;this.cameraCache=null;let e=this.tree?.root;if(!e)return null;let t=e=>{if(!this.cameraCache){if(e instanceof TC&&e.current){this.cameraCache=e;return}for(let n of e.children)t(n)}};return t(e),this.cameraCache}};function KC(e,t,n){return Math.min(n,Math.max(t,e))}function qC(e){let t=0,n=0,r=0;for(let i=e;i&&i instanceof qp;i=i.parent)t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0;return[t,n,r]}function JC(e,t){try{return e.isPressed(t)}catch{return!1}}var YC=.15,XC=.7,ZC=.5,QC=.7,$C=.5;function ew(e,t,n=3){let r=0,i=1,a=1,o=.65;for(let s=0;s<n;s++){let n=e*a,s=t*a,c=Math.sin(n*.1+s*.2)*.5+.5,l=Math.cos(n*.3+s*.1)*.5+.5,u=Math.sin((n+s)*.15)*.5+.5,d=Math.cos(n*n*.01+s*.2)*.5+.5,f=c*l*.7+u*d*.3;r+=f*i,i*=o,a*=2}return r/((1-o**n)/(1-o))}function tw(e,t){let n=ew(e*YC,t*YC,4),r=ew(e*YC*.2,t*YC*.2,2);return n>ZC-XC*.5-r*$C}var nw=.9;function rw(e,t,n){let r=(Math.imul(e,2246822507)^Math.imul(t,3266489909)^Math.imul(n+1,668265263))>>>0;return r=Math.imul(r^r>>>15,739982445)>>>0,r=Math.imul(r^r>>>12,695872825)>>>0,r^=r>>>15,(r>>>0)/4294967296}function iw(e,t,n=nw){let r=Math.floor(e/n),i=Math.floor(t/n),a=1/0,o=r,s=i;for(let c=-1;c<=1;c++)for(let l=-1;l<=1;l++){let u=r+l,d=i+c,f=(u+rw(u,d,0))*n,p=(d+rw(u,d,1))*n,m=(e-f)*(e-f)+(t-p)*(t-p);m<a&&(a=m,o=u,s=d)}return{id:Math.imul(o,2654435761)^Math.imul(s,2246822519)|0,hue:rw(o,s,2)*2-1,leanDir:rw(o,s,3)*Math.PI*2,lean:rw(o,s,4)}}function aw(e,t,n,r){let i=e*r,a=t*r,o=Math.floor(i),s=Math.floor(a),c=i-o,l=a-s,u=c*c*(3-2*c),d=l*l*(3-2*l),f=rw(o,s,n),p=rw(o+1,s,n),m=rw(o,s+1,n),h=rw(o+1,s+1,n),g=f+(p-f)*u;return g+(m+(h-m)*u-g)*d}var ow=[.55,1.7],sw=.17,cw=.23,lw=.28;function uw(e,t,n){let r=aw(e,t,n^6877377|0,sw),i=r*r*(3-2*r);return ow[0]+(ow[1]-ow[0])*i}function dw(e,t,n){return aw(e,t,n^3001105|0,cw)}function fw(e,t,n){let r=aw(e,t,n^7840757|0,lw)*.72+aw(e,t,n^1688295|0,lw*3.1)*.28,i=Math.min(1,Math.max(0,(r-.18)/.64));return i*i*(3-2*i)}function pw(e){let{seed:t,areaX:n,areaZ:r,count:i,density:a}=e,o=new b(t),s=n/2,c=r/2,l=[],u=Math.floor(i*QC);for(let e=0;e<u&&l.length<i;e++){let e=o.range(-s,s),t=o.range(-c,c),n=o.next()<.3,r=tw(e,t);if(!n&&!r&&o.next()>.15)continue;let i=o.next()*Math.PI*2,a=.5+o.next()*.7,u=r?a*(1+o.next()*.2):a*(.9+o.next()*.2);l.push({x:e,z:t,rotY:i,scale:u})}let d=Math.min(3,Math.max(1,a*10)),f=Math.ceil(Math.sqrt(i*d)),p=n/f,m=r/f,h=Math.floor((i-l.length)*.8),g=0;for(let e=0;e<f&&l.length<i;e++)for(let t=0;t<f&&l.length<i;t++){let i=t/f*n-s+p/2,a=e/f*r-c+m/2,u=i+(o.next()-.5)*p*1.5,d=a+(o.next()-.5)*m*1.5;if(u<-s||u>s||d<-c||d>c)continue;let _=tw(u,d);if(g<h){if(!_&&o.next()>.05)continue}else if(_){if(o.next()>.2)continue}else if(o.next()>.4)continue;if(o.next()<.2)continue;let v=o.next()*Math.PI*2,y=_?.5:.3;l.push({x:u,z:d,rotY:v,scale:.5+o.next()*y}),g++}for(;l.length<i;)l.push({x:o.range(-s,s),z:o.range(-c,c),rotY:o.next()*Math.PI*2,scale:.4+o.next()*.6});return l.sort((e,t)=>t.z-e.z),l}var mw=[`daisy`,`cosmos`,`bellflower`],hw={daisy:{petals:8,blooms:3,leaves:3,petalLength:.1,petalWidth:.052,cupDeg:16,nodDeg:14,centerRadius:.024,centerColor:`#e0a72e`},cosmos:{petals:8,blooms:2,leaves:2,petalLength:.12,petalWidth:.064,cupDeg:26,nodDeg:18,centerRadius:.023,centerColor:`#d2941f`},bellflower:{petals:5,blooms:3,leaves:2,petalLength:.088,petalWidth:.058,cupDeg:46,nodDeg:52,centerRadius:.015,centerColor:`#cfe06a`}},gw=[1,.78,.62],_w=[0,.07,.11],vw=[.6,2.7,4.9],yw=.07,bw=.011,xw=.17,Sw=.05,Cw=[.12,.2,.28],ww=new G(`#3e6a26`),Tw=new G(`#548331`);function Ew(e){let t=hw[e],n=new Dw(!0),r=new Dw(!1),i=new G(t.centerColor);for(let e=0;e<t.blooms;e++){let a=gw[e],o=vw[e],s=_w[e]*Math.cos(o),c=_w[e]*Math.sin(o),l=yw*Math.cos(o),u=yw*Math.sin(o),d=new H(s,0,c),f=new H(s+l,a,c+u),p=new H(s+l*.25,a*.55,c+u*.25);n.addStem(d,p,f,bw,ww);let m=t.nodDeg*Math.PI/180,h=new H(Math.sin(m)*Math.cos(o),Math.cos(m),Math.sin(m)*Math.sin(o)),g=new H(-Math.sin(o),0,Math.cos(o)),_=new H().crossVectors(h,g).normalize(),v=f.clone().addScaledVector(h,.012),y=t.cupDeg*Math.PI/180,b=e*.45;for(let e=0;e<t.petals;e++){let n=e/t.petals*Math.PI*2+b,i=g.clone().multiplyScalar(Math.cos(n)).addScaledVector(_,Math.sin(n)).normalize();r.addPetal(v,i,h,t,y)}n.addDisc(v.clone().addScaledVector(h,.004),g,_,t.centerRadius,i)}for(let e=0;e<t.leaves;e++){let t=Cw[e%Cw.length],r=1.1+e*2.3;n.addLeaf(new H(0,t,0),r,Tw)}return{structure:n.build(),petals:r.build()}}var Dw=class{positions=[];colors;indices=[];constructor(e){this.colors=e?[]:null}vertex(e,t){let n=this.positions.length/3;return this.positions.push(e.x,e.y,e.z),this.colors&&t&&this.colors.push(t.r,t.g,t.b),n}addStem(e,t,n,r,i){for(let a of[0,Math.PI/2]){let o=new H(Math.cos(a),0,Math.sin(a)),s=[];for(let a=0;a<=5;a++){let c=a/5,l=1-c,u=new H(l*l*e.x+2*l*c*t.x+c*c*n.x,l*l*e.y+2*l*c*t.y+c*c*n.y,l*l*e.z+2*l*c*t.z+c*c*n.z),d=r/2*(1-.4*c);s.push(this.vertex(u.clone().addScaledVector(o,-d),i),this.vertex(u.clone().addScaledVector(o,d),i))}for(let e=0;e<5;e++){let t=s[e*2],n=s[e*2+1],r=s[e*2+2],i=s[e*2+3];this.indices.push(t,n,r,r,n,i)}}}addPetal(e,t,n,r,i){let a=new H().crossVectors(n,t).normalize(),o=r.centerRadius*.85,s=Math.sin(i)*r.petalLength*.45,c=Math.sin(i)*r.petalLength*.95,l=Math.cos(i),u=e.clone().addScaledVector(t,o),d=o+r.petalLength*l*.55,f=o+r.petalLength*l,p=e.clone().addScaledVector(t,d).addScaledVector(a,r.petalWidth/2).addScaledVector(n,s),m=e.clone().addScaledVector(t,d).addScaledVector(a,-r.petalWidth/2).addScaledVector(n,s),h=e.clone().addScaledVector(t,f).addScaledVector(n,c),g=this.vertex(u,null),_=this.vertex(p,null),v=this.vertex(m,null),y=this.vertex(h,null);this.indices.push(g,_,y,g,y,v)}addDisc(e,t,n,r,i){let a=this.vertex(e,i),o=[];for(let a=0;a<6;a++){let s=a/6*Math.PI*2;o.push(this.vertex(e.clone().addScaledVector(t,Math.cos(s)*r).addScaledVector(n,Math.sin(s)*r),i))}for(let e=0;e<6;e++)this.indices.push(a,o[e],o[(e+1)%6])}addLeaf(e,t,n){let r=new H(Math.cos(t),0,Math.sin(t)),i=new H(-Math.sin(t),0,Math.cos(t)),a=Math.sin(.6),o=Math.cos(.6),s=e.clone().addScaledVector(r,xw*o*.5).add(new H(0,xw*a*.5,0)),c=e.clone().addScaledVector(r,xw*o).add(new H(0,xw*a*.8,0)),l=this.vertex(e,n),u=this.vertex(s.clone().addScaledVector(i,Sw/2),n),d=this.vertex(s.clone().addScaledVector(i,-.05/2),n),f=this.vertex(c,n);this.indices.push(l,u,f,l,f,d)}build(){let e=new q;return e.setAttribute(`position`,new K(new Float32Array(this.positions),3)),this.colors&&e.setAttribute(`color`,new K(new Float32Array(this.colors),3)),e.setIndex(this.indices),e.computeVertexNormals(),e}},Ow=2.6;function kw(e){let{seed:t,areaX:n,areaZ:r,count:i,clustering:a}=e,o=new b(t),s=n/2,c=r/2,l=1-.74*Math.min(Math.max(a,0),1),u=[];for(let e=0;e<i*16&&u.length<i;e++){let e=o.range(-s,s),t=o.range(-c,c),n=iw(e,t,Ow);n.lean>l&&o.next()>.06||u.push({x:e,z:t,rotY:o.next()*Math.PI*2,scale:.75+o.next()*.5,variety01:(n.hue+1)/2,color01:n.leanDir/(Math.PI*2)})}return u}var Aw=1.05,jw=1;function Mw(e,t=jw){e.computeBoundingSphere();let n=e.boundingSphere;n&&n.radius>=0&&(n.radius=n.radius*Aw+t),e.frustumCulled=!0}function Nw(e){let t=0,n=0,r=0;for(let i=e;i;i=i.parent)i instanceof qp&&(t+=i.position[0]??0,n+=i.position[1]??0,r+=i.position[2]??0);return[t,n,r]}function Pw(e,t){if(t!==``){let n=e.getNodeOrNull(t);return n instanceof yS?n:null}return Fw(e.getRoot())}function Fw(e){if(e instanceof yS)return e;for(let t of e.children){let e=Fw(t);if(e)return e}return null}var Iw={lush:2.2,sparse:.35,none:0},Lw=[`lush`,`sparse`,`none`];function Rw(e){if(typeof e==`number`)return e;let t=Iw[e];if(t===void 0)throw new y(`BAD_FORMAT`,`Flowers3D density must be one of [${Lw.join(`, `)}] or a number (plants/m²), got '${e}'.`,{prop:`density`,validOptions:Lw});return t}var zw=1e4,Bw=[`#f5f1e2`,`#e9d052`,`#8d7bd9`],Vw=/^#[0-9a-fA-F]{6}$/,Hw=class extends qp{static typeName=`Flowers3D`;static props={density:{default:`sparse`,options:Lw},area:{default:[20,20]},seed:{default:1},varieties:{default:[]},palette:{default:[]},height:{default:.45},clustering:{default:.6},sway:{default:.5},drape:{default:null},terrain:{default:``}};density=`sparse`;area=[20,20];seed=1;varieties=[];palette=[];height=.45;clustering=.6;sway=.5;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(typeof t.density==`string`)Rw(t.density);else if(!(Number.isFinite(t.density)&&t.density>=0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' density must be one of [${Lw.join(`, `)}] or a number >= 0 (plants/m²), got ${t.density}.`,{prop:`density`,validOptions:Lw});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});let n=Math.floor((t.area[0]??0)*(t.area[1]??0)*Rw(t.density));if(n>zw)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' blows the plant budget: area ${t.area[0]}×${t.area[1]} m × density ${Rw(t.density)} = ${n} plants > ${zw}. Lower the density or split the field into multiple nodes.`,{prop:`density`});if(!Array.isArray(t.varieties)||new Set(t.varieties).size!==t.varieties.length||!t.varieties.every(e=>mw.includes(e)))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' varieties must be a unique subset of [${mw.join(`, `)}] ([] = all three), got ${JSON.stringify(t.varieties)}.`,{prop:`varieties`,validOptions:[...mw]});if(!Array.isArray(t.palette)||!t.palette.every(e=>typeof e==`string`&&Vw.test(e)))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' palette must be an array of '#rrggbb' head colors ([] = white/yellow/violet), got ${JSON.stringify(t.palette)}.`,{prop:`palette`});if(!(t.height>0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' height must be > 0 meters, got ${t.height}.`,{prop:`height`});if(!(t.clustering>=0)||!(t.clustering<=1))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' clustering must be in [0, 1] (0 uniform … 1 tight patches), got ${t.clustering}.`,{prop:`clustering`});if(!(t.sway>=0))throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' sway must be >= 0, got ${t.sway}.`,{prop:`sway`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Flowers3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`})}time=0;field=null;varietyMeshes=[];fieldKey=``;timeUniform={value:0};swayUniform={value:.5};_createObject3D(){return new Qi}_varietyMeshes(){return this.rebuildIfNeeded(),this.varietyMeshes}update(e){this.time+=e,this.timeUniform.value=this.time}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded(),this.swayUniform.value=this.sway}rebuildIfNeeded(){this.field||(this.field=new Qi,this._ensureObject3D().add(this.field));let e=JSON.stringify([this.density,this.area,this.seed,this.varieties,this.palette,this.height,this.clustering,this.drape,this.terrain]);e!==this.fieldKey&&(this.fieldKey=e,this.disposeMeshes(),this.resolveDrape(),this.buildField())}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=Pw(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Nw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Flowers3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildField(){let e=Rw(this.density),t=Math.min(Math.floor((this.area[0]??0)*(this.area[1]??0)*e),zw);if(t<=0)return;let n=kw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:t,clustering:this.clustering}),r=this.varieties.length>0?this.varieties:mw,i=r.map(()=>[]);for(let e of n)i[Math.min(Math.floor(e.variety01*r.length),r.length-1)].push(e);let a=this.palette.length>0?this.palette:Bw,o=new b(this.seed+15797765);for(let e=0;e<r.length;e++){let t=i[e];if(t.length===0)continue;let{structure:n,petals:s}=Ew(r[e]),c=new nc({vertexColors:!0,roughness:1,side:2}),l=new nc({roughness:.85,side:2});Uw(c,this.timeUniform,this.swayUniform),Uw(l,this.timeUniform,this.swayUniform);let u=new rs(n,c,t.length),d=new rs(s,l,t.length);u.receiveShadow=!0,d.receiveShadow=!0;for(let e=0;e<t.length;e++){let n=t[e];Kw.set(n.x,this.bedY(n.x,n.z),n.z),qw.setFromAxisAngle(Ww,n.rotY),Jw.setScalar(this.height*n.scale),Gw.compose(Kw,qw,Jw),u.setMatrixAt(e,Gw),d.setMatrixAt(e,Gw);let r=Math.min(Math.floor(n.color01*a.length),a.length-1);Yw.set(a[r]).offsetHSL(o.range(-.02,.02),0,o.range(-.05,.05)),d.setColorAt(e,Yw),Yw.setRGB(1,1,1).offsetHSL(o.range(-.02,.02),0,o.range(-.06,.04)),u.setColorAt(e,Yw)}u.instanceMatrix.needsUpdate=!0,d.instanceMatrix.needsUpdate=!0,u.instanceColor&&(u.instanceColor.needsUpdate=!0),d.instanceColor&&(d.instanceColor.needsUpdate=!0),Mw(u),Mw(d),this.varietyMeshes.push({variety:r[e],structure:u,petals:d}),this.field.add(u),this.field.add(d)}}disposeMeshes(){for(let{structure:e,petals:t}of this.varietyMeshes)for(let n of[e,t])n.removeFromParent(),n.geometry.dispose(),n.material.dispose(),n.dispose();this.varietyMeshes=[]}free(){this.disposeMeshes(),this.field=null,super.free()}};function Uw(e,t,n){e.userData.sway=!0,e.userData.timeUniform=t,e.onBeforeCompile=e=>{e.uniforms.uFlowerTime=t,e.uniforms.uFlowerSway=n,e.vertexShader=`uniform float uFlowerTime;\nuniform float uFlowerSway;\n${e.vertexShader}`.replace(`#include <project_vertex>`,`
|
|
6898
6927
|
vec4 mvPosition = vec4(transformed, 1.0);
|
|
6899
6928
|
#ifdef USE_INSTANCING
|
|
6900
6929
|
mvPosition = instanceMatrix * mvPosition;
|
|
@@ -6907,7 +6936,7 @@ normal = perturbSplatNormal(normal, vViewPosition, vUvSplat, blendedNormalSample
|
|
|
6907
6936
|
mvPosition.z += uFlowerSway * swayW * 0.020 * cos(uFlowerTime * 1.3 + swayPhase * 1.4);
|
|
6908
6937
|
mvPosition = modelViewMatrix * mvPosition;
|
|
6909
6938
|
gl_Position = projectionMatrix * mvPosition;
|
|
6910
|
-
`)},e.customProgramCacheKey=()=>`incanto-flowers-sway`}var
|
|
6939
|
+
`)},e.customProgramCacheKey=()=>`incanto-flowers-sway`}var Ww=new H(0,1,0),Gw=new W,Kw=new H,qw=new V,Jw=new H,Yw=new G;function Xw(e,t,n=4){let r=t.areaX/2,i=t.areaZ/2,a=e.filter(e=>Math.abs(e.x-t.x)<=r+e.radius&&Math.abs(e.z-t.z)<=i+e.radius);return a.sort((e,n)=>(e.x-t.x)**2+(e.z-t.z)**2-((n.x-t.x)**2+(n.z-t.z)**2)),a.slice(0,n)}var Zw=[1,.78,.42];function Qw(e){let t=new Float32Array(21),n=new Float32Array(14);for(let r=0;r<3;r++){let i=r/3,a=Zw[r]*e/2;for(let e=0;e<2;e++){let o=r*2+e;t[o*3]=e===0?-a:a,t[o*3+1]=i,t[o*3+2]=0,n[o*2]=e,n[o*2+1]=i}}t[18]=0,t[19]=1,t[20]=0,n[12]=.5,n[13]=1;let r=new q;return r.setAttribute(`position`,new K(t,3)),r.setAttribute(`uv`,new K(n,2)),r.setIndex([0,1,2,2,1,3,2,3,4,4,3,5,4,5,6]),r}function $w(e){let t=new Float32Array([0,1.025,0,-e,.985,0,0,.985,e,e,.985,0,0,.985,-e]),n=new q;return n.setAttribute(`position`,new K(t,3)),n.setIndex([0,1,2,0,2,3,0,3,4,0,4,1]),n.computeVertexNormals(),n}var eT=`
|
|
6911
6940
|
uniform float time;
|
|
6912
6941
|
uniform float windStrength;
|
|
6913
6942
|
uniform float grassHeight;
|
|
@@ -6985,7 +7014,7 @@ void main() {
|
|
|
6985
7014
|
gl_Position = projectionMatrix * mvPosition;
|
|
6986
7015
|
#include <fog_vertex>
|
|
6987
7016
|
}
|
|
6988
|
-
`,
|
|
7017
|
+
`,tT=`
|
|
6989
7018
|
uniform float time;
|
|
6990
7019
|
varying vec2 vUv;
|
|
6991
7020
|
varying float vHeight;
|
|
@@ -7143,7 +7172,7 @@ void main() {
|
|
|
7143
7172
|
// patches melt into the same fog as the terrain instead of staying vivid.
|
|
7144
7173
|
#include <fog_fragment>
|
|
7145
7174
|
}
|
|
7146
|
-
`,
|
|
7175
|
+
`,nT=`
|
|
7147
7176
|
// incanto atmosphere: standard fog + shadow-receive chunks — both compile
|
|
7148
7177
|
// out unless the scene declares fog / a light casts (USE_FOG, USE_SHADOWMAP)
|
|
7149
7178
|
#include <common>
|
|
@@ -7247,7 +7276,7 @@ void main() {
|
|
|
7247
7276
|
#include <fog_vertex>
|
|
7248
7277
|
#include <shadowmap_vertex>
|
|
7249
7278
|
}
|
|
7250
|
-
`,
|
|
7279
|
+
`,rT=`
|
|
7251
7280
|
// incanto atmosphere: fog + shadow-receive (grass RECEIVES, never casts —
|
|
7252
7281
|
// per-blade casting would double the vertex bill for invisible gain).
|
|
7253
7282
|
// receiveShadow is declared by lights_pars_begin in BUILT-IN materials; a
|
|
@@ -7319,7 +7348,7 @@ void main() {
|
|
|
7319
7348
|
#include <colorspace_fragment>
|
|
7320
7349
|
#include <fog_fragment>
|
|
7321
7350
|
}
|
|
7322
|
-
`,
|
|
7351
|
+
`,iT=.4;function aT(e){if(typeof e.radius==`number`)return e.radius;let t=e.size;if(Array.isArray(t)){let e=typeof t[0]==`number`?t[0]:0,n=typeof t[2]==`number`?t[2]:0;if(e>0||n>0)return Math.max(e,n)/2}return iT}function oT(e){let t=typeof e.radius==`number`?e.radius:0,n=typeof e.height==`number`?e.height:0;if(n>0)return n/2+t;if(t>0)return t;let r=e.size;return Array.isArray(r)&&typeof r[1]==`number`?r[1]/2:iT}function sT(e,t){t.length=0,cT(e,t)}function cT(e,t){if(e instanceof Qp||e instanceof Zp){let[n,r,i]=Nw(e);t.push({x:n,y:r,z:i,radius:aT(e.collider),footY:r-oT(e.collider)})}for(let n of e.children)cT(n,t)}function lT(e){let t=e.tree;if(!t){let t=[];return sT(e.getRoot(),t),t}let n=t._frameScratch;if(n&&n.frameId===t.frameId)return n.bodies;let r=n?.bodies??[],i=t.root;return i?sT(i,r):r.length=0,t._frameScratch={frameId:t.frameId,bodies:r},r}var uT=6,dT=512;function fT(e,t=`grass`){if(t===`fern`)return pT(e);let n=new b(e+28919),r=[];for(let e=0;e<180;e++){let e=.5+(n.next()+n.next()-1)*.17,t=(e>=.5?1:-1)*n.range(.04,.5)+n.range(-.1,.1),i=n.range(.45,1),a=Math.min(1,Math.max(0,e+t*(1.5-.9*i)));r.push({rootX:e,tipX:a,height:i,width:n.range(.0028,.0085),shade:n.range(.45,.98),bow:t*n.range(.25,.6)})}return r}function pT(e){let t=new b(e+65121),n=[];for(let e=0;e<56;e++){let r=.5+(t.next()+t.next()-1)*.1,i=(e%2==0?1:-1)*t.range(.12,.55)+t.range(-.06,.06),a=t.range(.32,.85),o=Math.min(1,Math.max(0,r+i*(1.6-.7*a)));n.push({rootX:r,tipX:o,height:a,width:t.range(.014,.03),shade:t.range(.4,.85),bow:i*t.range(.5,.85)})}return n}function mT(e,t=`grass`){let n=e.shade,r=Math.max(.3,e.shade*.62);if(t===`fern`){let e=[{offset:0,gray:r,alpha:0}],t=.14;for(let i=0;i<uT;i++){let a=t+(1-t)*i/uT,o=t+(1-t)*(i+1)/uT,s=r+(n-r)*((a+o)/2);e.push({offset:a+(o-a)*.12,gray:s,alpha:1}),e.push({offset:a+(o-a)*.74,gray:s,alpha:1}),i<uT-1&&e.push({offset:a+(o-a)*.92,gray:s,alpha:.2})}return e[e.length-1].offset<1&&e.push({offset:1,gray:n,alpha:1}),e}return[{offset:0,gray:r,alpha:0},{offset:.22,gray:r,alpha:1},{offset:1,gray:n,alpha:1}]}function hT(e,t=`grass`){if(typeof document>`u`)return null;let n=dT,r=document.createElement(`canvas`);r.width=n,r.height=n;let i=r.getContext(`2d`);if(!i)return null;i.clearRect(0,0,n,n);for(let r of fT(e,t)){let e=r.rootX*n,a=n,o=r.tipX*n,s=(1-r.height)*n,c=(e+o)/2+r.bow*n,l=(a+s)/2,u=Math.max(r.width*n,.75);i.beginPath(),i.moveTo(e-u,a),i.quadraticCurveTo(c-u*.55,l,o,s),i.quadraticCurveTo(c+u*.55,l,e+u,a),i.closePath();let d=i.createLinearGradient(e,a,o,s);for(let e of mT(r,t)){let t=Math.round(e.gray*255);d.addColorStop(e.offset,`rgba(${t},${t},${t},${e.alpha})`)}i.fillStyle=d,i.fill()}let a=new Ps(r);return a.colorSpace=dr,a}var gT=.08,_T=.5,vT=12,yT=`
|
|
7323
7352
|
// GLSL Simplex Noise 3D — https://github.com/ashima/webgl-noise (MIT)
|
|
7324
7353
|
vec3 ezMod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
|
7325
7354
|
vec4 ezMod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
|
@@ -7371,9 +7400,9 @@ float ezSimplex3(vec3 v) {
|
|
|
7371
7400
|
m = m * m;
|
|
7372
7401
|
return 42.0 * dot(m * m, vec4(dot(g0, x0), dot(g1, x1), dot(g2, x2), dot(g3, x3)));
|
|
7373
7402
|
}
|
|
7374
|
-
`;function
|
|
7403
|
+
`;function bT(e){return`#include <lights_fragment_maps>
|
|
7375
7404
|
iblIrradiance *= ${e.toFixed(3)};
|
|
7376
|
-
radiance *= ${e.toFixed(3)};`}function
|
|
7405
|
+
radiance *= ${e.toFixed(3)};`}function xT(e,t){e.userData.envCut=t,e.onBeforeCompile=e=>{e.fragmentShader=e.fragmentShader.replace(`#include <lights_fragment_maps>`,bT(t))},e.customProgramCacheKey=()=>`incanto-env-cut-${t.toFixed(3)}`}function ST(e,t,n=1,r){e.userData.sway=!0,e.userData.timeUniform=t,e.userData.envCut=n,r&&(e.userData.leafFade=r);let i=r?`uniform float uLeafFadeStart;
|
|
7377
7406
|
uniform float uLeafFadeEnd;
|
|
7378
7407
|
attribute vec3 anchor;
|
|
7379
7408
|
`:``,a=r?`
|
|
@@ -7383,16 +7412,16 @@ attribute vec3 anchor;
|
|
|
7383
7412
|
#endif
|
|
7384
7413
|
vec4 ezAnchorWorld = modelMatrix * ezAnchor;
|
|
7385
7414
|
float ezFade = step(uLeafFadeStart + 1e-4, uLeafFadeEnd) * smoothstep(uLeafFadeStart, max(uLeafFadeEnd, uLeafFadeStart + 1e-4), distance(cameraPosition, ezAnchorWorld.xyz));
|
|
7386
|
-
mvPosition.xyz = mix(mvPosition.xyz, ezAnchor.xyz, ezFade);`:``;e.onBeforeCompile=e=>{e.uniforms.uTreeTime=t,r&&(e.uniforms.uLeafFadeStart=r.start,e.uniforms.uLeafFadeEnd=r.end),e.vertexShader=`uniform float uTreeTime;\n${i}${e.vertexShader}`.replace(`void main() {`,`${
|
|
7415
|
+
mvPosition.xyz = mix(mvPosition.xyz, ezAnchor.xyz, ezFade);`:``;e.onBeforeCompile=e=>{e.uniforms.uTreeTime=t,r&&(e.uniforms.uLeafFadeStart=r.start,e.uniforms.uLeafFadeEnd=r.end),e.vertexShader=`uniform float uTreeTime;\n${i}${e.vertexShader}`.replace(`void main() {`,`${yT}\nvoid main() {`).replace(`#include <project_vertex>`,`
|
|
7387
7416
|
vec4 mvPosition = vec4(transformed, 1.0);
|
|
7388
7417
|
#ifdef USE_INSTANCING
|
|
7389
7418
|
mvPosition = instanceMatrix * mvPosition;
|
|
7390
7419
|
#endif
|
|
7391
|
-
float windOffset = 2.0 * 3.14 * ezSimplex3(mvPosition.xyz / ${
|
|
7392
|
-
mvPosition.xyz += uv.y * ${
|
|
7393
|
-
0.5 * sin(uTreeTime * ${
|
|
7394
|
-
0.3 * sin(2.0 * uTreeTime * ${
|
|
7395
|
-
0.2 * sin(5.0 * uTreeTime * ${
|
|
7420
|
+
float windOffset = 2.0 * 3.14 * ezSimplex3(mvPosition.xyz / ${vT.toFixed(1)});
|
|
7421
|
+
mvPosition.xyz += uv.y * ${gT.toFixed(3)} * vec3(1.0, 0.0, 1.0) * (
|
|
7422
|
+
0.5 * sin(uTreeTime * ${_T.toFixed(2)} + windOffset) +
|
|
7423
|
+
0.3 * sin(2.0 * uTreeTime * ${_T.toFixed(2)} + 1.3 * windOffset) +
|
|
7424
|
+
0.2 * sin(5.0 * uTreeTime * ${_T.toFixed(2)} + 1.5 * windOffset)
|
|
7396
7425
|
);${a}
|
|
7397
7426
|
mvPosition = modelViewMatrix * mvPosition;
|
|
7398
7427
|
gl_Position = projectionMatrix * mvPosition;
|
|
@@ -7406,18 +7435,18 @@ attribute vec3 anchor;
|
|
|
7406
7435
|
if (diffuseColor.a < ezCutoff) discard;
|
|
7407
7436
|
#endif
|
|
7408
7437
|
#endif
|
|
7409
|
-
`).replace(`#include <lights_fragment_maps>`,
|
|
7438
|
+
`).replace(`#include <lights_fragment_maps>`,bT(n))},e.customProgramCacheKey=r?()=>`incanto-eztree-leaf-wind-v5-fade-${n.toFixed(3)}`:()=>`incanto-eztree-leaf-wind-v4-${n.toFixed(3)}`}var CT=40,wT=1;function TT(e,t,n){e.userData.sway=!0,e.userData.timeUniform=t,e.userData.strengthUniform=n,e.onBeforeCompile=e=>{e.uniforms.uTuftTime=t,e.uniforms.uTuftWind=n,e.vertexShader=`uniform float uTuftTime;\nuniform float uTuftWind;\n${e.vertexShader}`.replace(`void main() {`,`${yT}\nvoid main() {`).replace(`#include <project_vertex>`,`
|
|
7410
7439
|
vec4 mvPosition = vec4(transformed, 1.0);
|
|
7411
7440
|
#ifdef USE_INSTANCING
|
|
7412
7441
|
mvPosition = instanceMatrix * mvPosition;
|
|
7413
7442
|
#endif
|
|
7414
|
-
float tuftPhase = 6.2832 * ezSimplex3(vec3(mvPosition.xz / ${
|
|
7443
|
+
float tuftPhase = 6.2832 * ezSimplex3(vec3(mvPosition.xz / ${CT.toFixed(1)}, 0.0));
|
|
7415
7444
|
mvPosition.xz += uv.y * uTuftWind *
|
|
7416
|
-
sin(uTuftTime * ${
|
|
7417
|
-
cos(uTuftTime * ${(1.4*
|
|
7445
|
+
sin(uTuftTime * ${wT.toFixed(1)} + tuftPhase) *
|
|
7446
|
+
cos(uTuftTime * ${(1.4*wT).toFixed(1)} + tuftPhase) * vec2(1.0, 0.8);
|
|
7418
7447
|
mvPosition = modelViewMatrix * mvPosition;
|
|
7419
7448
|
gl_Position = projectionMatrix * mvPosition;
|
|
7420
|
-
`)},e.customProgramCacheKey=()=>`incanto-tuft-wind`}var gT=[`grass`,`flowers`,`reeds`],_T=[`blades`,`simple`,`mesh`,`tufts`],vT=[`grass`,`fern`],yT={grass:.08,flowers:.14,reeds:.05},bT=[.75,1.25],xT=.05,ST=.25,CT=2e5,wT=8,TT=.05,ET=.38,DT=[.75,1.3],OT=.1,kT=.42,AT=[.6,1.6],jT=.8,MT=.9,NT=.04,PT=[`#f5f1e2`,`#e9d052`,`#8d7bd9`],FT=1/3,IT=1.5,LT=1.45,RT=.4,zT=.13,BT=[.85,1.2],VT=[.8,1.3],HT=`#b3a24e`,UT=.8,WT=.5,GT=class e extends qp{static typeName=`Foliage3D`;static props={kind:{default:`grass`,options:gT},style:{default:`mesh`,options:_T},tuftStyle:{default:`grass`,options:vT},area:{default:[20,20]},density:{default:12},maxInstances:{default:5e4},height:{default:.25},colorA:{default:`#4d7232`},colorB:{default:`#9aab55`},groundColor:{default:`#1f3015`},sunDirection:{default:[.5,.8,.3]},fadeStart:{default:60},fadeEnd:{default:90},sway:{default:.6},interaction:{default:!0},coverage:{default:.85},flowers:{default:0},seed:{default:1},drape:{default:null},terrain:{default:``},renderOrder:{default:2}};renderOrder=2;kind=`grass`;style=`mesh`;tuftStyle=`grass`;area=[20,20];density=12;maxInstances=5e4;height=.25;colorA=`#4d7232`;colorB=`#9aab55`;groundColor=`#1f3015`;sunDirection=[.5,.8,.3];fadeStart=60;fadeEnd=90;sway=.6;interaction=!0;coverage=.85;flowers=0;seed=1;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(!gT.includes(t.kind))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' kind must be one of [${gT.join(`, `)}], got '${t.kind}'.`,{prop:`kind`,validOptions:gT});if(!_T.includes(t.style))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' style must be one of [${_T.join(`, `)}], got '${t.style}'.`,{prop:`style`,validOptions:_T});if(!vT.includes(t.tuftStyle))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' tuftStyle must be one of [${vT.join(`, `)}], got '${t.tuftStyle}'.`,{prop:`tuftStyle`,validOptions:vT});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});if(!(t.density>0)||!(t.maxInstances>=1))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' needs density > 0 and maxInstances >= 1, got density ${t.density}, maxInstances ${t.maxInstances}.`,{prop:`density`});if(t.maxInstances>CT)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' maxInstances is capped at ${CT} (got ${t.maxInstances}) — split giant fields into multiple nodes.`,{prop:`maxInstances`});if(!(t.fadeStart>=0)||!(t.fadeEnd>t.fadeStart))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' needs fadeStart >= 0 and fadeEnd > fadeStart (the LOD fade window), got fadeStart ${t.fadeStart}, fadeEnd ${t.fadeEnd}.`,{prop:`fadeStart`});let n=t.sunDirection;if(!Array.isArray(n)||n.length!==3||!n.every(e=>Number.isFinite(e))||Math.hypot(n[0]??0,n[1]??0,n[2]??0)===0)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' sunDirection must be a non-zero [x, y, z] vector, got ${JSON.stringify(n)}.`,{prop:`sunDirection`});if(!(t.coverage>0)||!(t.coverage<=1))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' coverage must be in (0, 1] (carpet fill — 1 is solid, lower carves dirt patches), got ${t.coverage}.`,{prop:`coverage`});if(!(t.flowers>=0)||!(t.flowers<=.2))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' flowers must be in [0, 0.2] (fraction of instances rendered as flower heads — for a whole flower FIELD use kind: 'flowers'), got ${t.flowers}.`,{prop:`flowers`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`})}time=0;pivot=null;meshes=[];bladesMaterial=null;benderSlots=null;pickedBenders=[];fieldKey=``;tuftTime=null;tuftStrength=null;tuftTexture=null;_createObject3D(){return new Qi}get isBlades(){return this.kind===`grass`&&this.style===`blades`}get isMesh(){return this.kind===`grass`&&this.style===`mesh`}get isTufts(){return this.kind===`grass`&&this.style===`tufts`}get isShaderField(){return this.isMesh||this.isBlades}_field(){return this.rebuildIfNeeded(),this.meshes[0]}_fields(){return this.rebuildIfNeeded(),this.meshes}update(e){this.time+=e,this.pickedBenders=this.computeBenders(),this.writeAnimationUniforms()}writeAnimationUniforms(){if(this.isShaderField&&this.bladesMaterial){let e=this.bladesMaterial.uniforms;e.time&&(e.time.value=this.time),e.windStrength&&(e.windStrength.value=this.sway*(this.isMesh?ET:ST));let t=this.benderSlots;if(t)for(let e=0;e<4;e++){let n=this.pickedBenders[e];n?t[e]?.set(n.x,n.y,n.z,n.radius):t[e]?.set(0,0,0,0)}}else this.isTufts&&(this.tuftTime&&(this.tuftTime.value=this.time),this.tuftStrength&&(this.tuftStrength.value=this.sway*zT))}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded();let e=this.pivot;if(this.writeAnimationUniforms(),this.isShaderField){e.matrix.identity();let t=this.bladesMaterial.uniforms;(t.bottomColor?.value).set(this.colorA),(t.topColor?.value).set(this.colorB),this.isMesh&&((t.groundColor?.value).set(this.groundColor),(t.sunDirection?.value).set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),t.fadeStart&&(t.fadeStart.value=this.fadeStart),t.fadeEnd&&(t.fadeEnd.value=this.fadeEnd))}else if(this.isTufts)e.matrix.identity();else if(this.sway>0){let t=Math.sin(this.time*1.7)*xT*this.sway,n=Math.sin(this.time*1.3+1.7)*xT*this.sway*.6;e.matrix.makeShear(0,0,t,n,0,0)}else e.matrix.identity();e.matrixWorldNeedsUpdate=!0}_applySunDirection(t){if(!this.isMesh||!this.bladesMaterial)return;let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this.bladesMaterial.uniforms.sunDirection?.value)?.set(t[0],t[1],t[2])}computeBenders(){if(!this.interaction||!this.isShaderField)return[];let[e,t,n]=Cw(this);this.drape===!0&&!this.drapeTerrain&&this.resolveDrape();let r=this.drapeTerrain,i=[];for(let e of $w(this)){let n=r?r.heightAt(e.x,e.z):t,a=e.footY-n;a<=WT&&a>=-2.5&&i.push({x:e.x,y:e.y,z:e.z,radius:e.radius+UT})}return Bw(i,{x:e,z:n,areaX:this.area[0]??0,areaZ:this.area[1]??0})}rebuildIfNeeded(){this.pivot||(this.pivot=new Qi,this.pivot.matrixAutoUpdate=!1,this._ensureObject3D().add(this.pivot));let e=JSON.stringify([this.kind,this.style,this.tuftStyle,this.area,this.density,this.maxInstances,this.height,this.colorA,this.colorB,this.coverage,this.flowers,this.seed,this.drape,this.terrain]);if(e===this.fieldKey&&this.meshes.length>0)return;this.fieldKey=e,this.disposeMeshes(),this.resolveDrape();let t=this.isMesh?wT:this.isTufts?FT:1,n=Math.min(Math.floor((this.area[0]??0)*(this.area[1]??0)*this.density*t),this.maxInstances);this.isMesh?this.buildMeshField(n):this.isTufts?this.buildTuftField(n):this.isBlades?this.buildBladesField(n):this.buildSimpleField(n);for(let e of this.meshes)Sw(e),this.pivot.add(e)}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=ww(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Cw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Foliage3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildMeshField(e){let t=rw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density*wT}),n=this.coverage>=1?t:t.filter(e=>nw(e.x,e.z,this.seed)<=this.coverage),r=this.flowers>0?Math.floor(n.length*this.flowers):0,i=new Set;for(let e=0;e<r;e++)i.add(Math.floor((e+.5)*n.length/r));let a=n.filter((e,t)=>!i.has(t)),o=n.filter((e,t)=>i.has(t));this.benderSlots=Array.from({length:4},()=>new bi(0,0,0,0));let s=Zs.merge([Y.lights,Y.fog]);Object.assign(s,{time:{value:0},windStrength:{value:this.sway*ET},topColor:{value:new G(this.colorB)},bottomColor:{value:new G(this.colorA)},groundColor:{value:new G(this.groundColor)},sunDirection:{value:new H(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize()},fadeStart:{value:this.fadeStart},fadeEnd:{value:this.fadeEnd},benders:{value:this.benderSlots}}),this.bladesMaterial=new ec({vertexShader:Kw,fragmentShader:qw,uniforms:s,fog:!0,lights:!0,side:2});let c=Hw(TT),l=a.length,u=Math.max(l,1),d=new rs(c,this.bladesMaterial,u);d.count=l,d.receiveShadow=!0;let f=new b(this.seed+5352221),p=new Float32Array(u*4),m=new Float32Array(u),h=new Float32Array(u);for(let e=0;e<l;e++){let t=a[e],n=JC(t.x,t.z),r=ew(t.x,t.z,this.seed),i=(r-.55)/1.15,o=f.range(DT[0],DT[1]),s=this.height*r*(.55+t.scale*.6);ZT.set(t.x,this.bedY(t.x,t.z),t.z),QT.setFromAxisAngle(YT,t.rotY),$T.set(o,s,o),d.setMatrixAt(e,XT.compose(ZT,QT,$T));let c=n.leanDir+f.range(-.6,.6),l=(OT+kT*(.5*n.lean+.5*f.next()))*(1+jT*i);p[e*4]=Math.cos(c)*l,p[e*4+1]=Math.sin(c)*l,p[e*4+2]=f.range(AT[0],AT[1])*(1+MT*i),p[e*4+3]=f.next(),m[e]=n.hue;let u=tw(t.x,t.z,this.seed)*.85+(f.next()-.5)*.3;h[e]=Math.min(1,Math.max(0,u))}c.setAttribute(`aBlade`,new Yo(p,4)),c.setAttribute(`aClumpHue`,new Yo(m,1)),c.setAttribute(`aDry`,new Yo(h,1)),d.instanceMatrix.needsUpdate=!0,this.meshes=[d],o.length>0&&this.meshes.push(this.buildFlowerMesh(o))}buildFlowerMesh(e){let t=new rs(Uw(NT),new nc({roughness:1,side:2}),Math.max(e.length,1));t.count=e.length,t.receiveShadow=!0;let n=new b(this.seed+15797765);for(let r=0;r<e.length;r++){let i=e[r],a=ew(i.x,i.z,this.seed),o=this.height*a*(.85+n.next()*.35);ZT.set(i.x,this.bedY(i.x,i.z),i.z),QT.setFromAxisAngle(YT,i.rotY),$T.set(1,o,1),t.setMatrixAt(r,XT.compose(ZT,QT,$T));let s=n.next(),c=PT[s<.45?0:s<.75?1:2];t.setColorAt(r,nE.set(c))}return t.instanceMatrix.needsUpdate=!0,t.instanceColor&&(t.instanceColor.needsUpdate=!0),t}buildTuftField(e){let t=rw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density*FT}),n=this.coverage>=1?t:t.filter(e=>nw(e.x,e.z,this.seed)<=this.coverage);this.tuftTime={value:this.time},this.tuftStrength={value:this.sway*zT};let r=new nc({alphaTest:.5,side:2,roughness:1}),i=aT(this.seed,this.tuftStyle);i&&(r.map=i,this.tuftTexture=i),hT(r,this.tuftTime,this.tuftStrength);let a=new rs(qT(),r,Math.max(n.length,1));a.count=n.length,a.castShadow=!1,a.receiveShadow=!0;let o=new b(this.seed+7403357),s=eE.set(this.colorA),c=tE.set(this.colorB);for(let e=0;e<n.length;e++){let t=n[e],r=1+(ew(t.x,t.z,this.seed)-1)*RT,i=this.height*IT*r*o.range(BT[0],BT[1]),l=i*LT*o.range(VT[0],VT[1]);ZT.set(t.x,this.bedY(t.x,t.z),t.z),QT.setFromAxisAngle(YT,t.rotY),$T.set(l,i,l),a.setMatrixAt(e,XT.compose(ZT,QT,$T));let u=JC(t.x,t.z),d=Math.min(1,Math.max(0,.5+.35*u.hue+(o.next()-.5)*.3)),f=Math.min(1,Math.max(0,tw(t.x,t.z,this.seed)*.8-.1));nE.copy(s).lerp(c,d).lerp(rE.set(HT),f*.5).multiplyScalar(o.range(.62,1.18)),a.setColorAt(e,nE)}a.instanceMatrix.needsUpdate=!0,a.instanceColor&&(a.instanceColor.needsUpdate=!0),this.meshes=[a]}buildBladesField(e){let t=rw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density});this.benderSlots=Array.from({length:4},()=>new bi(0,0,0,0));let n=Zs.merge([Y.fog]);Object.assign(n,{time:{value:0},windStrength:{value:this.sway*ST},topColor:{value:new G(this.colorB)},bottomColor:{value:new G(this.colorA)},grassHeight:{value:this.height},grassScale:{value:1},benders:{value:this.benderSlots}}),this.bladesMaterial=new ec({vertexShader:Ww,fragmentShader:Gw,uniforms:n,fog:!0,transparent:!0,side:2,depthWrite:!0,depthTest:!0,alphaTest:.1,blending:0});let r=KT(this.height),i=new rs(r,this.bladesMaterial,Math.max(e,1)),a=new rs(r,this.bladesMaterial,Math.max(e,1));i.count=e,a.count=e,i.renderOrder=this.renderOrder,a.renderOrder=this.renderOrder;for(let n=0;n<e;n++){let e=t[n];ZT.set(e.x,this.bedY(e.x,e.z),e.z),$T.setScalar(e.scale),QT.setFromAxisAngle(YT,e.rotY),i.setMatrixAt(n,XT.compose(ZT,QT,$T)),QT.setFromAxisAngle(YT,e.rotY+Math.PI/2),a.setMatrixAt(n,XT.compose(ZT,QT,$T))}i.instanceMatrix.needsUpdate=!0,a.instanceMatrix.needsUpdate=!0,this.meshes=[i,a]}buildSimpleField(e){let t=new nc({side:2,roughness:1}),n=new rs(JT(yT[this.kind]??.08),t,Math.max(e,1));n.count=e,n.receiveShadow=!0;let r=new b(this.seed),i=(this.area[0]??0)/2,a=(this.area[1]??0)/2,o=eE.set(this.colorA),s=tE.set(this.colorB);for(let t=0;t<e;t++){let e=r.range(-i,i),c=r.range(-a,a);ZT.set(e,this.bedY(e,c),c),QT.setFromAxisAngle(YT,r.range(0,Math.PI*2)),$T.set(1,this.height*r.range(bT[0],bT[1]),1),XT.compose(ZT,QT,$T),n.setMatrixAt(t,XT),n.setColorAt(t,nE.copy(o).lerp(s,r.next()))}n.instanceMatrix.needsUpdate=!0,n.instanceColor&&(n.instanceColor.needsUpdate=!0),this.meshes=[n]}disposeMeshes(){let e=new Set(this.meshes.map(e=>e.geometry)),t=new Set(this.meshes.map(e=>e.material));for(let e of this.meshes)e.removeFromParent(),e.dispose();for(let t of e)t.dispose();for(let e of t)e.dispose?.();this.bladesMaterial?.dispose(),this.bladesMaterial=null,this.benderSlots=null,this.tuftTexture?.dispose(),this.tuftTexture=null,this.tuftTime=null,this.tuftStrength=null,this.meshes=[]}free(){this.disposeMeshes(),this.pivot=null,super.free()}};function KT(e){let t=new Ws(1,e,1,1);return t.translate(0,e/2,0),t}function qT(){let e=[],t=[],n=[],r=[];for(let i=0;i<3;i++){let a=i*Math.PI/3,o=Math.cos(a)/2,s=Math.sin(a)/2,c=-Math.sin(a),l=Math.cos(a),u=i*4;e.push(-o,0,-s,o,0,s,-o,1,-s,o,1,s);for(let e=0;e<4;e++)t.push(c,0,l);n.push(0,0,1,0,0,1,1,1),r.push(u,u+1,u+3,u,u+3,u+2)}let i=new q;return i.setAttribute(`position`,new K(new Float32Array(e),3)),i.setAttribute(`normal`,new K(new Float32Array(t),3)),i.setAttribute(`uv`,new K(new Float32Array(n),2)),i.setIndex(r),i}function JT(e){let t=e/2,n=new Float32Array([-t,0,0,t,0,0,-t,1,0,t,1,0,0,0,-t,0,0,t,0,1,-t,0,1,t]),r=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0]),i=new q;return i.setAttribute(`position`,new K(n,3)),i.setAttribute(`normal`,new K(r,3)),i.setIndex([0,1,2,2,1,3,4,5,6,6,5,7]),i}var YT=new H(0,1,0),XT=new W,ZT=new H,QT=new V,$T=new H,eE=new G,tE=new G,nE=new G,rE=new G,iE=[`color`,`metalness`,`roughness`,`emissive`,`emissiveIntensity`,`wireframe`,`flatShading`,`opacity`,`clearcoat`,`clearcoatRoughness`,`envMapIntensity`,`depthTest`,`depthWrite`,`map`,`normalMap`,`repeat`],aE=class extends qp{static typeName=`MeshInstance3D`;static props={mesh:{default:`box`,options:[`box`,`sphere`,`capsule`,`plane`,`cylinder`,`gem`]},size:{default:[1,1,1]},material:{default:{}},castShadow:{default:!1},receiveShadow:{default:!1}};mesh=`box`;size=[1,1,1];material={};castShadow=!1;receiveShadow=!1;static validateJson(e){sE(e.material,e.name)}geometryKey=``;textureKey=``;loadedTextures=[];_createObject3D(){return new jo(new Rs(1,1,1),new rc)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D(),t=`${this.mesh}:${JSON.stringify(this.size)}`;t!==this.geometryKey&&(e.geometry.dispose(),e.geometry=cE(this.mesh,this.size),this.geometryKey=t);let n=e.material;oE(n,this.material),this.syncTextures(n),e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow}syncTextures(e){let t=JSON.stringify([this.material.map??``,this.material.normalMap??``,this.material.repeat??null]);if(t===this.textureKey)return;this.textureKey=t;for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[];let n=e.map!==null||e.normalMap!==null;e.map=null,e.normalMap=null;let r=typeof document<`u`?new Ic:null;r&&this.material.map&&(e.map=this.loadTexture(r,this.material.map,!0)),r&&this.material.normalMap&&(e.normalMap=this.loadTexture(r,this.material.normalMap,!1)),(n||e.map||e.normalMap)&&(e.needsUpdate=!0)}loadTexture(e,t,n){let r=e.load(t);r.wrapS=It,r.wrapT=It;let[i,a]=this.material.repeat??[1,1];return r.repeat.set(i,a),r.anisotropy=4,n&&(r.colorSpace=dr),this.loadedTextures.push(r),r}free(){for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[],super.free()}};function oE(e,t){e.color.set(t.color??`#ffffff`),e.metalness=t.metalness??0,e.roughness=t.roughness??1,e.wireframe=t.wireframe??!1,e.emissive.set(t.emissive??`#000000`),e.emissiveIntensity=t.emissiveIntensity??1;let n=t.opacity??1;e.opacity=n,e.transparent=n<1;let r=t.clearcoat??0;e.clearcoat>0!=r>0&&(e.needsUpdate=!0),e.clearcoat=r,e.clearcoatRoughness=t.clearcoatRoughness??0,e.envMapIntensity=t.envMapIntensity??1,e.depthTest=t.depthTest??!0,e.depthWrite=t.depthWrite??!0;let i=t.flatShading??!1;e.flatShading!==i&&(e.flatShading=i,e.needsUpdate=!0)}function sE(e,t,n=`MeshInstance3D`){let r=e=>{throw new y(`BAD_FORMAT`,`${n} '${t}' ${e}`,{prop:`material`,validOptions:[...iE]})};(typeof e!=`object`||!e||Array.isArray(e))&&r(`material must be an object, got ${JSON.stringify(e)}.`);for(let t of Object.keys(e))iE.includes(t)||r(`material has unknown key '${t}' — must be one of [${iE.join(`, `)}].`);for(let t of[`map`,`normalMap`]){let n=e[t];n!==void 0&&(typeof n!=`string`||n.length===0)&&r(`material.${t} must be a non-empty texture URL string, got ${JSON.stringify(n)}.`)}if(e.repeat!==void 0){let t=e.repeat;(!Array.isArray(t)||t.length!==2||!t.every(e=>typeof e==`number`&&Number.isFinite(e)&&e>0))&&r(`material.repeat must be [u, v] with positive numbers, got ${JSON.stringify(t)}.`),!e.map&&!e.normalMap&&r(`material.repeat tiles nothing — add a 'map' and/or 'normalMap' texture URL.`)}for(let t of[`metalness`,`roughness`,`opacity`,`clearcoat`,`clearcoatRoughness`]){let n=e[t];n!==void 0&&!(typeof n==`number`&&n>=0&&n<=1)&&r(`material.${t} must be a number in 0..1, got ${JSON.stringify(n)}.`)}e.envMapIntensity!==void 0&&!(typeof e.envMapIntensity==`number`&&Number.isFinite(e.envMapIntensity)&&e.envMapIntensity>=0)&&r(`material.envMapIntensity must be a number >= 0, got ${JSON.stringify(e.envMapIntensity)}.`);for(let t of[`wireframe`,`flatShading`,`depthTest`,`depthWrite`]){let n=e[t];n!==void 0&&typeof n!=`boolean`&&r(`material.${t} must be a boolean, got ${JSON.stringify(n)}.`)}}function cE(e,t){let n=t[0]??1,r=t[1]??1,i=t[2]??1;switch(e){case`box`:return new Rs(n,r,i);case`sphere`:return new Gs(n,32,16);case`gem`:return new Us(n,0);case`capsule`:return new zs(n,r,8,16);case`plane`:{let e=new Ws(n,i);return e.rotateX(-Math.PI/2),e}case`cylinder`:return new Bs(n,n,r,24);default:throw new y(`PROP_TYPE_MISMATCH`,`MeshInstance3D.mesh must be one of box|sphere|capsule|plane|cylinder|gem, got '${e}'.`)}}var lE=class extends qp{static typeName=`InstancedMesh3D`;static props={mesh:{default:`box`,options:[`box`,`sphere`,`capsule`,`plane`,`cylinder`,`gem`]},size:{default:[1,1,1]},material:{default:{}},transforms:{default:[]},castShadow:{default:!1},receiveShadow:{default:!1}};mesh=`box`;size=[1,1,1];material={};castShadow=!1;receiveShadow=!1;_transforms=[];transformsDirty=!0;get transforms(){return this._transforms}set transforms(e){this._transforms=e,this.transformsDirty=!0}instanced=null;builtKey=``;static validateJson(e){let t=e;sE(t.material,e.name);for(let[n,r]of t._transforms.entries())if(!Array.isArray(r)||r.length<3||r.length>5||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`InstancedMesh3D '${e.name}': transforms[${n}] must be [x, y, z, yawDeg?, scale?] (numbers), got ${JSON.stringify(r)}.`)}get instanceCount(){return this.instanced?.count??0}_syncObject3D(e){super._syncObject3D(e);let t=this._ensureObject3D(),n=`${this.mesh} ${JSON.stringify(this.size)} ${this._transforms.length}`;if(n!==this.builtKey){if(this.builtKey=n,this.instanced&&=(t.remove(this.instanced),this.instanced.geometry.dispose(),this.instanced.material.dispose(),null),this._transforms.length>0){let e=cE(this.mesh,this.size),n=new rc;this.instanced=new rs(e,n,this._transforms.length),this.instanced.instanceMatrix.setUsage(_r),t.add(this.instanced)}this.transformsDirty=!0}let r=this.instanced;if(r&&(r.castShadow=this.castShadow,r.receiveShadow=this.receiveShadow,oE(r.material,this.material),this.transformsDirty)){this.transformsDirty=!1;for(let e=0;e<this._transforms.length;e++){let t=this._transforms[e];dE.set(t[0]??0,t[1]??0,t[2]??0),fE.setFromAxisAngle(uE,(t[3]??0)*Math.PI/180);let n=t[4]??1;pE.set(n,n,n),mE.compose(dE,fE,pE),r.setMatrixAt(e,mE)}r.instanceMatrix.needsUpdate=!0,r.computeBoundingSphere()}}free(){this.instanced&&(this.instanced.geometry.dispose(),this.instanced.material.dispose()),super.free()}},uE=new H(0,1,0),dE=new H,fE=new V,pE=new H,mE=new W,hE=class extends qp{static typeName=`DirectionalLight3D`;static props={color:{default:`#ffffff`},intensity:{default:1},castShadow:{default:!1},shadowArea:{default:75},shadowMapSize:{default:2048},shadowFollowsCamera:{default:!1}};color=`#ffffff`;intensity=1;castShadow=!1;shadowArea=75;shadowMapSize=2048;shadowFollowsCamera=!1;_createObject3D(){return new nl}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();if(e.color.set(this.color),e.intensity=this.intensity,e.castShadow=this.castShadow,this.castShadow&&`shadow`in e){let t=e.shadow.camera;`left`in t&&(t.left=-this.shadowArea,t.right=this.shadowArea,t.top=this.shadowArea,t.bottom=-this.shadowArea,t.near=.5,t.far=500,t.updateProjectionMatrix()),e.shadow.mapSize.set(this.shadowMapSize,this.shadowMapSize),e.shadow.bias=-2e-4,e.shadow.normalBias=.002}}},gE=class extends qp{static typeName=`OmniLight3D`;static props={color:{default:`#ffffff`},intensity:{default:1},range:{default:0}};color=`#ffffff`;intensity=1;range=0;_createObject3D(){return new $c}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();e.color.set(this.color),e.intensity=this.intensity,e.distance=this.range}},_E=class extends qp{static typeName=`LoftMesh3D`;static props={sections:{default:[]},slices:{default:24},smooth:{default:4},material:{default:{}},castShadow:{default:!1},receiveShadow:{default:!1}};sections=[];slices=24;smooth=4;material={};castShadow=!1;receiveShadow=!1;static validateJson(e){let t=e;vE(t.sections,e.name),sE(t.material,e.name,`LoftMesh3D`);for(let n of[`map`,`normalMap`,`repeat`])if(t.material[n]!==void 0)throw new y(`BAD_FORMAT`,`LoftMesh3D '${e.name}' material does not support '${n}' — a loft has no UVs; use color/metalness/roughness/clearcoat/envMapIntensity instead.`,{prop:`material`})}geometryKey=``;_createObject3D(){return new jo(new q,new rc)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D(),t=JSON.stringify([this.sections,this.slices,this.smooth]);t!==this.geometryKey&&this.sections.length>=2&&(e.geometry.dispose(),e.geometry=xE(this.sections,this.slices,this.smooth),this.geometryKey=t),oE(e.material,this.material),e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow}};function vE(e,t){let n=e=>{throw new y(`BAD_FORMAT`,`LoftMesh3D '${t}' ${e}`,{prop:`sections`})};(!Array.isArray(e)||e.length<2)&&n(`sections needs at least 2 stations, got ${JSON.stringify(e)}.`);for(let[t,r]of e.entries()){(typeof r!=`object`||!r)&&n(`sections[${t}] must be an object.`);for(let e of[`z`,`width`,`height`,`y`])(typeof r[e]!=`number`||!Number.isFinite(r[e]))&&n(`sections[${t}].${e} must be a finite number, got ${JSON.stringify(r[e])}.`);(r.width<=0||r.height<=0)&&n(`sections[${t}] width/height must be positive, got ${r.width}×${r.height}.`),r.corner!==void 0&&!(typeof r.corner==`number`&&r.corner>=0&&r.corner<=1)&&n(`sections[${t}].corner must be in 0..1, got ${JSON.stringify(r.corner)}.`),t>0&&r.z<=e[t-1].z&&n(`sections[].z must be strictly ascending (sections[${t}].z=${r.z}).`)}}function yE(e,t,n,r,i){let a=i*i,o=a*i;return .5*(2*t+(n-e)*i+(2*e-5*t+4*n-r)*a+(-e+3*t-3*n+r)*o)}function bE(e,t){let n=t=>{let n=e[Math.max(0,Math.min(e.length-1,t))];return{z:n.z,width:n.width,height:n.height,y:n.y,corner:n.corner??.7}},r=[];for(let i=0;i<e.length-1;i++){let a=n(i-1),o=n(i),s=n(i+1),c=n(i+2),l=i===e.length-2?t+1:t;for(let e=0;e<l;e++){let n=e/t;r.push({z:yE(a.z,o.z,s.z,c.z,n),width:Math.max(1e-4,yE(a.width,o.width,s.width,c.width,n)),height:Math.max(1e-4,yE(a.height,o.height,s.height,c.height,n)),y:yE(a.y,o.y,s.y,c.y,n),corner:Math.min(1,Math.max(0,yE(a.corner,o.corner,s.corner,c.corner,n)))})}}return r}function xE(e,t,n){let r=Math.max(8,Math.min(64,Math.round(t))),i=bE(e,Math.max(1,Math.min(16,Math.round(n)))),a=i.length,o=new Float32Array((a*r+2)*3),s=i[0],c=i[a-1];o.set([0,s.y,s.z],0),o.set([0,c.y,c.z],3);for(let e=0;e<a;e++){let t=i[e],n=8-6*t.corner,a=Math.max(n,5);for(let i=0;i<r;i++){let s=i/r*Math.PI*2,c=Math.cos(s),l=Math.sin(s),u=l>=0?n:a,d=t.width/2*Math.sign(c)*Math.abs(c)**(2/u),f=t.height/2*Math.sign(l)*Math.abs(l)**(2/u),p=(2+e*r+i)*3;o[p]=d,o[p+1]=t.y+f,o[p+2]=t.z}}let l=[],u=(e,t)=>2+e*r+t%r;for(let e=0;e<a-1;e++)for(let t=0;t<r;t++){let n=u(e,t),r=u(e,t+1),i=u(e+1,t),a=u(e+1,t+1);l.push(n,r,i,r,a,i)}for(let e=0;e<r;e++)l.push(0,u(0,e+1),u(0,e)),l.push(1,u(a-1,e),u(a-1,e+1));let d=new q;return d.setAttribute(`position`,new K(o,3)),d.setIndex(l),d.computeVertexNormals(),d}function SE(e){let t=e.lastIndexOf(`.`);return t===-1?e:e.slice(0,t)}function CE(e,t,n){let r=e.tracks.filter(e=>{let r=t.has(SE(e.name));return n===`keep`?r:!r});return new Cc(`${e.name}#${n}`,e.duration,r)}function wE(e){let t=new Set,n=e=>{t.add(e.name);for(let t of e.children)n(t)};return n(e),t}var TE={Hips:`hips`,Spine:`spine`,Spine1:`chest`,Spine2:`upperChest`,Neck:`neck`,Head:`head`,LeftShoulder:`leftShoulder`,LeftArm:`leftUpperArm`,LeftForeArm:`leftLowerArm`,LeftHand:`leftHand`,RightShoulder:`rightShoulder`,RightArm:`rightUpperArm`,RightForeArm:`rightLowerArm`,RightHand:`rightHand`,LeftUpLeg:`leftUpperLeg`,LeftLeg:`leftLowerLeg`,LeftFoot:`leftFoot`,LeftToeBase:`leftToes`,RightUpLeg:`rightUpperLeg`,RightLeg:`rightLowerLeg`,RightFoot:`rightFoot`,RightToeBase:`rightToes`,LeftHandThumb1:`leftThumbMetacarpal`,LeftHandThumb2:`leftThumbProximal`,LeftHandThumb3:`leftThumbDistal`,LeftHandIndex1:`leftIndexProximal`,LeftHandIndex2:`leftIndexIntermediate`,LeftHandIndex3:`leftIndexDistal`,LeftHandMiddle1:`leftMiddleProximal`,LeftHandMiddle2:`leftMiddleIntermediate`,LeftHandMiddle3:`leftMiddleDistal`,LeftHandRing1:`leftRingProximal`,LeftHandRing2:`leftRingIntermediate`,LeftHandRing3:`leftRingDistal`,LeftHandPinky1:`leftLittleProximal`,LeftHandPinky2:`leftLittleIntermediate`,LeftHandPinky3:`leftLittleDistal`,RightHandThumb1:`rightThumbMetacarpal`,RightHandThumb2:`rightThumbProximal`,RightHandThumb3:`rightThumbDistal`,RightHandIndex1:`rightIndexProximal`,RightHandIndex2:`rightIndexIntermediate`,RightHandIndex3:`rightIndexDistal`,RightHandMiddle1:`rightMiddleProximal`,RightHandMiddle2:`rightMiddleIntermediate`,RightHandMiddle3:`rightMiddleDistal`,RightHandRing1:`rightRingProximal`,RightHandRing2:`rightRingIntermediate`,RightHandRing3:`rightRingDistal`,RightHandPinky1:`rightLittleProximal`,RightHandPinky2:`rightLittleIntermediate`,RightHandPinky3:`rightLittleDistal`},EE={};for(let[e,t]of Object.entries(TE))EE[`mixamorig${e}`]=t,EE[`mixamorig:${e}`]=t;function DE(e,t,n){let r=[],i=new Set,a=new V,o=new V,s=new V,c=n.meta?.metaVersion===`0`,l=t.getObjectByName(`mixamorigHips`)??t.getObjectByName(`mixamorig:Hips`),u=n.humanoid?.getNormalizedBoneNode(`hips`),d=l&&u?Math.abs(u.getWorldPosition(new H).y)/Math.max(1e-6,Math.abs(l.getWorldPosition(new H).y)):1;for(let l of e.tracks){let e=l.name.lastIndexOf(`.`),u=l.name.slice(0,e),f=l.name.slice(e+1),p=EE[u],m=p?n.humanoid?.getNormalizedBoneNode(p)?.name:void 0,h=t.getObjectByName(u);if(!m||!h){i.add(u);continue}if(h.getWorldQuaternion(a).invert(),h.parent?h.parent.getWorldQuaternion(o):o.identity(),l instanceof bc&&f===`quaternion`){let e=Float32Array.from(l.values);for(let t=0;t<e.length;t+=4)s.set(e[t]??0,e[t+1]??0,e[t+2]??0,e[t+3]??1),s.premultiply(o).multiply(a),e[t]=c?-s.x:s.x,e[t+1]=s.y,e[t+2]=c?-s.z:s.z,e[t+3]=s.w;r.push(new bc(`${m}.quaternion`,[...l.times],[...e]))}else if(l instanceof Sc&&f===`position`){let e=Float32Array.from(l.values);for(let t=0;t<e.length;t+=3)e[t]=(c?-(e[t]??0):e[t]??0)*d,e[t+1]=(e[t+1]??0)*d,e[t+2]=(c?-(e[t+2]??0):e[t+2]??0)*d;r.push(new Sc(`${m}.position`,[...l.times],[...e]))}}return{clip:new Cc(`${e.name} (VRM)`,e.duration,r),retargetedTracks:r.length,skippedBones:[...i]}}var OE=.2,kE=.12,AE=class extends qp{static typeName=`ModelInstance3D`;static signals=[`animationFinished`];static props={...qp.props,model:{default:``},animation:{default:``},targetHeight:{default:0},castShadow:{default:!1},animationLoop:{default:!0},animationUpper:{default:``},animationUpperLoop:{default:!1},upperBodyRoot:{default:`Spine`},receiveShadow:{default:!1},tint:{default:``},metalness:{default:-1},roughness:{default:-1}};model=``;animation=``;targetHeight=0;castShadow=!1;animationLoop=!0;animationUpper=``;animationUpperLoop=!1;upperBodyRoot=`Spine`;receiveShadow=!1;tint=``;metalness=-1;roughness=-1;store=null;entry=null;mountedRef=``;fittedHeight=-1;fitGroup=null;mixer=null;playing=``;currentAction=null;playingUpper=``;upperAction=null;baseMode=`full`;maskCache=new Map;actionKeys=new WeakMap;warnedClaim=!1;tintTargets=[];tintedClones=[];appliedMods=``;nodePoses=new Map;poseNode(e,t){this.nodePoses.set(e,t),this.applyPoses()}_createObject3D(){return new Qi}findBone(e){let t=this.fitGroup;if(!t||e===``)return null;let n=t.getObjectByName(e)??t.getObjectByName(`mixamorig${e}`)??t.getObjectByName(`mixamorig:${e}`);if(n)return n;let r=e.toLowerCase(),i=null;return t.traverse(e=>{!i&&e.name.toLowerCase().endsWith(r)&&(i=e)}),i}boneNames(){let e=[];return this.fitGroup?.traverse(t=>{t.isBone&&e.push(t.name)}),e}availableAnimations(){let e=this.entry?.animations.map(e=>e.name)??[],t=this.store?.animationRefs()??[];return[...e,...t]}_syncModel(e){this.store=e;let t=this._ensureObject3D();if(this.model===``){this.fitGroup&&this.unmount(t);return}let n=e.getModel(this.model);if(!(n.status!==`ready`||!n.scene)){if(this.mountedRef!==this.model){this.unmount(t);let e;if(n.isVrm){if(n.claimedBy&&n.claimedBy!==this){this.warnedClaim||(this.warnedClaim=!0,console.warn(`incanto: VRM '${this.model}' is already displayed by another node — a VRM asset can back only one ModelInstance3D.`));return}n.claimedBy=this,e=n.scene}else e=bb(n.scene);let r=new Qi;r.add(e),t.add(r),this.fitGroup=r,this.entry=n,this.mountedRef=this.model,this.mixer=new El(e),this.mixer.addEventListener(`finished`,e=>{let t=e.action,n=(t&&this.actionKeys.get(t))??this.animation;t&&t===this.upperAction&&(t.fadeOut(kE),this.upperAction=null,this.playingUpper=``,this.animationUpper=``),this.emit(`animationFinished`,n)}),this.playing=``,this.currentAction=null,this.fittedHeight=-1,e.traverse(e=>{e.userData.incantoModelShared=!0}),this.tintTargets=[],this.tintedClones=[],this.appliedMods=``,e.traverse(e=>{let t=e;t.isMesh&&t.material&&this.tintTargets.push({mesh:t,original:t.material})})}if(this.fitGroup&&this.fittedHeight!==this.targetHeight)if(this.fittedHeight=this.targetHeight,this.targetHeight>0){let e=this.fitGroup.scale.x;this.fitGroup.scale.setScalar(1);let t=jE(this.fitGroup).getSize(new H),n=t.y>0?this.targetHeight/t.y:e;n<.05||n>20?(this.fitGroup.scale.setScalar(1),console.warn(`[incanto] ModelInstance3D '${this.name}': targetHeight fit measured an implausible scale (${n.toFixed(2)}x) — skinned rigs defeat bounding-box measurement. Rendering at the model's authored scale instead.`)):this.fitGroup.scale.setScalar(n)}else this.fitGroup.scale.setScalar(1);this.fitGroup&&this.fitGroup.traverse(e=>{let t=e;t.isMesh&&(t.castShadow=this.castShadow,t.receiveShadow=this.receiveShadow)}),this.applyMaterialMods(),this.applyPoses(),this.syncAnimation(e),this.syncUpperAnimation(e)}}applyMaterialMods(){let e=`${this.tint}|${this.metalness}|${this.roughness}`;if(e===this.appliedMods)return;for(let e of this.tintedClones)e.dispose();this.tintedClones=[];let t=this.tint?new G(this.tint):null,n=t!==null||this.metalness>=0||this.roughness>=0;for(let e of this.tintTargets){if(!n){e.mesh.material=e.original;continue}let r=e=>{let n=e.clone();if(t){let r=n,i=e.color;r.color&&=i?i.clone().multiply(t):t.clone()}let r=n;return this.metalness>=0&&typeof r.metalness==`number`&&(r.metalness=this.metalness),this.roughness>=0&&typeof r.roughness==`number`&&(r.roughness=this.roughness),n.userData.incantoTinted=!0,this.tintedClones.push(n),n};e.mesh.material=Array.isArray(e.original)?e.original.map(r):r(e.original)}this.appliedMods=e}applyPoses(){if(!this.fitGroup||this.nodePoses.size===0)return;let e=Math.PI/180;for(let[t,n]of this.nodePoses){let r=this.fitGroup.getObjectByName(t);r&&r.rotation.set(n[0]*e,n[1]*e,n[2]*e)}}resolveClip(e,t){if(!this.entry)return null;let n=this.entry.animations.find(t=>t.name===e);if(n)return n;if(!(e.startsWith(`$`)||/\.(glb|gltf)$/i.test(e)))return null;let r=t.getAnimation(e);if(r.status===`loading`)return`loading`;if(r.status!==`ready`||!r.scene)return null;let i=(r.clip?r.clips.find(e=>e.name===r.clip):void 0)??r.clips[0];if(!i)return null;if(this.entry.isVrm&&this.entry.vrm){let t=this.entry.retargeted.get(e);if(t)return t;let n=DE(i,r.scene,this.entry.vrm);return n.skippedBones.length>0&&console.warn(`incanto: retarget '${e}' skipped bones: ${n.skippedBones.join(`, `)}`),this.entry.retargeted.set(e,n.clip),n.clip}return i}layerVariants(e){let t=this.findBone(this.upperBodyRoot);if(!t)return null;let n=`${e.uuid} ${t.name}`,r=this.maskCache.get(n);if(!r){let i=wE(t);r={upper:CE(e,i,`keep`),lower:CE(e,i,`drop`)},this.maskCache.set(n,r)}return r}upperLayerActive(){return this.animationUpper!==``||this.upperAction!==null}syncAnimation(e){if(!this.mixer||!this.entry)return;let t=this.upperLayerActive()?`lower`:`full`;if(this.playing===this.animation&&this.baseMode===t)return;if(this.animation===``){this.currentAction&&this.currentAction.fadeOut(OE),this.currentAction=null,this.playing=``,this.baseMode=t;return}let n=this.resolveClip(this.animation,e);if(n===`loading`)return;let r=n;if(r&&t===`lower`){let e=this.layerVariants(r);e&&(r=e.lower)}let i=this.playing===this.animation;if(this.playing=this.animation,this.baseMode=t,r){let e=this.mixer.clipAction(r);if(e.reset(),this.animationLoop?e.setLoop(Qn,1/0):(e.setLoop(Zn,1),e.clampWhenFinished=!0),e.setEffectiveWeight(1),e.play(),this.actionKeys.set(e,this.animation),this.currentAction&&this.currentAction!==e){i&&r.duration>0&&(e.time=this.currentAction.time%r.duration);let t=r.duration>0&&this.currentAction.getClip().duration>0;e.crossFadeFrom(this.currentAction,OE,t)}this.currentAction=e}else console.warn(`incanto: model '${this.model}' has no animation '${this.animation}' — embedded: ${this.entry.animations.map(e=>e.name).join(`, `)||`(none)`}; assets: ${e.animationRefs().join(`, `)||`(none)`}`)}syncUpperAnimation(e){if(!this.mixer||!this.entry||this.playingUpper===this.animationUpper)return;if(this.animationUpper===``){this.upperAction?.fadeOut(kE),this.upperAction=null,this.playingUpper=``;return}let t=this.resolveClip(this.animationUpper,e);if(t===`loading`)return;if(!t){console.warn(`incanto: model '${this.model}' has no animation '${this.animationUpper}' for the upper layer.`),this.playingUpper=this.animationUpper;return}let n=this.layerVariants(t);if(!n){console.warn(`incanto: upperBodyRoot '${this.upperBodyRoot}' not found in '${this.model}' — upper layer skipped.`),this.playingUpper=this.animationUpper;return}let r=this.mixer.clipAction(n.upper);r.reset(),this.animationUpperLoop?r.setLoop(Qn,1/0):(r.setLoop(Zn,1),r.clampWhenFinished=!0),r.setEffectiveWeight(1),r.fadeIn(kE),r.play(),this.actionKeys.set(r,this.animationUpper),this.upperAction&&this.upperAction!==r&&this.upperAction.fadeOut(kE),this.upperAction=r,this.playingUpper=this.animationUpper}update(e){this.mixer?.update(e),this.entry?.isVrm&&this.entry.claimedBy===this&&this.entry.vrm?.update(e)}onExitTree(){this.unmount(this._ensureObject3D())}unmount(e){this.entry?.claimedBy===this&&(this.entry.claimedBy=null),this.fitGroup&&e.remove(this.fitGroup);for(let e of this.tintedClones)e.dispose();this.tintedClones=[],this.tintTargets=[],this.appliedMods=``,this.fitGroup=null,this.mixer=null,this.currentAction=null,this.upperAction=null,this.playingUpper=``,this.baseMode=`full`,this.maskCache.clear(),this.entry=null,this.mountedRef=``,this.playing=``,this.fittedHeight=-1}};function jE(e){e.updateWorldMatrix(!0,!0);let t=new Sa,n=new Sa,r=e.matrixWorld.clone().invert(),i=new W,a=new H;return e.traverse(e=>{let o=e;if(o.isSkinnedMesh&&o.skeleton){for(let e of o.skeleton.boneInverses)i.copy(e).invert().premultiply(o.matrixWorld).premultiply(r),a.setFromMatrixPosition(i),t.expandByPoint(a);return}let s=e;s.isMesh&&s.geometry&&(s.geometry.computeBoundingBox(),s.geometry.boundingBox&&(n.copy(s.geometry.boundingBox).applyMatrix4(s.matrixWorld).applyMatrix4(r),t.union(n)))}),t}var ME=.01,NE=class e extends qp{orderGroup=`effects`;static typeName=`Particles3D`;static signals=[`finished`];static props={orderGroup:{default:`effects`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},preset:{default:`custom`,options:[`custom`,...it]},emitting:{default:!0},rate:{default:40},burst:{default:0},lifetime:{default:[.6,1.2]},speed:{default:[40,120]},directionDeg:{default:-90},spreadDeg:{default:30},gravity:{default:[0,0]},drag:{default:0},sizeStart:{default:8},sizeEnd:{default:2},colorStart:{default:`#ffffff`},colorEnd:{default:`#ffffff`},paletteColors:{default:[]},alphaStart:{default:1},alphaEnd:{default:0},shimmer:{default:0},blend:{default:`add`,options:[`add`,`normal`]},depthTest:{default:!0},maxParticles:{default:256}};preset=`custom`;emitting=!0;rate=40;burst=0;lifetime=[.6,1.2];speed=[40,120];directionDeg=-90;spreadDeg=30;gravity=[0,0];drag=0;sizeStart=8;sizeEnd=2;colorStart=`#ffffff`;colorEnd=`#ffffff`;paletteColors=[];alphaStart=1;alphaEnd=0;shimmer=0;blend=`add`;depthTest=!0;maxParticles=256;static validateJson(e){let t=e;if(t.preset!==`custom`&&!it.includes(t.preset))throw new y(`BAD_FORMAT`,`Particles3D '${e.name}' preset must be 'custom' or one of [${it.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:it});if(t.blend!==`add`&&t.blend!==`normal`)throw new y(`BAD_FORMAT`,`Particles3D '${e.name}' blend must be 'add' or 'normal', got '${t.blend}'.`,{prop:`blend`,validOptions:[`add`,`normal`]})}sim=null;bursted=!1;finishedEmitted=!1;_ensureSim(){if(!this.sim){at(this,this.preset,ge(e.typeName));let t=this.tree?.engine?.rng??new b(4660);this.sim=new st({rate:this.emitting?this.rate:0,lifetime:[this.lifetime[0]??1,this.lifetime[1]??1],speed:[(this.speed[0]??0)*ME,(this.speed[1]??0)*ME],directionDeg:this.directionDeg,spreadDeg:this.spreadDeg,gravity:[(this.gravity[0]??0)*ME,(this.gravity[1]??0)*ME,(this.gravity[2]??0)*ME],drag:this.drag,maxParticles:this.maxParticles,spreadZ:!0},t)}return this.sim}update(e){let t=this._ensureSim();t.setRate(this.emitting?this.rate:0),this.burst>0&&!this.bursted&&(this.bursted=!0,t.burst(this.burst)),t.update(e),(!this.emitting||this.rate===0)&&this.bursted&&t.done&&!this.finishedEmitted&&(this.finishedEmitted=!0,this.emit(`finished`))}replay(){this.bursted=!1,this.finishedEmitted=!1}points=null;positions=null;colors=null;paletteCache=[];paletteCacheKey=``;_syncObject3D(){super._syncObject3D(),this.syncParticles()}refreshPalette(){let e=this.paletteColors;if(e.length===0)return null;let t=e.join(`|`);if(t!==this.paletteCacheKey){this.paletteCacheKey=t;for(let t=0;t<e.length;t++){let n=this.paletteCache[t];n||(n=new G,this.paletteCache[t]=n),n.set(e[t])}this.paletteCache.length=e.length}return this.paletteCache}syncParticles(){let e=this._ensureSim();if(!this.points||(this.positions?.length??0)!==this.maxParticles*3){this.points?.removeFromParent(),this.positions=new Float32Array(this.maxParticles*3),this.colors=new Float32Array(this.maxParticles*4);let e=new q;e.setAttribute(`position`,new K(this.positions,3)),e.setAttribute(`color`,new K(this.colors,4));let t=new Es({size:(this.sizeStart+this.sizeEnd)/2*ME,map:RE(),vertexColors:!0,transparent:!0,depthWrite:!1,depthTest:this.depthTest,alphaTest:.02,sizeAttenuation:!0,blending:this.blend===`add`?2:1});this.points=new js(e,t),this.points.frustumCulled=!1,this._ensureObject3D().add(this.points)}this.points.renderOrder=this.renderOrder;let t=this.points.material;t.depthTest=this.depthTest,t.blending=this.blend===`add`?2:1;let n=this.positions,r=this.colors,i=this.refreshPalette(),a=i?null:PE.set(this.colorStart),o=FE.set(this.colorEnd),s=this.shimmer,c=0;e.forEach(e=>{n[c*3]=e.x,n[c*3+1]=-e.y,n[c*3+2]=e.z;let t=i?i[Math.floor(e.seed*i.length)]:a,l=Math.max(0,this.alphaStart+(this.alphaEnd-this.alphaStart)*e.t);s>0&&(l*=.5+.5*Math.sin(2*Math.PI*(e.age*s+e.seed))),IE.copy(t).lerp(o,e.t),r[c*4]=IE.r,r[c*4+1]=IE.g,r[c*4+2]=IE.b,r[c*4+3]=l,c+=1});let l=this.points.geometry;l.setDrawRange(0,c),l.getAttribute(`position`).needsUpdate=!0,l.getAttribute(`color`).needsUpdate=!0}},PE=new G,FE=new G,IE=new G,LE=null;function RE(){if(LE)return LE;let e=63/2,t=new Uint8Array(4096*4);for(let n=0;n<64;n++)for(let r=0;r<64;r++){let i=(r-e)/e,a=(n-e)/e,o=Math.hypot(i,a),s=.35,c;if(o<=s)c=1;else{let e=Math.max(0,1-(o-s)/(1-s));c=e*e}let l=Math.round(c*255),u=(n*64+r)*4;t[u]=255,t[u+1]=255,t[u+2]=255,t[u+3]=l}let n=new Go(t,64,64,sn);return n.magFilter=Ht,n.minFilter=Ht,n.generateMipmaps=!1,n.needsUpdate=!0,LE=n,n}var zE=24,BE=3,VE=4,HE=.05,UE=12;function WE(e,t){let n=e.map(e=>({x:e[0]??0,z:e[1]??0})).filter((e,t,n)=>t===0||Math.hypot(e.x-(n[t-1]?.x??0),e.z-(n[t-1]?.z??0))>1e-6);if(n.length<2||t<=0)return[];let r=[],i=0;for(let e=0;e<n.length-1;e++){let t=n[Math.max(0,e-1)],a=n[e],o=n[e+1],s=n[Math.min(n.length-1,e+2)];for(let e=0;e<zE;e++){let n=e/zE,c=QE(t.x,a.x,o.x,s.x,n),l=QE(t.z,a.z,o.z,s.z,n),u=r[r.length-1];u&&(i+=Math.hypot(c-u.x,l-u.z)),r.push({x:c,z:l,along:i})}}let a=n[n.length-1],o=r[r.length-1];o&&(i+=Math.hypot(a.x-o.x,a.z-o.z)),r.push({x:a.x,z:a.z,along:i});let s=i;if(s<1e-6)return[];let c=Math.max(1,Math.round(s/t)),l=s/c,u=[],d=0;for(let e=0;e<=c;e++){let t=Math.min(e*l,s);for(;d<r.length-2&&r[d+1].along<t;)d++;let n=r[d],i=r[Math.min(d+1,r.length-1)],a=i.along-n.along,o=a>1e-9?(t-n.along)/a:0;u.push({x:n.x+(i.x-n.x)*o,z:n.z+(i.z-n.z)*o,tx:1,tz:0,along:t})}for(let e=0;e<u.length;e++){let t=u[Math.max(0,e-1)],n=u[Math.min(u.length-1,e+1)],r=n.x-t.x,i=n.z-t.z,a=Math.hypot(r,i)||1,o=u[e];o.tx=r/a,o.tz=i/a}return u}function GE(e,t){if(e.length===0)return 0;if(e.length===1)return e[0];let n=Math.min(Math.max(t,0),1)*(e.length-1),r=Math.min(Math.floor(n),e.length-2),i=n-r,a=e[r];return a+(e[r+1]-a)*i}function KE(e){let t=WE(e.path,e.step);if(t.length===0)return[];let n=t[t.length-1].along||1,r=t.map(t=>Math.max(GE(e.widths,t.along/n),.05)/2),i=t.map(t=>e.bedAt(t.x,t.z)),a=Array(i.length);for(let e=0;e<i.length;e++){let t=i[e];a[e]=e===0?t:Math.min(t,a[e-1])}let o=Math.max(.5,e.depth*1.5),s=a.map((e,t)=>{let n=0,r=0;for(let i=-3;i<=BE;i++){let s=a[Math.min(Math.max(t+i,0),a.length-1)];Math.abs(s-e)>o||(n+=s,r++)}return r>0?n/r:e}),c=Array(s.length);for(let e=0;e<s.length;e++){let t=s[e];c[e]=e===0?t:Math.min(t,c[e-1])}let l=r.reduce((e,t)=>e+t,0)/r.length||1;return t.map((n,i)=>{let a=c[i]+e.depth,o=Math.max(0,i-1),s=Math.min(t.length-1,i+1),u=t[s].along-t[o].along,d=(c[o]+e.depth-(c[s]+e.depth))/(u||1),f=Math.max(0,d),p=r[i],m=Math.min(Math.max(e.flowSpeed*Math.sqrt(l/p)*(1+VE*f),HE),UE);return{...n,halfWidth:p,surfaceY:a,slope:f,speed:m}})}function qE(e,t){let n=Math.max(1,Math.round(t.acrossSegments)),r=n+1,i=e.length*r,a=new Float32Array(i*3),o=new Float32Array(i*3),s=new Float32Array(i*2),c=new Float32Array(i*2),l=new Float32Array(i*4),u=Math.max(0,e.length-1)*n,d=new Uint32Array(u*6);for(let i=0;i<e.length;i++){let u=e[i],d=-u.tz,f=u.tx,p=Math.hypot(u.slope,1),m=u.tx*u.slope/p,h=1/p,g=u.tz*u.slope/p;for(let e=0;e<=n;e++){let p=e/n*2-1,_=p*u.halfWidth*t.bankOvershoot,v=u.x+d*_,y=u.z+f*_,b=i*r+e;a[b*3]=v,a[b*3+1]=u.surfaceY,a[b*3+2]=y,o[b*3]=m,o[b*3+1]=h,o[b*3+2]=g,s[b*2]=u.along,s[b*2+1]=_,c[b*2]=u.tx,c[b*2+1]=u.tz,l[b*4]=u.speed,l[b*4+1]=Math.max(0,u.surfaceY-JE(t,v,y)),l[b*4+2]=u.slope,l[b*4+3]=p*t.bankOvershoot}}let f=0;for(let t=0;t+1<e.length;t++)for(let e=0;e<n;e++){let n=t*r+e,i=n+1,a=n+r,o=a+1;d[f++]=n,d[f++]=i,d[f++]=a,d[f++]=i,d[f++]=o,d[f++]=a}return{positions:a,normals:o,uvs:s,flow:c,river:l,indices:d}}function JE(e,t,n){let r=e.bedBlur??0;return r<=0?e.bedAt(t,n):(e.bedAt(t,n)+e.bedAt(t+r,n)+e.bedAt(t-r,n)+e.bedAt(t,n+r)+e.bedAt(t,n-r))/5}function YE(e,t,n){if(e.length===0)return null;let r=0,i=1/0;for(let a=0;a<e.length;a++){let o=e[a],s=(o.x-t)**2+(o.z-n)**2;s<i&&(i=s,r=a)}if(e.length===1){let r=e[0];return XE(r,r,0,t,n,!1)}let a=null,o=1/0;for(let i of[r-1,r]){if(i<0||i+1>=e.length)continue;let r=e[i],s=e[i+1],c=s.x-r.x,l=s.z-r.z,u=c*c+l*l,d=u>1e-9?((t-r.x)*c+(n-r.z)*l)/u:0,f=Math.min(Math.max(d,0),1),p=i===0&&d<0||i+2===e.length&&d>1,m=r.x+c*f,h=r.z+l*f,g=(m-t)**2+(h-n)**2;g<o&&(o=g,a=XE(r,s,f,t,n,p))}return a}function XE(e,t,n,r,i,a){let o=e.x+(t.x-e.x)*n,s=e.z+(t.z-e.z)*n,c=e.tx+(t.tx-e.tx)*n,l=e.tz+(t.tz-e.tz)*n,u=Math.hypot(c,l)||1;c/=u,l/=u;let d=e.halfWidth+(t.halfWidth-e.halfWidth)*n,f=((r-o)*-l+(i-s)*c)/(d||1);return{inside:!a&&Math.abs(f)<=1,across:f,along:e.along+(t.along-e.along)*n,surfaceY:e.surfaceY+(t.surfaceY-e.surfaceY)*n,dirX:c,dirZ:l,speed:e.speed+(t.speed-e.speed)*n,halfWidth:d}}function ZE(e,t={}){let n=t.minGrade??.45,r=t.minDrop??1.2,i=[],a=-1;for(let t=0;t<=e.length;t++){let o=t<e.length&&e[t].slope>=n;if(o&&a<0&&(a=t),o||a<0)continue;let s=e[Math.max(0,a-1)],c=e[Math.min(e.length-1,t)],l=s.surfaceY-c.surfaceY;l>=r&&i.push({x:c.x,z:c.z,topY:s.surfaceY,baseY:c.surfaceY,drop:l,halfWidth:c.halfWidth,dirX:c.tx,dirZ:c.tz,speed:c.speed}),a=-1}return i}function QE(e,t,n,r,i){let a=i*i,o=a*i;return .5*(2*t+(-e+n)*i+(2*e-5*t+4*n-r)*a+(-e+3*t-3*n+r)*o)}var $E=`
|
|
7449
|
+
`)},e.customProgramCacheKey=()=>`incanto-tuft-wind`}var ET=[`grass`,`flowers`,`reeds`],DT=[`blades`,`simple`,`mesh`,`tufts`],OT=[`grass`,`fern`],kT={grass:.08,flowers:.14,reeds:.05},AT=[.75,1.25],jT=.05,MT=.25,NT=2e5,PT=8,FT=.05,IT=.38,LT=[.75,1.3],RT=.1,zT=.42,BT=[.6,1.6],VT=.8,HT=.9,UT=.04,WT=[`#f5f1e2`,`#e9d052`,`#8d7bd9`],GT=1/3,KT=1.5,qT=1.45,JT=.4,YT=.13,XT=[.85,1.2],ZT=[.8,1.3],QT=`#b3a24e`,$T=.8,eE=.5,tE=class e extends qp{static typeName=`Foliage3D`;static props={kind:{default:`grass`,options:ET},style:{default:`mesh`,options:DT},tuftStyle:{default:`grass`,options:OT},area:{default:[20,20]},density:{default:12},maxInstances:{default:5e4},height:{default:.25},colorA:{default:`#4d7232`},colorB:{default:`#9aab55`},groundColor:{default:`#1f3015`},sunDirection:{default:[.5,.8,.3]},fadeStart:{default:60},fadeEnd:{default:90},sway:{default:.6},interaction:{default:!0},coverage:{default:.85},flowers:{default:0},seed:{default:1},drape:{default:null},terrain:{default:``},renderOrder:{default:2}};renderOrder=2;kind=`grass`;style=`mesh`;tuftStyle=`grass`;area=[20,20];density=12;maxInstances=5e4;height=.25;colorA=`#4d7232`;colorB=`#9aab55`;groundColor=`#1f3015`;sunDirection=[.5,.8,.3];fadeStart=60;fadeEnd=90;sway=.6;interaction=!0;coverage=.85;flowers=0;seed=1;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(!ET.includes(t.kind))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' kind must be one of [${ET.join(`, `)}], got '${t.kind}'.`,{prop:`kind`,validOptions:ET});if(!DT.includes(t.style))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' style must be one of [${DT.join(`, `)}], got '${t.style}'.`,{prop:`style`,validOptions:DT});if(!OT.includes(t.tuftStyle))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' tuftStyle must be one of [${OT.join(`, `)}], got '${t.tuftStyle}'.`,{prop:`tuftStyle`,validOptions:OT});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});if(!(t.density>0)||!(t.maxInstances>=1))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' needs density > 0 and maxInstances >= 1, got density ${t.density}, maxInstances ${t.maxInstances}.`,{prop:`density`});if(t.maxInstances>NT)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' maxInstances is capped at ${NT} (got ${t.maxInstances}) — split giant fields into multiple nodes.`,{prop:`maxInstances`});if(!(t.fadeStart>=0)||!(t.fadeEnd>t.fadeStart))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' needs fadeStart >= 0 and fadeEnd > fadeStart (the LOD fade window), got fadeStart ${t.fadeStart}, fadeEnd ${t.fadeEnd}.`,{prop:`fadeStart`});let n=t.sunDirection;if(!Array.isArray(n)||n.length!==3||!n.every(e=>Number.isFinite(e))||Math.hypot(n[0]??0,n[1]??0,n[2]??0)===0)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' sunDirection must be a non-zero [x, y, z] vector, got ${JSON.stringify(n)}.`,{prop:`sunDirection`});if(!(t.coverage>0)||!(t.coverage<=1))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' coverage must be in (0, 1] (carpet fill — 1 is solid, lower carves dirt patches), got ${t.coverage}.`,{prop:`coverage`});if(!(t.flowers>=0)||!(t.flowers<=.2))throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' flowers must be in [0, 0.2] (fraction of instances rendered as flower heads — for a whole flower FIELD use kind: 'flowers'), got ${t.flowers}.`,{prop:`flowers`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Foliage3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`})}time=0;pivot=null;meshes=[];bladesMaterial=null;benderSlots=null;pickedBenders=[];fieldKey=``;tuftTime=null;tuftStrength=null;tuftTexture=null;_createObject3D(){return new Qi}get isBlades(){return this.kind===`grass`&&this.style===`blades`}get isMesh(){return this.kind===`grass`&&this.style===`mesh`}get isTufts(){return this.kind===`grass`&&this.style===`tufts`}get isShaderField(){return this.isMesh||this.isBlades}_field(){return this.rebuildIfNeeded(),this.meshes[0]}_fields(){return this.rebuildIfNeeded(),this.meshes}update(e){this.time+=e,this.pickedBenders=this.computeBenders(),this.writeAnimationUniforms()}writeAnimationUniforms(){if(this.isShaderField&&this.bladesMaterial){let e=this.bladesMaterial.uniforms;e.time&&(e.time.value=this.time),e.windStrength&&(e.windStrength.value=this.sway*(this.isMesh?IT:MT));let t=this.benderSlots;if(t)for(let e=0;e<4;e++){let n=this.pickedBenders[e];n?t[e]?.set(n.x,n.y,n.z,n.radius):t[e]?.set(0,0,0,0)}}else this.isTufts&&(this.tuftTime&&(this.tuftTime.value=this.time),this.tuftStrength&&(this.tuftStrength.value=this.sway*YT))}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded();let e=this.pivot;if(this.writeAnimationUniforms(),this.isShaderField){e.matrix.identity();let t=this.bladesMaterial.uniforms;(t.bottomColor?.value).set(this.colorA),(t.topColor?.value).set(this.colorB),this.isMesh&&((t.groundColor?.value).set(this.groundColor),(t.sunDirection?.value).set(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize(),t.fadeStart&&(t.fadeStart.value=this.fadeStart),t.fadeEnd&&(t.fadeEnd.value=this.fadeEnd))}else if(this.isTufts)e.matrix.identity();else if(this.sway>0){let t=Math.sin(this.time*1.7)*jT*this.sway,n=Math.sin(this.time*1.3+1.7)*jT*this.sway*.6;e.matrix.makeShear(0,0,t,n,0,0)}else e.matrix.identity();e.matrixWorldNeedsUpdate=!0}_applySunDirection(t){if(!this.isMesh||!this.bladesMaterial)return;let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this.bladesMaterial.uniforms.sunDirection?.value)?.set(t[0],t[1],t[2])}computeBenders(){if(!this.interaction||!this.isShaderField)return[];let[e,t,n]=Nw(this);this.drape===!0&&!this.drapeTerrain&&this.resolveDrape();let r=this.drapeTerrain,i=[];for(let e of lT(this)){let n=r?r.heightAt(e.x,e.z):t,a=e.footY-n;a<=eE&&a>=-2.5&&i.push({x:e.x,y:e.y,z:e.z,radius:e.radius+$T})}return Xw(i,{x:e,z:n,areaX:this.area[0]??0,areaZ:this.area[1]??0})}rebuildIfNeeded(){this.pivot||(this.pivot=new Qi,this.pivot.matrixAutoUpdate=!1,this._ensureObject3D().add(this.pivot));let e=JSON.stringify([this.kind,this.style,this.tuftStyle,this.area,this.density,this.maxInstances,this.height,this.colorA,this.colorB,this.coverage,this.flowers,this.seed,this.drape,this.terrain]);if(e===this.fieldKey&&this.meshes.length>0)return;this.fieldKey=e,this.disposeMeshes(),this.resolveDrape();let t=this.isMesh?PT:this.isTufts?GT:1,n=Math.min(Math.floor((this.area[0]??0)*(this.area[1]??0)*this.density*t),this.maxInstances);this.isMesh?this.buildMeshField(n):this.isTufts?this.buildTuftField(n):this.isBlades?this.buildBladesField(n):this.buildSimpleField(n);for(let e of this.meshes)Mw(e),this.pivot.add(e)}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=Pw(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Nw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Foliage3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildMeshField(e){let t=pw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density*PT}),n=this.coverage>=1?t:t.filter(e=>fw(e.x,e.z,this.seed)<=this.coverage),r=this.flowers>0?Math.floor(n.length*this.flowers):0,i=new Set;for(let e=0;e<r;e++)i.add(Math.floor((e+.5)*n.length/r));let a=n.filter((e,t)=>!i.has(t)),o=n.filter((e,t)=>i.has(t));this.benderSlots=Array.from({length:4},()=>new bi(0,0,0,0));let s=Zs.merge([Y.lights,Y.fog]);Object.assign(s,{time:{value:0},windStrength:{value:this.sway*IT},topColor:{value:new G(this.colorB)},bottomColor:{value:new G(this.colorA)},groundColor:{value:new G(this.groundColor)},sunDirection:{value:new H(this.sunDirection[0]??0,this.sunDirection[1]??1,this.sunDirection[2]??0).normalize()},fadeStart:{value:this.fadeStart},fadeEnd:{value:this.fadeEnd},benders:{value:this.benderSlots}}),this.bladesMaterial=new ec({vertexShader:nT,fragmentShader:rT,uniforms:s,fog:!0,lights:!0,side:2});let c=Qw(FT),l=a.length,u=Math.max(l,1),d=new rs(c,this.bladesMaterial,u);d.count=l,d.receiveShadow=!0;let f=new b(this.seed+5352221),p=new Float32Array(u*4),m=new Float32Array(u),h=new Float32Array(u);for(let e=0;e<l;e++){let t=a[e],n=iw(t.x,t.z),r=uw(t.x,t.z,this.seed),i=(r-.55)/1.15,o=f.range(LT[0],LT[1]),s=this.height*r*(.55+t.scale*.6);sE.set(t.x,this.bedY(t.x,t.z),t.z),cE.setFromAxisAngle(aE,t.rotY),lE.set(o,s,o),d.setMatrixAt(e,oE.compose(sE,cE,lE));let c=n.leanDir+f.range(-.6,.6),l=(RT+zT*(.5*n.lean+.5*f.next()))*(1+VT*i);p[e*4]=Math.cos(c)*l,p[e*4+1]=Math.sin(c)*l,p[e*4+2]=f.range(BT[0],BT[1])*(1+HT*i),p[e*4+3]=f.next(),m[e]=n.hue;let u=dw(t.x,t.z,this.seed)*.85+(f.next()-.5)*.3;h[e]=Math.min(1,Math.max(0,u))}c.setAttribute(`aBlade`,new Yo(p,4)),c.setAttribute(`aClumpHue`,new Yo(m,1)),c.setAttribute(`aDry`,new Yo(h,1)),d.instanceMatrix.needsUpdate=!0,this.meshes=[d],o.length>0&&this.meshes.push(this.buildFlowerMesh(o))}buildFlowerMesh(e){let t=new rs($w(UT),new nc({roughness:1,side:2}),Math.max(e.length,1));t.count=e.length,t.receiveShadow=!0;let n=new b(this.seed+15797765);for(let r=0;r<e.length;r++){let i=e[r],a=uw(i.x,i.z,this.seed),o=this.height*a*(.85+n.next()*.35);sE.set(i.x,this.bedY(i.x,i.z),i.z),cE.setFromAxisAngle(aE,i.rotY),lE.set(1,o,1),t.setMatrixAt(r,oE.compose(sE,cE,lE));let s=n.next(),c=WT[s<.45?0:s<.75?1:2];t.setColorAt(r,fE.set(c))}return t.instanceMatrix.needsUpdate=!0,t.instanceColor&&(t.instanceColor.needsUpdate=!0),t}buildTuftField(e){let t=pw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density*GT}),n=this.coverage>=1?t:t.filter(e=>fw(e.x,e.z,this.seed)<=this.coverage);this.tuftTime={value:this.time},this.tuftStrength={value:this.sway*YT};let r=new nc({alphaTest:.5,side:2,roughness:1}),i=hT(this.seed,this.tuftStyle);i&&(r.map=i,this.tuftTexture=i),TT(r,this.tuftTime,this.tuftStrength);let a=new rs(rE(),r,Math.max(n.length,1));a.count=n.length,a.castShadow=!1,a.receiveShadow=!0;let o=new b(this.seed+7403357),s=uE.set(this.colorA),c=dE.set(this.colorB);for(let e=0;e<n.length;e++){let t=n[e],r=1+(uw(t.x,t.z,this.seed)-1)*JT,i=this.height*KT*r*o.range(XT[0],XT[1]),l=i*qT*o.range(ZT[0],ZT[1]);sE.set(t.x,this.bedY(t.x,t.z),t.z),cE.setFromAxisAngle(aE,t.rotY),lE.set(l,i,l),a.setMatrixAt(e,oE.compose(sE,cE,lE));let u=iw(t.x,t.z),d=Math.min(1,Math.max(0,.5+.35*u.hue+(o.next()-.5)*.3)),f=Math.min(1,Math.max(0,dw(t.x,t.z,this.seed)*.8-.1));fE.copy(s).lerp(c,d).lerp(pE.set(QT),f*.5).multiplyScalar(o.range(.62,1.18)),a.setColorAt(e,fE)}a.instanceMatrix.needsUpdate=!0,a.instanceColor&&(a.instanceColor.needsUpdate=!0),this.meshes=[a]}buildBladesField(e){let t=pw({seed:this.seed,areaX:this.area[0]??0,areaZ:this.area[1]??0,count:e,density:this.density});this.benderSlots=Array.from({length:4},()=>new bi(0,0,0,0));let n=Zs.merge([Y.fog]);Object.assign(n,{time:{value:0},windStrength:{value:this.sway*MT},topColor:{value:new G(this.colorB)},bottomColor:{value:new G(this.colorA)},grassHeight:{value:this.height},grassScale:{value:1},benders:{value:this.benderSlots}}),this.bladesMaterial=new ec({vertexShader:eT,fragmentShader:tT,uniforms:n,fog:!0,transparent:!0,side:2,depthWrite:!0,depthTest:!0,alphaTest:.1,blending:0});let r=nE(this.height),i=new rs(r,this.bladesMaterial,Math.max(e,1)),a=new rs(r,this.bladesMaterial,Math.max(e,1));i.count=e,a.count=e,i.renderOrder=this.renderOrder,a.renderOrder=this.renderOrder;for(let n=0;n<e;n++){let e=t[n];sE.set(e.x,this.bedY(e.x,e.z),e.z),lE.setScalar(e.scale),cE.setFromAxisAngle(aE,e.rotY),i.setMatrixAt(n,oE.compose(sE,cE,lE)),cE.setFromAxisAngle(aE,e.rotY+Math.PI/2),a.setMatrixAt(n,oE.compose(sE,cE,lE))}i.instanceMatrix.needsUpdate=!0,a.instanceMatrix.needsUpdate=!0,this.meshes=[i,a]}buildSimpleField(e){let t=new nc({side:2,roughness:1}),n=new rs(iE(kT[this.kind]??.08),t,Math.max(e,1));n.count=e,n.receiveShadow=!0;let r=new b(this.seed),i=(this.area[0]??0)/2,a=(this.area[1]??0)/2,o=uE.set(this.colorA),s=dE.set(this.colorB);for(let t=0;t<e;t++){let e=r.range(-i,i),c=r.range(-a,a);sE.set(e,this.bedY(e,c),c),cE.setFromAxisAngle(aE,r.range(0,Math.PI*2)),lE.set(1,this.height*r.range(AT[0],AT[1]),1),oE.compose(sE,cE,lE),n.setMatrixAt(t,oE),n.setColorAt(t,fE.copy(o).lerp(s,r.next()))}n.instanceMatrix.needsUpdate=!0,n.instanceColor&&(n.instanceColor.needsUpdate=!0),this.meshes=[n]}disposeMeshes(){let e=new Set(this.meshes.map(e=>e.geometry)),t=new Set(this.meshes.map(e=>e.material));for(let e of this.meshes)e.removeFromParent(),e.dispose();for(let t of e)t.dispose();for(let e of t)e.dispose?.();this.bladesMaterial?.dispose(),this.bladesMaterial=null,this.benderSlots=null,this.tuftTexture?.dispose(),this.tuftTexture=null,this.tuftTime=null,this.tuftStrength=null,this.meshes=[]}free(){this.disposeMeshes(),this.pivot=null,super.free()}};function nE(e){let t=new Ws(1,e,1,1);return t.translate(0,e/2,0),t}function rE(){let e=[],t=[],n=[],r=[];for(let i=0;i<3;i++){let a=i*Math.PI/3,o=Math.cos(a)/2,s=Math.sin(a)/2,c=-Math.sin(a),l=Math.cos(a),u=i*4;e.push(-o,0,-s,o,0,s,-o,1,-s,o,1,s);for(let e=0;e<4;e++)t.push(c,0,l);n.push(0,0,1,0,0,1,1,1),r.push(u,u+1,u+3,u,u+3,u+2)}let i=new q;return i.setAttribute(`position`,new K(new Float32Array(e),3)),i.setAttribute(`normal`,new K(new Float32Array(t),3)),i.setAttribute(`uv`,new K(new Float32Array(n),2)),i.setIndex(r),i}function iE(e){let t=e/2,n=new Float32Array([-t,0,0,t,0,0,-t,1,0,t,1,0,0,0,-t,0,0,t,0,1,-t,0,1,t]),r=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0]),i=new q;return i.setAttribute(`position`,new K(n,3)),i.setAttribute(`normal`,new K(r,3)),i.setIndex([0,1,2,2,1,3,4,5,6,6,5,7]),i}var aE=new H(0,1,0),oE=new W,sE=new H,cE=new V,lE=new H,uE=new G,dE=new G,fE=new G,pE=new G,mE=[`color`,`metalness`,`roughness`,`emissive`,`emissiveIntensity`,`wireframe`,`flatShading`,`opacity`,`clearcoat`,`clearcoatRoughness`,`envMapIntensity`,`depthTest`,`depthWrite`,`map`,`normalMap`,`repeat`],hE=class extends qp{static typeName=`MeshInstance3D`;static props={mesh:{default:`box`,options:[`box`,`sphere`,`capsule`,`plane`,`cylinder`,`gem`]},size:{default:[1,1,1]},material:{default:{}},castShadow:{default:!1},receiveShadow:{default:!1}};mesh=`box`;size=[1,1,1];material={};castShadow=!1;receiveShadow=!1;static validateJson(e){_E(e.material,e.name)}geometryKey=``;textureKey=``;loadedTextures=[];_createObject3D(){return new jo(new Rs(1,1,1),new rc)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D(),t=`${this.mesh}:${JSON.stringify(this.size)}`;t!==this.geometryKey&&(e.geometry.dispose(),e.geometry=vE(this.mesh,this.size),this.geometryKey=t);let n=e.material;gE(n,this.material),this.syncTextures(n),e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow}syncTextures(e){let t=JSON.stringify([this.material.map??``,this.material.normalMap??``,this.material.repeat??null]);if(t===this.textureKey)return;this.textureKey=t;for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[];let n=e.map!==null||e.normalMap!==null;e.map=null,e.normalMap=null;let r=typeof document<`u`?new Ic:null;r&&this.material.map&&(e.map=this.loadTexture(r,this.material.map,!0)),r&&this.material.normalMap&&(e.normalMap=this.loadTexture(r,this.material.normalMap,!1)),(n||e.map||e.normalMap)&&(e.needsUpdate=!0)}loadTexture(e,t,n){let r=e.load(t);r.wrapS=It,r.wrapT=It;let[i,a]=this.material.repeat??[1,1];return r.repeat.set(i,a),r.anisotropy=4,n&&(r.colorSpace=dr),this.loadedTextures.push(r),r}free(){for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[],super.free()}};function gE(e,t){e.color.set(t.color??`#ffffff`),e.metalness=t.metalness??0,e.roughness=t.roughness??1,e.wireframe=t.wireframe??!1,e.emissive.set(t.emissive??`#000000`),e.emissiveIntensity=t.emissiveIntensity??1;let n=t.opacity??1;e.opacity=n,e.transparent=n<1;let r=t.clearcoat??0;e.clearcoat>0!=r>0&&(e.needsUpdate=!0),e.clearcoat=r,e.clearcoatRoughness=t.clearcoatRoughness??0,e.envMapIntensity=t.envMapIntensity??1,e.depthTest=t.depthTest??!0,e.depthWrite=t.depthWrite??!0;let i=t.flatShading??!1;e.flatShading!==i&&(e.flatShading=i,e.needsUpdate=!0)}function _E(e,t,n=`MeshInstance3D`){let r=e=>{throw new y(`BAD_FORMAT`,`${n} '${t}' ${e}`,{prop:`material`,validOptions:[...mE]})};(typeof e!=`object`||!e||Array.isArray(e))&&r(`material must be an object, got ${JSON.stringify(e)}.`);for(let t of Object.keys(e))mE.includes(t)||r(`material has unknown key '${t}' — must be one of [${mE.join(`, `)}].`);for(let t of[`map`,`normalMap`]){let n=e[t];n!==void 0&&(typeof n!=`string`||n.length===0)&&r(`material.${t} must be a non-empty texture URL string, got ${JSON.stringify(n)}.`)}if(e.repeat!==void 0){let t=e.repeat;(!Array.isArray(t)||t.length!==2||!t.every(e=>typeof e==`number`&&Number.isFinite(e)&&e>0))&&r(`material.repeat must be [u, v] with positive numbers, got ${JSON.stringify(t)}.`),!e.map&&!e.normalMap&&r(`material.repeat tiles nothing — add a 'map' and/or 'normalMap' texture URL.`)}for(let t of[`metalness`,`roughness`,`opacity`,`clearcoat`,`clearcoatRoughness`]){let n=e[t];n!==void 0&&!(typeof n==`number`&&n>=0&&n<=1)&&r(`material.${t} must be a number in 0..1, got ${JSON.stringify(n)}.`)}e.envMapIntensity!==void 0&&!(typeof e.envMapIntensity==`number`&&Number.isFinite(e.envMapIntensity)&&e.envMapIntensity>=0)&&r(`material.envMapIntensity must be a number >= 0, got ${JSON.stringify(e.envMapIntensity)}.`);for(let t of[`wireframe`,`flatShading`,`depthTest`,`depthWrite`]){let n=e[t];n!==void 0&&typeof n!=`boolean`&&r(`material.${t} must be a boolean, got ${JSON.stringify(n)}.`)}}function vE(e,t){let n=t[0]??1,r=t[1]??1,i=t[2]??1;switch(e){case`box`:return new Rs(n,r,i);case`sphere`:return new Gs(n,32,16);case`gem`:return new Us(n,0);case`capsule`:return new zs(n,r,8,16);case`plane`:{let e=new Ws(n,i);return e.rotateX(-Math.PI/2),e}case`cylinder`:return new Bs(n,n,r,24);default:throw new y(`PROP_TYPE_MISMATCH`,`MeshInstance3D.mesh must be one of box|sphere|capsule|plane|cylinder|gem, got '${e}'.`)}}var yE=class extends qp{static typeName=`InstancedMesh3D`;static props={mesh:{default:`box`,options:[`box`,`sphere`,`capsule`,`plane`,`cylinder`,`gem`]},size:{default:[1,1,1]},material:{default:{}},transforms:{default:[]},castShadow:{default:!1},receiveShadow:{default:!1}};mesh=`box`;size=[1,1,1];material={};castShadow=!1;receiveShadow=!1;_transforms=[];transformsDirty=!0;get transforms(){return this._transforms}set transforms(e){this._transforms=e,this.transformsDirty=!0}instanced=null;builtKey=``;static validateJson(e){let t=e;_E(t.material,e.name);for(let[n,r]of t._transforms.entries())if(!Array.isArray(r)||r.length<3||r.length>5||r.some(e=>typeof e!=`number`))throw new y(`BAD_FORMAT`,`InstancedMesh3D '${e.name}': transforms[${n}] must be [x, y, z, yawDeg?, scale?] (numbers), got ${JSON.stringify(r)}.`)}get instanceCount(){return this.instanced?.count??0}_syncObject3D(e){super._syncObject3D(e);let t=this._ensureObject3D(),n=`${this.mesh} ${JSON.stringify(this.size)} ${this._transforms.length}`;if(n!==this.builtKey){if(this.builtKey=n,this.instanced&&=(t.remove(this.instanced),this.instanced.geometry.dispose(),this.instanced.material.dispose(),null),this._transforms.length>0){let e=vE(this.mesh,this.size),n=new rc;this.instanced=new rs(e,n,this._transforms.length),this.instanced.instanceMatrix.setUsage(_r),t.add(this.instanced)}this.transformsDirty=!0}let r=this.instanced;if(r&&(r.castShadow=this.castShadow,r.receiveShadow=this.receiveShadow,gE(r.material,this.material),this.transformsDirty)){this.transformsDirty=!1;for(let e=0;e<this._transforms.length;e++){let t=this._transforms[e];xE.set(t[0]??0,t[1]??0,t[2]??0),SE.setFromAxisAngle(bE,(t[3]??0)*Math.PI/180);let n=t[4]??1;CE.set(n,n,n),wE.compose(xE,SE,CE),r.setMatrixAt(e,wE)}r.instanceMatrix.needsUpdate=!0,r.computeBoundingSphere()}}free(){this.instanced&&(this.instanced.geometry.dispose(),this.instanced.material.dispose()),super.free()}},bE=new H(0,1,0),xE=new H,SE=new V,CE=new H,wE=new W,TE=class extends qp{static typeName=`DirectionalLight3D`;static props={color:{default:`#ffffff`},intensity:{default:1},castShadow:{default:!1},shadowArea:{default:75},shadowMapSize:{default:2048},shadowFollowsCamera:{default:!1}};color=`#ffffff`;intensity=1;castShadow=!1;shadowArea=75;shadowMapSize=2048;shadowFollowsCamera=!1;_createObject3D(){return new nl}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();if(e.color.set(this.color),e.intensity=this.intensity,e.castShadow=this.castShadow,this.castShadow&&`shadow`in e){let t=e.shadow.camera;`left`in t&&(t.left=-this.shadowArea,t.right=this.shadowArea,t.top=this.shadowArea,t.bottom=-this.shadowArea,t.near=.5,t.far=500,t.updateProjectionMatrix()),e.shadow.mapSize.set(this.shadowMapSize,this.shadowMapSize),e.shadow.bias=-2e-4,e.shadow.normalBias=.002}}},EE=class extends qp{static typeName=`OmniLight3D`;static props={color:{default:`#ffffff`},intensity:{default:1},range:{default:0}};color=`#ffffff`;intensity=1;range=0;_createObject3D(){return new $c}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();e.color.set(this.color),e.intensity=this.intensity,e.distance=this.range}},DE=class extends qp{static typeName=`LoftMesh3D`;static props={sections:{default:[]},slices:{default:24},smooth:{default:4},material:{default:{}},castShadow:{default:!1},receiveShadow:{default:!1}};sections=[];slices=24;smooth=4;material={};castShadow=!1;receiveShadow=!1;static validateJson(e){let t=e;OE(t.sections,e.name),_E(t.material,e.name,`LoftMesh3D`);for(let n of[`map`,`normalMap`,`repeat`])if(t.material[n]!==void 0)throw new y(`BAD_FORMAT`,`LoftMesh3D '${e.name}' material does not support '${n}' — a loft has no UVs; use color/metalness/roughness/clearcoat/envMapIntensity instead.`,{prop:`material`})}geometryKey=``;_createObject3D(){return new jo(new q,new rc)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D(),t=JSON.stringify([this.sections,this.slices,this.smooth]);t!==this.geometryKey&&this.sections.length>=2&&(e.geometry.dispose(),e.geometry=jE(this.sections,this.slices,this.smooth),this.geometryKey=t),gE(e.material,this.material),e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow}};function OE(e,t){let n=e=>{throw new y(`BAD_FORMAT`,`LoftMesh3D '${t}' ${e}`,{prop:`sections`})};(!Array.isArray(e)||e.length<2)&&n(`sections needs at least 2 stations, got ${JSON.stringify(e)}.`);for(let[t,r]of e.entries()){(typeof r!=`object`||!r)&&n(`sections[${t}] must be an object.`);for(let e of[`z`,`width`,`height`,`y`])(typeof r[e]!=`number`||!Number.isFinite(r[e]))&&n(`sections[${t}].${e} must be a finite number, got ${JSON.stringify(r[e])}.`);(r.width<=0||r.height<=0)&&n(`sections[${t}] width/height must be positive, got ${r.width}×${r.height}.`),r.corner!==void 0&&!(typeof r.corner==`number`&&r.corner>=0&&r.corner<=1)&&n(`sections[${t}].corner must be in 0..1, got ${JSON.stringify(r.corner)}.`),t>0&&r.z<=e[t-1].z&&n(`sections[].z must be strictly ascending (sections[${t}].z=${r.z}).`)}}function kE(e,t,n,r,i){let a=i*i,o=a*i;return .5*(2*t+(n-e)*i+(2*e-5*t+4*n-r)*a+(-e+3*t-3*n+r)*o)}function AE(e,t){let n=t=>{let n=e[Math.max(0,Math.min(e.length-1,t))];return{z:n.z,width:n.width,height:n.height,y:n.y,corner:n.corner??.7}},r=[];for(let i=0;i<e.length-1;i++){let a=n(i-1),o=n(i),s=n(i+1),c=n(i+2),l=i===e.length-2?t+1:t;for(let e=0;e<l;e++){let n=e/t;r.push({z:kE(a.z,o.z,s.z,c.z,n),width:Math.max(1e-4,kE(a.width,o.width,s.width,c.width,n)),height:Math.max(1e-4,kE(a.height,o.height,s.height,c.height,n)),y:kE(a.y,o.y,s.y,c.y,n),corner:Math.min(1,Math.max(0,kE(a.corner,o.corner,s.corner,c.corner,n)))})}}return r}function jE(e,t,n){let r=Math.max(8,Math.min(64,Math.round(t))),i=AE(e,Math.max(1,Math.min(16,Math.round(n)))),a=i.length,o=new Float32Array((a*r+2)*3),s=i[0],c=i[a-1];o.set([0,s.y,s.z],0),o.set([0,c.y,c.z],3);for(let e=0;e<a;e++){let t=i[e],n=8-6*t.corner,a=Math.max(n,5);for(let i=0;i<r;i++){let s=i/r*Math.PI*2,c=Math.cos(s),l=Math.sin(s),u=l>=0?n:a,d=t.width/2*Math.sign(c)*Math.abs(c)**(2/u),f=t.height/2*Math.sign(l)*Math.abs(l)**(2/u),p=(2+e*r+i)*3;o[p]=d,o[p+1]=t.y+f,o[p+2]=t.z}}let l=[],u=(e,t)=>2+e*r+t%r;for(let e=0;e<a-1;e++)for(let t=0;t<r;t++){let n=u(e,t),r=u(e,t+1),i=u(e+1,t),a=u(e+1,t+1);l.push(n,r,i,r,a,i)}for(let e=0;e<r;e++)l.push(0,u(0,e+1),u(0,e)),l.push(1,u(a-1,e),u(a-1,e+1));let d=new q;return d.setAttribute(`position`,new K(o,3)),d.setIndex(l),d.computeVertexNormals(),d}function ME(e){let t=e.lastIndexOf(`.`);return t===-1?e:e.slice(0,t)}function NE(e,t,n){let r=e.tracks.filter(e=>{let r=t.has(ME(e.name));return n===`keep`?r:!r});return new Cc(`${e.name}#${n}`,e.duration,r)}function PE(e){let t=new Set,n=e=>{t.add(e.name);for(let t of e.children)n(t)};return n(e),t}var FE={Hips:`hips`,Spine:`spine`,Spine1:`chest`,Spine2:`upperChest`,Neck:`neck`,Head:`head`,LeftShoulder:`leftShoulder`,LeftArm:`leftUpperArm`,LeftForeArm:`leftLowerArm`,LeftHand:`leftHand`,RightShoulder:`rightShoulder`,RightArm:`rightUpperArm`,RightForeArm:`rightLowerArm`,RightHand:`rightHand`,LeftUpLeg:`leftUpperLeg`,LeftLeg:`leftLowerLeg`,LeftFoot:`leftFoot`,LeftToeBase:`leftToes`,RightUpLeg:`rightUpperLeg`,RightLeg:`rightLowerLeg`,RightFoot:`rightFoot`,RightToeBase:`rightToes`,LeftHandThumb1:`leftThumbMetacarpal`,LeftHandThumb2:`leftThumbProximal`,LeftHandThumb3:`leftThumbDistal`,LeftHandIndex1:`leftIndexProximal`,LeftHandIndex2:`leftIndexIntermediate`,LeftHandIndex3:`leftIndexDistal`,LeftHandMiddle1:`leftMiddleProximal`,LeftHandMiddle2:`leftMiddleIntermediate`,LeftHandMiddle3:`leftMiddleDistal`,LeftHandRing1:`leftRingProximal`,LeftHandRing2:`leftRingIntermediate`,LeftHandRing3:`leftRingDistal`,LeftHandPinky1:`leftLittleProximal`,LeftHandPinky2:`leftLittleIntermediate`,LeftHandPinky3:`leftLittleDistal`,RightHandThumb1:`rightThumbMetacarpal`,RightHandThumb2:`rightThumbProximal`,RightHandThumb3:`rightThumbDistal`,RightHandIndex1:`rightIndexProximal`,RightHandIndex2:`rightIndexIntermediate`,RightHandIndex3:`rightIndexDistal`,RightHandMiddle1:`rightMiddleProximal`,RightHandMiddle2:`rightMiddleIntermediate`,RightHandMiddle3:`rightMiddleDistal`,RightHandRing1:`rightRingProximal`,RightHandRing2:`rightRingIntermediate`,RightHandRing3:`rightRingDistal`,RightHandPinky1:`rightLittleProximal`,RightHandPinky2:`rightLittleIntermediate`,RightHandPinky3:`rightLittleDistal`},IE={};for(let[e,t]of Object.entries(FE))IE[`mixamorig${e}`]=t,IE[`mixamorig:${e}`]=t;function LE(e,t,n){let r=[],i=new Set,a=new V,o=new V,s=new V,c=n.meta?.metaVersion===`0`,l=t.getObjectByName(`mixamorigHips`)??t.getObjectByName(`mixamorig:Hips`),u=n.humanoid?.getNormalizedBoneNode(`hips`),d=l&&u?Math.abs(u.getWorldPosition(new H).y)/Math.max(1e-6,Math.abs(l.getWorldPosition(new H).y)):1;for(let l of e.tracks){let e=l.name.lastIndexOf(`.`),u=l.name.slice(0,e),f=l.name.slice(e+1),p=IE[u],m=p?n.humanoid?.getNormalizedBoneNode(p)?.name:void 0,h=t.getObjectByName(u);if(!m||!h){i.add(u);continue}if(h.getWorldQuaternion(a).invert(),h.parent?h.parent.getWorldQuaternion(o):o.identity(),l instanceof bc&&f===`quaternion`){let e=Float32Array.from(l.values);for(let t=0;t<e.length;t+=4)s.set(e[t]??0,e[t+1]??0,e[t+2]??0,e[t+3]??1),s.premultiply(o).multiply(a),e[t]=c?-s.x:s.x,e[t+1]=s.y,e[t+2]=c?-s.z:s.z,e[t+3]=s.w;r.push(new bc(`${m}.quaternion`,[...l.times],[...e]))}else if(l instanceof Sc&&f===`position`){let e=Float32Array.from(l.values);for(let t=0;t<e.length;t+=3)e[t]=(c?-(e[t]??0):e[t]??0)*d,e[t+1]=(e[t+1]??0)*d,e[t+2]=(c?-(e[t+2]??0):e[t+2]??0)*d;r.push(new Sc(`${m}.position`,[...l.times],[...e]))}}return{clip:new Cc(`${e.name} (VRM)`,e.duration,r),retargetedTracks:r.length,skippedBones:[...i]}}var RE=.2,zE=.12,BE=class extends qp{static typeName=`ModelInstance3D`;static signals=[`animationFinished`];static props={...qp.props,model:{default:``},animation:{default:``},targetHeight:{default:0},castShadow:{default:!1},animationLoop:{default:!0},animationUpper:{default:``},animationUpperLoop:{default:!1},upperBodyRoot:{default:`Spine`},receiveShadow:{default:!1},tint:{default:``},metalness:{default:-1},roughness:{default:-1}};model=``;animation=``;targetHeight=0;castShadow=!1;animationLoop=!0;animationUpper=``;animationUpperLoop=!1;upperBodyRoot=`Spine`;receiveShadow=!1;tint=``;metalness=-1;roughness=-1;store=null;entry=null;mountedRef=``;fittedHeight=-1;fitGroup=null;mixer=null;playing=``;currentAction=null;playingUpper=``;upperAction=null;baseMode=`full`;maskCache=new Map;actionKeys=new WeakMap;warnedClaim=!1;tintTargets=[];tintedClones=[];appliedMods=``;nodePoses=new Map;poseNode(e,t){this.nodePoses.set(e,t),this.applyPoses()}_createObject3D(){return new Qi}findBone(e){let t=this.fitGroup;if(!t||e===``)return null;let n=t.getObjectByName(e)??t.getObjectByName(`mixamorig${e}`)??t.getObjectByName(`mixamorig:${e}`);if(n)return n;let r=e.toLowerCase(),i=null;return t.traverse(e=>{!i&&e.name.toLowerCase().endsWith(r)&&(i=e)}),i}boneNames(){let e=[];return this.fitGroup?.traverse(t=>{t.isBone&&e.push(t.name)}),e}availableAnimations(){let e=this.entry?.animations.map(e=>e.name)??[],t=this.store?.animationRefs()??[];return[...e,...t]}_syncModel(e){this.store=e;let t=this._ensureObject3D();if(this.model===``){this.fitGroup&&this.unmount(t);return}let n=e.getModel(this.model);if(!(n.status!==`ready`||!n.scene)){if(this.mountedRef!==this.model){this.unmount(t);let e;if(n.isVrm){if(n.claimedBy&&n.claimedBy!==this){this.warnedClaim||(this.warnedClaim=!0,console.warn(`incanto: VRM '${this.model}' is already displayed by another node — a VRM asset can back only one ModelInstance3D.`));return}n.claimedBy=this,e=n.scene}else e=Ab(n.scene);let r=new Qi;r.add(e),t.add(r),this.fitGroup=r,this.entry=n,this.mountedRef=this.model,this.mixer=new El(e),this.mixer.addEventListener(`finished`,e=>{let t=e.action,n=(t&&this.actionKeys.get(t))??this.animation;t&&t===this.upperAction&&(t.fadeOut(zE),this.upperAction=null,this.playingUpper=``,this.animationUpper=``),this.emit(`animationFinished`,n)}),this.playing=``,this.currentAction=null,this.fittedHeight=-1,e.traverse(e=>{e.userData.incantoModelShared=!0}),this.tintTargets=[],this.tintedClones=[],this.appliedMods=``,e.traverse(e=>{let t=e;t.isMesh&&t.material&&this.tintTargets.push({mesh:t,original:t.material})})}if(this.fitGroup&&this.fittedHeight!==this.targetHeight)if(this.fittedHeight=this.targetHeight,this.targetHeight>0){let e=this.fitGroup.scale.x;this.fitGroup.scale.setScalar(1);let t=VE(this.fitGroup).getSize(new H),n=t.y>0?this.targetHeight/t.y:e;n<.05||n>20?(this.fitGroup.scale.setScalar(1),console.warn(`[incanto] ModelInstance3D '${this.name}': targetHeight fit measured an implausible scale (${n.toFixed(2)}x) — skinned rigs defeat bounding-box measurement. Rendering at the model's authored scale instead.`)):this.fitGroup.scale.setScalar(n)}else this.fitGroup.scale.setScalar(1);this.fitGroup&&this.fitGroup.traverse(e=>{let t=e;t.isMesh&&(t.castShadow=this.castShadow,t.receiveShadow=this.receiveShadow)}),this.applyMaterialMods(),this.applyPoses(),this.syncAnimation(e),this.syncUpperAnimation(e)}}applyMaterialMods(){let e=`${this.tint}|${this.metalness}|${this.roughness}`;if(e===this.appliedMods)return;for(let e of this.tintedClones)e.dispose();this.tintedClones=[];let t=this.tint?new G(this.tint):null,n=t!==null||this.metalness>=0||this.roughness>=0;for(let e of this.tintTargets){if(!n){e.mesh.material=e.original;continue}let r=e=>{let n=e.clone();if(t){let r=n,i=e.color;r.color&&=i?i.clone().multiply(t):t.clone()}let r=n;return this.metalness>=0&&typeof r.metalness==`number`&&(r.metalness=this.metalness),this.roughness>=0&&typeof r.roughness==`number`&&(r.roughness=this.roughness),n.userData.incantoTinted=!0,this.tintedClones.push(n),n};e.mesh.material=Array.isArray(e.original)?e.original.map(r):r(e.original)}this.appliedMods=e}applyPoses(){if(!this.fitGroup||this.nodePoses.size===0)return;let e=Math.PI/180;for(let[t,n]of this.nodePoses){let r=this.fitGroup.getObjectByName(t);r&&r.rotation.set(n[0]*e,n[1]*e,n[2]*e)}}resolveClip(e,t){if(!this.entry)return null;let n=this.entry.animations.find(t=>t.name===e);if(n)return n;if(!(e.startsWith(`$`)||/\.(glb|gltf)$/i.test(e)))return null;let r=t.getAnimation(e);if(r.status===`loading`)return`loading`;if(r.status!==`ready`||!r.scene)return null;let i=(r.clip?r.clips.find(e=>e.name===r.clip):void 0)??r.clips[0];if(!i)return null;if(this.entry.isVrm&&this.entry.vrm){let t=this.entry.retargeted.get(e);if(t)return t;let n=LE(i,r.scene,this.entry.vrm);return n.skippedBones.length>0&&console.warn(`incanto: retarget '${e}' skipped bones: ${n.skippedBones.join(`, `)}`),this.entry.retargeted.set(e,n.clip),n.clip}return i}layerVariants(e){let t=this.findBone(this.upperBodyRoot);if(!t)return null;let n=`${e.uuid} ${t.name}`,r=this.maskCache.get(n);if(!r){let i=PE(t);r={upper:NE(e,i,`keep`),lower:NE(e,i,`drop`)},this.maskCache.set(n,r)}return r}upperLayerActive(){return this.animationUpper!==``||this.upperAction!==null}syncAnimation(e){if(!this.mixer||!this.entry)return;let t=this.upperLayerActive()?`lower`:`full`;if(this.playing===this.animation&&this.baseMode===t)return;if(this.animation===``){this.currentAction&&this.currentAction.fadeOut(RE),this.currentAction=null,this.playing=``,this.baseMode=t;return}let n=this.resolveClip(this.animation,e);if(n===`loading`)return;let r=n;if(r&&t===`lower`){let e=this.layerVariants(r);e&&(r=e.lower)}let i=this.playing===this.animation;if(this.playing=this.animation,this.baseMode=t,r){let e=this.mixer.clipAction(r);if(e.reset(),this.animationLoop?e.setLoop(Qn,1/0):(e.setLoop(Zn,1),e.clampWhenFinished=!0),e.setEffectiveWeight(1),e.play(),this.actionKeys.set(e,this.animation),this.currentAction&&this.currentAction!==e){i&&r.duration>0&&(e.time=this.currentAction.time%r.duration);let t=r.duration>0&&this.currentAction.getClip().duration>0;e.crossFadeFrom(this.currentAction,RE,t)}this.currentAction=e}else console.warn(`incanto: model '${this.model}' has no animation '${this.animation}' — embedded: ${this.entry.animations.map(e=>e.name).join(`, `)||`(none)`}; assets: ${e.animationRefs().join(`, `)||`(none)`}`)}syncUpperAnimation(e){if(!this.mixer||!this.entry||this.playingUpper===this.animationUpper)return;if(this.animationUpper===``){this.upperAction?.fadeOut(zE),this.upperAction=null,this.playingUpper=``;return}let t=this.resolveClip(this.animationUpper,e);if(t===`loading`)return;if(!t){console.warn(`incanto: model '${this.model}' has no animation '${this.animationUpper}' for the upper layer.`),this.playingUpper=this.animationUpper;return}let n=this.layerVariants(t);if(!n){console.warn(`incanto: upperBodyRoot '${this.upperBodyRoot}' not found in '${this.model}' — upper layer skipped.`),this.playingUpper=this.animationUpper;return}let r=this.mixer.clipAction(n.upper);r.reset(),this.animationUpperLoop?r.setLoop(Qn,1/0):(r.setLoop(Zn,1),r.clampWhenFinished=!0),r.setEffectiveWeight(1),r.fadeIn(zE),r.play(),this.actionKeys.set(r,this.animationUpper),this.upperAction&&this.upperAction!==r&&this.upperAction.fadeOut(zE),this.upperAction=r,this.playingUpper=this.animationUpper}update(e){this.mixer?.update(e),this.entry?.isVrm&&this.entry.claimedBy===this&&this.entry.vrm?.update(e)}onExitTree(){this.unmount(this._ensureObject3D())}unmount(e){this.entry?.claimedBy===this&&(this.entry.claimedBy=null),this.fitGroup&&e.remove(this.fitGroup);for(let e of this.tintedClones)e.dispose();this.tintedClones=[],this.tintTargets=[],this.appliedMods=``,this.fitGroup=null,this.mixer=null,this.currentAction=null,this.upperAction=null,this.playingUpper=``,this.baseMode=`full`,this.maskCache.clear(),this.entry=null,this.mountedRef=``,this.playing=``,this.fittedHeight=-1}};function VE(e){e.updateWorldMatrix(!0,!0);let t=new Sa,n=new Sa,r=e.matrixWorld.clone().invert(),i=new W,a=new H;return e.traverse(e=>{let o=e;if(o.isSkinnedMesh&&o.skeleton){for(let e of o.skeleton.boneInverses)i.copy(e).invert().premultiply(o.matrixWorld).premultiply(r),a.setFromMatrixPosition(i),t.expandByPoint(a);return}let s=e;s.isMesh&&s.geometry&&(s.geometry.computeBoundingBox(),s.geometry.boundingBox&&(n.copy(s.geometry.boundingBox).applyMatrix4(s.matrixWorld).applyMatrix4(r),t.union(n)))}),t}var HE=.01,UE=class e extends qp{orderGroup=`effects`;static typeName=`Particles3D`;static signals=[`finished`];static props={orderGroup:{default:`effects`,options:[`background`,`terrain`,`default`,`characters`,`effects`,`overlay`]},preset:{default:`custom`,options:[`custom`,...it]},emitting:{default:!0},rate:{default:40},burst:{default:0},lifetime:{default:[.6,1.2]},speed:{default:[40,120]},directionDeg:{default:-90},spreadDeg:{default:30},gravity:{default:[0,0]},drag:{default:0},sizeStart:{default:8},sizeEnd:{default:2},colorStart:{default:`#ffffff`},colorEnd:{default:`#ffffff`},paletteColors:{default:[]},alphaStart:{default:1},alphaEnd:{default:0},shimmer:{default:0},blend:{default:`add`,options:[`add`,`normal`]},depthTest:{default:!0},maxParticles:{default:256}};preset=`custom`;emitting=!0;rate=40;burst=0;lifetime=[.6,1.2];speed=[40,120];directionDeg=-90;spreadDeg=30;gravity=[0,0];drag=0;sizeStart=8;sizeEnd=2;colorStart=`#ffffff`;colorEnd=`#ffffff`;paletteColors=[];alphaStart=1;alphaEnd=0;shimmer=0;blend=`add`;depthTest=!0;maxParticles=256;static validateJson(e){let t=e;if(t.preset!==`custom`&&!it.includes(t.preset))throw new y(`BAD_FORMAT`,`Particles3D '${e.name}' preset must be 'custom' or one of [${it.join(`, `)}], got '${t.preset}'.`,{prop:`preset`,validOptions:it});if(t.blend!==`add`&&t.blend!==`normal`)throw new y(`BAD_FORMAT`,`Particles3D '${e.name}' blend must be 'add' or 'normal', got '${t.blend}'.`,{prop:`blend`,validOptions:[`add`,`normal`]})}sim=null;bursted=!1;finishedEmitted=!1;_ensureSim(){if(!this.sim){at(this,this.preset,ge(e.typeName));let t=this.tree?.engine?.rng??new b(4660);this.sim=new st({rate:this.emitting?this.rate:0,lifetime:[this.lifetime[0]??1,this.lifetime[1]??1],speed:[(this.speed[0]??0)*HE,(this.speed[1]??0)*HE],directionDeg:this.directionDeg,spreadDeg:this.spreadDeg,gravity:[(this.gravity[0]??0)*HE,(this.gravity[1]??0)*HE,(this.gravity[2]??0)*HE],drag:this.drag,maxParticles:this.maxParticles,spreadZ:!0},t)}return this.sim}update(e){let t=this._ensureSim();t.setRate(this.emitting?this.rate:0),this.burst>0&&!this.bursted&&(this.bursted=!0,t.burst(this.burst)),t.update(e),(!this.emitting||this.rate===0)&&this.bursted&&t.done&&!this.finishedEmitted&&(this.finishedEmitted=!0,this.emit(`finished`))}replay(){this.bursted=!1,this.finishedEmitted=!1}points=null;positions=null;colors=null;paletteCache=[];paletteCacheKey=``;_syncObject3D(){super._syncObject3D(),this.syncParticles()}refreshPalette(){let e=this.paletteColors;if(e.length===0)return null;let t=e.join(`|`);if(t!==this.paletteCacheKey){this.paletteCacheKey=t;for(let t=0;t<e.length;t++){let n=this.paletteCache[t];n||(n=new G,this.paletteCache[t]=n),n.set(e[t])}this.paletteCache.length=e.length}return this.paletteCache}syncParticles(){let e=this._ensureSim();if(!this.points||(this.positions?.length??0)!==this.maxParticles*3){this.points?.removeFromParent(),this.positions=new Float32Array(this.maxParticles*3),this.colors=new Float32Array(this.maxParticles*4);let e=new q;e.setAttribute(`position`,new K(this.positions,3)),e.setAttribute(`color`,new K(this.colors,4));let t=new Es({size:(this.sizeStart+this.sizeEnd)/2*HE,map:JE(),vertexColors:!0,transparent:!0,depthWrite:!1,depthTest:this.depthTest,alphaTest:.02,sizeAttenuation:!0,blending:this.blend===`add`?2:1});this.points=new js(e,t),this.points.frustumCulled=!1,this._ensureObject3D().add(this.points)}this.points.renderOrder=this.renderOrder;let t=this.points.material;t.depthTest=this.depthTest,t.blending=this.blend===`add`?2:1;let n=this.positions,r=this.colors,i=this.refreshPalette(),a=i?null:WE.set(this.colorStart),o=GE.set(this.colorEnd),s=this.shimmer,c=0;e.forEach(e=>{n[c*3]=e.x,n[c*3+1]=-e.y,n[c*3+2]=e.z;let t=i?i[Math.floor(e.seed*i.length)]:a,l=Math.max(0,this.alphaStart+(this.alphaEnd-this.alphaStart)*e.t);s>0&&(l*=.5+.5*Math.sin(2*Math.PI*(e.age*s+e.seed))),KE.copy(t).lerp(o,e.t),r[c*4]=KE.r,r[c*4+1]=KE.g,r[c*4+2]=KE.b,r[c*4+3]=l,c+=1});let l=this.points.geometry;l.setDrawRange(0,c),l.getAttribute(`position`).needsUpdate=!0,l.getAttribute(`color`).needsUpdate=!0}},WE=new G,GE=new G,KE=new G,qE=null;function JE(){if(qE)return qE;let e=63/2,t=new Uint8Array(4096*4);for(let n=0;n<64;n++)for(let r=0;r<64;r++){let i=(r-e)/e,a=(n-e)/e,o=Math.hypot(i,a),s=.35,c;if(o<=s)c=1;else{let e=Math.max(0,1-(o-s)/(1-s));c=e*e}let l=Math.round(c*255),u=(n*64+r)*4;t[u]=255,t[u+1]=255,t[u+2]=255,t[u+3]=l}let n=new Go(t,64,64,sn);return n.magFilter=Ht,n.minFilter=Ht,n.generateMipmaps=!1,n.needsUpdate=!0,qE=n,n}var YE=24,XE=3,ZE=4,QE=.05,$E=12,eD=14,tD=3,nD=5,rD=.04,iD=2;function aD(e,t){return Math.max(e*tD,e+t*nD)}function oD(e,t){let n=e.map(e=>({x:e[0]??0,z:e[1]??0})).filter((e,t,n)=>t===0||Math.hypot(e.x-(n[t-1]?.x??0),e.z-(n[t-1]?.z??0))>1e-6);if(n.length<2||t<=0)return[];let r=[],i=0;for(let e=0;e<n.length-1;e++){let t=n[Math.max(0,e-1)],a=n[e],o=n[e+1],s=n[Math.min(n.length-1,e+2)];for(let e=0;e<YE;e++){let n=e/YE,c=mD(t.x,a.x,o.x,s.x,n),l=mD(t.z,a.z,o.z,s.z,n),u=r[r.length-1];u&&(i+=Math.hypot(c-u.x,l-u.z)),r.push({x:c,z:l,along:i})}}let a=n[n.length-1],o=r[r.length-1];o&&(i+=Math.hypot(a.x-o.x,a.z-o.z)),r.push({x:a.x,z:a.z,along:i});let s=i;if(s<1e-6)return[];let c=Math.max(1,Math.round(s/t)),l=s/c,u=[],d=0;for(let e=0;e<=c;e++){let t=Math.min(e*l,s);for(;d<r.length-2&&r[d+1].along<t;)d++;let n=r[d],i=r[Math.min(d+1,r.length-1)],a=i.along-n.along,o=a>1e-9?(t-n.along)/a:0;u.push({x:n.x+(i.x-n.x)*o,z:n.z+(i.z-n.z)*o,tx:1,tz:0,along:t})}for(let e=0;e<u.length;e++){let t=u[Math.max(0,e-1)],n=u[Math.min(u.length-1,e+1)],r=n.x-t.x,i=n.z-t.z,a=Math.hypot(r,i)||1,o=u[e];o.tx=r/a,o.tz=i/a}return u}function sD(e,t){if(e.length===0)return 0;if(e.length===1)return e[0];let n=Math.min(Math.max(t,0),1)*(e.length-1),r=Math.min(Math.floor(n),e.length-2),i=n-r,a=e[r];return a+(e[r+1]-a)*i}function cD(e){let t=oD(e.path,e.step);if(t.length===0)return[];let n=t[t.length-1].along||1,r=t.map(t=>Math.max(sD(e.widths,t.along/n),.05)/2),i=t.map(t=>e.bedAt(t.x,t.z)),a=Array(i.length);for(let e=0;e<i.length;e++){let t=i[e];a[e]=e===0?t:Math.min(t,a[e-1])}let o=Math.max(.5,e.depth*1.5),s=a.map((e,t)=>{let n=0,r=0;for(let i=-3;i<=XE;i++){let s=a[Math.min(Math.max(t+i,0),a.length-1)];Math.abs(s-e)>o||(n+=s,r++)}return r>0?n/r:e}),c=Array(s.length);for(let e=0;e<s.length;e++){let t=s[e];c[e]=e===0?t:Math.min(t,c[e-1])}let l=e.fit===!0,u=Array(t.length),d=Array(t.length);for(let n=0;n<t.length;n++){let i=t[n],a=c[n]+e.depth;if(!l){d[n]=[1/0,1/0],u[n]=a;continue}let o=aD(r[n],e.depth),s=-i.tz,f=i.tx,p=-1/0,m=-1/0;for(let t=1;t<=eD;t++){let n=t/eD*o;p=Math.max(p,e.bedAt(i.x+s*n,i.z+f*n)),m=Math.max(m,e.bedAt(i.x-s*n,i.z-f*n))}d[n]=[p,m],u[n]=Math.min(a,p,m)}for(let e=0;e<u.length;e++){let t=u[e];l&&(t=Math.max(t,i[e]+rD)),e>0&&(t=Math.min(t,u[e-1]));let n=d[e];t=Math.min(t,Math.max(Math.min(n[0],n[1]),i[e]+rD)),u[e]=t}let f=t.map((t,n)=>{let i=r[n];if(!l)return[i,i];let a=aD(i,e.depth),o=u[n],s=-t.tz,c=t.tx,d=n=>{for(let r=1;r<=eD;r++){let i=r/eD*a;if(e.bedAt(t.x+s*i*n,t.z+c*i*n)>=o)return i}return-i};return[d(1),d(-1)]}),p=f.map((e,t)=>{let n=0,r=0,i=0;for(let e=-2;e<=iD;e++){let a=f[Math.min(Math.max(t+e,0),f.length-1)];n+=Math.abs(a[0]),r+=Math.abs(a[1]),i++}let a=f[t];return[Math.min(n/i,Math.abs(a[0])),Math.min(r/i,Math.abs(a[1]))]}),m=r.reduce((e,t)=>e+t,0)/r.length||1;return t.map((n,i)=>{let a=u[i],o=Math.max(0,i-1),s=Math.min(t.length-1,i+1),c=t[s].along-t[o].along,l=(u[o]-u[s])/(c||1),d=Math.max(0,l),h=r[i],g=p[i],_=Math.min(Math.max(e.flowSpeed*Math.sqrt(m/h)*(1+ZE*d),QE),$E),v=f[i];return{...n,halfWidth:h,halfLeft:Math.max(g[0],.05),halfRight:Math.max(g[1],.05),spillLeft:v[0]<0,spillRight:v[1]<0,surfaceY:a,slope:d,speed:_}})}function lD(e,t){let n=Math.max(1,Math.round(t.acrossSegments)),r=n+1,i=e.length*r,a=new Float32Array(i*3),o=new Float32Array(i*3),s=new Float32Array(i*2),c=new Float32Array(i*2),l=new Float32Array(i*4),u=Math.max(0,e.length-1)*n,d=new Uint32Array(u*6);for(let i=0;i<e.length;i++){let u=e[i],d=Math.max(u.surfaceY-uD(t,u.x,u.z),rD),f=-u.tz,p=u.tx,m=Math.hypot(u.slope,1),h=u.tx*u.slope/m,g=1/m,_=u.tz*u.slope/m;for(let e=0;e<=n;e++){let m=e/n*2-1,v=m*(m<0?u.halfRight:u.halfLeft)*t.bankOvershoot,y=u.x+f*v,b=u.z+p*v,x=i*r+e,S=uD(t,y,b),C=(m<0?u.spillRight:u.spillLeft)?d+(rD-d)*Math.abs(m):d,w=Math.min(u.surfaceY,S+C);a[x*3]=y,a[x*3+1]=w,a[x*3+2]=b,o[x*3]=h,o[x*3+1]=g,o[x*3+2]=_,s[x*2]=u.along,s[x*2+1]=v,c[x*2]=u.tx,c[x*2+1]=u.tz,l[x*4]=u.speed,l[x*4+1]=Math.max(0,w-S),l[x*4+2]=u.slope,l[x*4+3]=m*t.bankOvershoot}}let f=0;for(let t=0;t+1<e.length;t++)for(let e=0;e<n;e++){let n=t*r+e,i=n+1,a=n+r,o=a+1;d[f++]=n,d[f++]=i,d[f++]=a,d[f++]=i,d[f++]=o,d[f++]=a}return{positions:a,normals:o,uvs:s,flow:c,river:l,indices:d}}function uD(e,t,n){let r=e.bedBlur??0;return r<=0?e.bedAt(t,n):(e.bedAt(t,n)+e.bedAt(t+r,n)+e.bedAt(t-r,n)+e.bedAt(t,n+r)+e.bedAt(t,n-r))/5}function dD(e,t,n){if(e.length===0)return null;let r=0,i=1/0;for(let a=0;a<e.length;a++){let o=e[a],s=(o.x-t)**2+(o.z-n)**2;s<i&&(i=s,r=a)}if(e.length===1){let r=e[0];return fD(r,r,0,t,n,!1)}let a=null,o=1/0;for(let i of[r-1,r]){if(i<0||i+1>=e.length)continue;let r=e[i],s=e[i+1],c=s.x-r.x,l=s.z-r.z,u=c*c+l*l,d=u>1e-9?((t-r.x)*c+(n-r.z)*l)/u:0,f=Math.min(Math.max(d,0),1),p=i===0&&d<0||i+2===e.length&&d>1,m=r.x+c*f,h=r.z+l*f,g=(m-t)**2+(h-n)**2;g<o&&(o=g,a=fD(r,s,f,t,n,p))}return a}function fD(e,t,n,r,i,a){let o=e.x+(t.x-e.x)*n,s=e.z+(t.z-e.z)*n,c=e.tx+(t.tx-e.tx)*n,l=e.tz+(t.tz-e.tz)*n,u=Math.hypot(c,l)||1;c/=u,l/=u;let d=(r-o)*-l+(i-s)*c,f=(e,t)=>e+(t-e)*n,p=d<0?f(e.halfRight,t.halfRight):f(e.halfLeft,t.halfLeft),m=d/(p||1);return{inside:!a&&Math.abs(m)<=1,across:m,along:e.along+(t.along-e.along)*n,surfaceY:e.surfaceY+(t.surfaceY-e.surfaceY)*n,dirX:c,dirZ:l,speed:e.speed+(t.speed-e.speed)*n,halfWidth:p}}function pD(e,t={}){let n=t.minGrade??.45,r=t.minDrop??1.2,i=[],a=-1;for(let t=0;t<=e.length;t++){let o=t<e.length&&e[t].slope>=n;if(o&&a<0&&(a=t),o||a<0)continue;let s=e[Math.max(0,a-1)],c=e[Math.min(e.length-1,t)],l=s.surfaceY-c.surfaceY;l>=r&&i.push({x:c.x,z:c.z,topY:s.surfaceY,baseY:c.surfaceY,drop:l,halfWidth:(c.halfLeft+c.halfRight)/2,dirX:c.tx,dirZ:c.tz,speed:c.speed}),a=-1}return i}function mD(e,t,n,r,i){let a=i*i,o=a*i;return .5*(2*t+(-e+n)*i+(2*e-5*t+4*n-r)*a+(-e+3*t-3*n+r)*o)}var hD=`
|
|
7421
7450
|
float riverHash(vec2 p) {
|
|
7422
7451
|
p = fract(p * vec2(127.31, 311.7));
|
|
7423
7452
|
p += dot(p, p + 34.23);
|
|
@@ -7434,7 +7463,7 @@ float riverNoise(vec2 p) {
|
|
|
7434
7463
|
float d = riverHash(i + vec2(1.0, 1.0));
|
|
7435
7464
|
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
|
7436
7465
|
}
|
|
7437
|
-
`,
|
|
7466
|
+
`,gD=`
|
|
7438
7467
|
precision highp float;
|
|
7439
7468
|
|
|
7440
7469
|
#include <fog_pars_vertex>
|
|
@@ -7495,7 +7524,7 @@ void main() {
|
|
|
7495
7524
|
|
|
7496
7525
|
#include <fog_vertex>
|
|
7497
7526
|
}
|
|
7498
|
-
`,
|
|
7527
|
+
`,_D=`
|
|
7499
7528
|
precision highp float;
|
|
7500
7529
|
|
|
7501
7530
|
#include <fog_pars_fragment>
|
|
@@ -7519,6 +7548,15 @@ uniform float uRippleStrength;
|
|
|
7519
7548
|
uniform float uFlowRate;
|
|
7520
7549
|
uniform float uSparkle;
|
|
7521
7550
|
uniform float uFresnelScale;
|
|
7551
|
+
/**
|
|
7552
|
+
* Rocks standing in the current: xz = centre, z = radius, w = how much of the
|
|
7553
|
+
* water they break (0 = drowned and quiet, 1 = the crest stands proud).
|
|
7554
|
+
* The water does not flow AROUND them in any simulated sense — it is told
|
|
7555
|
+
* where they are and paints what a current does when it meets one: a bow
|
|
7556
|
+
* cushion upstream, a broken wake downstream, and a bent surface between.
|
|
7557
|
+
*/
|
|
7558
|
+
uniform int uRockCount;
|
|
7559
|
+
uniform vec4 uRocks[8];
|
|
7522
7560
|
|
|
7523
7561
|
varying vec3 vWorldPosition;
|
|
7524
7562
|
varying vec3 vSurfaceNormal;
|
|
@@ -7526,7 +7564,7 @@ varying vec2 vFlowUv;
|
|
|
7526
7564
|
varying vec2 vFlow;
|
|
7527
7565
|
varying vec4 vRiver;
|
|
7528
7566
|
|
|
7529
|
-
${
|
|
7567
|
+
${hD}
|
|
7530
7568
|
|
|
7531
7569
|
/**
|
|
7532
7570
|
* Ripple field in flow space: (height, d/d-downstream, d/d-across).
|
|
@@ -7559,6 +7597,53 @@ void main() {
|
|
|
7559
7597
|
float across = vRiver.w;
|
|
7560
7598
|
|
|
7561
7599
|
vec2 dir = normalize(vFlow + vec2(1e-5, 0.0));
|
|
7600
|
+
|
|
7601
|
+
// ── rocks in the current ────────────────────────────────────────────────
|
|
7602
|
+
// Three things happen where a stream meets a boulder, and all three are
|
|
7603
|
+
// read off the same geometry: the flow BENDS around it (a doublet, the
|
|
7604
|
+
// textbook potential flow past a cylinder), it piles into a bow cushion on
|
|
7605
|
+
// the upstream face, and it tears into a broken wake behind. Everything is
|
|
7606
|
+
// in flow space, so a rock in a bend behaves like a rock in a straight.
|
|
7607
|
+
vec2 bend = vec2(0.0);
|
|
7608
|
+
float bow = 0.0;
|
|
7609
|
+
float wake = 0.0;
|
|
7610
|
+
float shed = 0.0;
|
|
7611
|
+
for (int i = 0; i < 8; i++) {
|
|
7612
|
+
if (i >= uRockCount) break;
|
|
7613
|
+
vec4 rock = uRocks[i];
|
|
7614
|
+
float R = max(rock.z, 0.02);
|
|
7615
|
+
vec2 rel = vWorldPosition.xz - rock.xy;
|
|
7616
|
+
float d = length(rel);
|
|
7617
|
+
if (d > R * 6.0) continue;
|
|
7618
|
+
float breaks = rock.w;
|
|
7619
|
+
// flow-space: +s downstream of the rock, t across it
|
|
7620
|
+
float s = dot(rel, dir);
|
|
7621
|
+
float t = dot(rel, vec2(-dir.y, dir.x));
|
|
7622
|
+
// the doublet: strength falls as 1/r², and inside the rock it is capped
|
|
7623
|
+
// so the field never explodes at the centre
|
|
7624
|
+
float rr = max(d, R);
|
|
7625
|
+
// the BEND is not whitewater: even a drowned stone turns the sheen
|
|
7626
|
+
// around itself, so it never fades out with how proud the rock stands
|
|
7627
|
+
bend += (rel / rr) * (R * R / (rr * rr)) * max(breaks, 0.55);
|
|
7628
|
+
// BOW: a cushion of piled water on the upstream face, brightest dead
|
|
7629
|
+
// ahead of the stone and gone by its shoulders
|
|
7630
|
+
float upstream = smoothstep(0.0, -R * 1.1, s);
|
|
7631
|
+
bow += upstream * (1.0 - smoothstep(R * 0.9, R * 2.0, d)) *
|
|
7632
|
+
(1.0 - smoothstep(R * 0.7, R * 1.6, abs(t))) * breaks;
|
|
7633
|
+
// WAKE: a V opening downstream, fading over a few radii
|
|
7634
|
+
float len = R * 5.0;
|
|
7635
|
+
float along = clamp(s / len, 0.0, 1.0);
|
|
7636
|
+
float halfWake = R * (0.5 + 1.3 * along);
|
|
7637
|
+
wake += step(0.0, s) * (1.0 - along) * (1.0 - along) *
|
|
7638
|
+
(1.0 - smoothstep(halfWake * 0.45, halfWake, abs(t))) * breaks;
|
|
7639
|
+
// the SHOULDERS shed water fastest — that is where the white tears off
|
|
7640
|
+
shed += (1.0 - smoothstep(R * 0.8, R * 1.7, d)) *
|
|
7641
|
+
smoothstep(R * 0.35, R * 0.95, abs(t)) * step(-R * 0.6, s) * breaks;
|
|
7642
|
+
}
|
|
7643
|
+
// a bent surface, not a bent texture: rotating the frame the ripple normal
|
|
7644
|
+
// is built in is what makes the sheen sweep around a stone
|
|
7645
|
+
dir = normalize(dir + clamp(bend, vec2(-1.2), vec2(1.2)));
|
|
7646
|
+
|
|
7562
7647
|
vec3 dir3 = vec3(dir.x, 0.0, dir.y);
|
|
7563
7648
|
vec3 perp3 = vec3(-dir.y, 0.0, dir.x);
|
|
7564
7649
|
|
|
@@ -7625,6 +7710,17 @@ void main() {
|
|
|
7625
7710
|
float foam = smoothstep(0.74 - 0.45 * drive, 1.02 - 0.24 * drive, streak) * min(drive, 1.0);
|
|
7626
7711
|
// crest froth: the tops of standing waves in a real rapid always carry white
|
|
7627
7712
|
foam = max(foam, smoothstep(0.68, 0.96, ripple.x) * smoothstep(0.4, 1.0, rapids) * uFoam * 0.5);
|
|
7713
|
+
|
|
7714
|
+
// rock whitewater: the cushion is a smooth pile (white but soft-edged), the
|
|
7715
|
+
// wake and the shoulders are TORN, so they ride the advected noise and boil
|
|
7716
|
+
// instead of sitting there as a painted decal
|
|
7717
|
+
float boil = 0.5 + 0.5 * sin(uTime * 3.1 + vFlowUv.x * 2.7);
|
|
7718
|
+
float rockFoam = clamp(bow * 1.6, 0.0, 1.0) * (0.62 + 0.38 * boil);
|
|
7719
|
+
rockFoam = max(rockFoam, clamp(wake * 1.5, 0.0, 1.0) * smoothstep(0.24, 0.72, streak) * 1.3);
|
|
7720
|
+
rockFoam = max(rockFoam, clamp(shed * 1.5, 0.0, 1.0) * smoothstep(0.32, 0.8, streak));
|
|
7721
|
+
// a boulder in a millpond barely whitens; the same boulder in a chute tears
|
|
7722
|
+
foam = max(foam, clamp(rockFoam, 0.0, 1.0) * smoothstep(0.15, 0.9, speed) * uFoam);
|
|
7723
|
+
|
|
7628
7724
|
// froth can never be more present than the water carrying it
|
|
7629
7725
|
foam = clamp(foam, 0.0, 1.0) * smoothstep(0.02, 0.14, column);
|
|
7630
7726
|
|
|
@@ -7703,7 +7799,7 @@ void main() {
|
|
|
7703
7799
|
#include <colorspace_fragment>
|
|
7704
7800
|
#include <fog_fragment>
|
|
7705
7801
|
}
|
|
7706
|
-
`,nD=1.25,rD=.6,iD=2.5,aD=.45,oD=4,sD=12,cD=1.5,lD=.35,uD=1.2,dD=6,fD=.05,pD=1.5,mD={shallow:`#74b2a2`,deep:`#123f4b`,sky:`#8ab6d8`,horizon:`#9fb6c2`,bank:`#465447`},hD=`#e9f2ef`,gD={rippleScale:.85,rippleStrength:.09,flowRate:.42,fresnelScale:.95,standingAmp:.11,glideAmp:.025},_D=class e extends qp{static typeName=`River3D`;static props={path:{default:[]},width:{default:6},widths:{default:[]},depth:{default:.8},flowSpeed:{default:1.6},colors:{default:{}},absorption:{default:.5},opacity:{default:.85},foam:{default:1},ripples:{default:1},sunDirection:{default:[.5,.8,.3]},sunColor:{default:`#fff6e0`},sunIntensity:{default:1},terrain:{default:``},flowForce:{default:1},spray:{default:1}};path=[];width=6;widths=[];depth=.8;flowSpeed=1.6;colors={};absorption=.5;opacity=.85;foam=1;ripples=1;sunDirection=[.5,.8,.3];sunColor=`#fff6e0`;sunIntensity=1;terrain=``;flowForce=1;spray=1;renderOrder=1;time=0;rings=[];falls=[];sprayKey=``;courseKey=``;bedAt=null;world=[0,0,0];_bodies=[];static validateJson(e){let t=e;if(!Array.isArray(t.path))throw new y(`BAD_FORMAT`,`River3D '${e.name}' path must be an array of [x, z] points, got ${JSON.stringify(t.path)}.`,{prop:`path`});if(t.path.length>0&&t.path.length<2)throw new y(`BAD_FORMAT`,`River3D '${e.name}' path needs at least 2 points (source → mouth), got ${t.path.length}.`,{prop:`path`});if(t.path.forEach((t,n)=>{if(!Array.isArray(t)||t.length<2||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new y(`BAD_FORMAT`,`River3D '${e.name}' path[${n}] must be [x, z] with finite numbers, got ${JSON.stringify(t)}.`,{prop:`path`})}),!(typeof t.width==`number`&&t.width>0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' width must be a positive number of meters, got ${JSON.stringify(t.width)}.`,{prop:`width`});if(!Array.isArray(t.widths)||t.widths.some(e=>!(typeof e==`number`&&e>0)))throw new y(`BAD_FORMAT`,`River3D '${e.name}' widths must be a list of positive meters (source→mouth), got ${JSON.stringify(t.widths)}.`,{prop:`widths`});if(!(t.depth>0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' depth must be > 0 meters, got ${JSON.stringify(t.depth)}.`,{prop:`depth`});if(!(t.flowSpeed>=0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' flowSpeed must be >= 0 m/s, got ${JSON.stringify(t.flowSpeed)}.`,{prop:`flowSpeed`});for(let n of[`absorption`,`foam`,`ripples`,`flowForce`,`spray`,`sunIntensity`]){let r=t[n];if(!(typeof r==`number`&&r>=0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' ${n} must be a number >= 0, got ${JSON.stringify(r)}.`,{prop:n})}if(!(t.opacity>=0&&t.opacity<=1))throw new y(`BAD_FORMAT`,`River3D '${e.name}' opacity must be within [0, 1], got ${JSON.stringify(t.opacity)}.`,{prop:`opacity`});let n=t.colors;if(typeof n!=`object`||!n||Array.isArray(n))throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors must be an object of { shallow, deep, sky, horizon, bank } hex strings.`,{prop:`colors`});for(let t of Object.keys(n)){if(!(t in mD))throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors has unknown key '${t}' — expected shallow, deep, sky, horizon or bank.`,{prop:`colors`});if(typeof n[t]!=`string`)throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors.${t} must be a hex string, got ${JSON.stringify(n[t])}.`,{prop:`colors`})}}_createObject3D(){return new jo(new q,this.buildMaterial())}update(e){this.time+=e,this.ensureCourse(),this.syncSpray(),this.flowForce>0&&this.rings.length>1&&this.sweepBodies(e)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();this.rebuildIfNeeded(e),this.syncUniforms(e)}sampleAt(e,t){if(this.ensureCourse(),this.rings.length===0)return null;let[n,r,i]=this.world,a=YE(this.rings,e-n,t-i);return a?{...a,surfaceY:a.surfaceY+r}:null}fallsAt(){this.ensureCourse();let[e,t,n]=this.world;return this.falls.map(r=>({...r,worldX:r.x+e,worldY:r.baseY+t,worldZ:r.z+n}))}_rings(){return this.rings}_applySunDirection(t){let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this._ensureObject3D().material.uniforms?.uSunDirection?.value)?.set(t[0],t[1],t[2])}free(){let e=this._ensureObject3D();e.geometry?.dispose(),e.material?.dispose?.(),super.free()}widthProfile(){return this.widths.length>0?this.widths:[this.width]}resolveTerrain(){let e=ww(this,this.terrain);if(!e&&this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`River3D '${this.name}' terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`});return e}ensureCourse(){let e=this.resolveTerrain(),t=Cw(this),n=JSON.stringify([this.path,this.width,this.widths,this.depth,this.flowSpeed,e?e.name:``,t]);if(n===this.courseKey)return!1;if(this.courseKey=n,this.world=t,this.bedAt=null,this.path.length<2)return this.rings=[],this.falls=[],!0;let[r,i,a]=t;this.bedAt=e?(t,n)=>e.heightAt(t+r,n+a)-i:()=>-this.depth;let o=this.widthProfile(),s=Math.min(...o);return this.rings=KE({path:this.path,widths:o,depth:this.depth,flowSpeed:this.flowSpeed,step:Math.min(Math.max(s*aD,rD),iD),bedAt:this.bedAt}),this.falls=ZE(this.rings),!0}rebuildIfNeeded(e){if(!this.ensureCourse()&&e.geometry.getAttribute(`position`))return;if(this.rings.length===0||!this.bedAt){e.geometry.dispose();let t=new q;t.setAttribute(`position`,new K(new Float32Array,3)),e.geometry=t;return}let t=this.widthProfile(),n=Math.min(...t),r=Math.max(...t),i=qE(this.rings,{acrossSegments:Math.min(sD,Math.max(oD,Math.round(r/cD))),bankOvershoot:nD,bedBlur:Math.min(n/2*lD,uD),bedAt:this.bedAt}),a=new q;a.setAttribute(`position`,new K(i.positions,3)),a.setAttribute(`normal`,new K(i.normals,3)),a.setAttribute(`aFlowUv`,new K(i.uvs,2)),a.setAttribute(`aFlow`,new K(i.flow,2)),a.setAttribute(`aRiver`,new K(i.river,4)),a.setIndex(new K(i.indices,1)),a.computeBoundingSphere(),e.geometry.dispose(),e.geometry=a}buildMaterial(){return new ec({vertexShader:eD,fragmentShader:tD,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uShallowColor:{value:new G(mD.shallow)},uDeepColor:{value:new G(mD.deep)},uFoamColor:{value:new G(hD)},uSkyColor:{value:new G(mD.sky)},uHorizonColor:{value:new G(mD.horizon)},uBankColor:{value:new G(mD.bank)},uSunDirection:{value:new H(.5,.8,.3)},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.sunIntensity},uMaxDepth:{value:this.depth},uAbsorption:{value:this.absorption},uOpacity:{value:this.opacity},uFoam:{value:this.foam},uRippleScale:{value:gD.rippleScale},uRippleStrength:{value:gD.rippleStrength*this.ripples},uFlowRate:{value:gD.flowRate},uSparkle:{value:this.ripples},uFresnelScale:{value:gD.fresnelScale},uStandingAmp:{value:gD.standingAmp},uGlideAmp:{value:gD.glideAmp}},transparent:!0,depthTest:!0,depthWrite:!1,side:2})}syncUniforms(e){let t=e.material.uniforms,n=(e,n)=>{let r=t[e];r&&(r.value=n)},r=(e,n)=>{(t[e]?.value)?.set(n)},i=this.colors;n(`uTime`,this.time),r(`uShallowColor`,i.shallow??mD.shallow),r(`uDeepColor`,i.deep??mD.deep),r(`uSkyColor`,i.sky??mD.sky),r(`uHorizonColor`,i.horizon??mD.horizon),r(`uBankColor`,i.bank??mD.bank),r(`uSunColor`,this.sunColor),(t.uSunDirection?.value)?.set(this.sunDirection[0]??.5,this.sunDirection[1]??.8,this.sunDirection[2]??.3),n(`uSunIntensity`,this.sunIntensity),n(`uMaxDepth`,this.depth),n(`uAbsorption`,this.absorption),n(`uOpacity`,this.opacity),n(`uFoam`,this.foam),n(`uRippleStrength`,gD.rippleStrength*this.ripples),n(`uSparkle`,this.ripples)}syncSpray(){let e=this.spray>0?`${this.spray}|${JSON.stringify(this.falls)}`:``;if(e!==this.sprayKey){this.sprayKey=e;for(let e of[...this.children])e.name.startsWith(`__spray`)&&e.free();this.spray<=0||this.falls.forEach((e,t)=>{let n=new NE(`__spray${t}`);n.position=[e.x+e.dirX*.6,e.baseY+.15,e.z+e.dirZ*.6];let r=Math.min(1.6,.4+e.drop*.12)*this.spray;n.rate=Math.round(Math.min(46,10+e.drop*3)*this.spray),n.maxParticles=160,n.lifetime=[1,2.1],n.speed=[55*r,170*r],n.directionDeg=-90,n.spreadDeg=58,n.gravity=[0,-240,0],n.drag=1.2,n.sizeStart=16*r,n.sizeEnd=80*r,n.colorStart=`#ffffff`,n.colorEnd=`#dfe9ec`,n.alphaStart=.2,n.alphaEnd=0,n.blend=`normal`,n.depthTest=!0,this.addChild(n)})}}sweepBodies(e){let t=this;for(;t.parent;)t=t.parent;let n=this._bodies;if(n.length=0,vD(t,n),n.length===0)return;let[r,i,a]=this.world;for(let t of n){let n=Cw(t),o=YE(this.rings,n[0]-r,n[2]-a);if(!o?.inside)continue;let s=o.surfaceY+i,c=n[1]-rp(t.collider);if(c>s+fD||c<s-this.depth-pD)continue;let l=yD(t);if(!l)continue;let u=Math.min(1,this.flowForce*dD*e),d=(o.dirX*o.speed-(l[0]??0))*u,f=(o.dirZ*o.speed-(l[2]??0))*u;if(t instanceof Zp){let e=t.mass||1;t.applyImpulse([d*e,0,f*e])}else l[0]=(l[0]??0)+d,l[2]=(l[2]??0)+f}}};function vD(e,t){(e instanceof Qp||e instanceof Zp)&&t.push(e);for(let n of e.children)vD(n,t)}function yD(e){return e.velocity??e.linearVelocity}var bD=128,xD=class extends qp{static typeName=`Trail3D`;static props={width:{default:.3},color:{default:`#ffffff`},opacity:{default:.8},seconds:{default:.6},emitting:{default:!0},additive:{default:!1},minDistance:{default:.05}};width=.3;color=`#ffffff`;opacity=.8;seconds=.6;emitting=!0;additive=!1;minDistance=.05;points=[];clock=0;mesh=null;lastColor=``;_createObject3D(){let e=new Qi,t=new q;t.setAttribute(`position`,new K(new Float32Array(bD*2*3),3));let n=new yo({color:this.color,transparent:!0,opacity:this.opacity,side:2,depthWrite:!1,blending:this.additive?2:1});return this.mesh=new jo(t,n),this.mesh.frustumCulled=!1,this.mesh.matrixAutoUpdate=!1,this.mesh.matrixWorld.identity(),this.mesh.updateMatrixWorld=()=>{},e.add(this.mesh),e}update(e){for(this.clock+=e;this.points.length>0&&this.clock-this.points[0].t>this.seconds;)this.points.shift()}_onRender3D(e){let t=this._ensureObject3D();if(this.emitting){t.getWorldPosition(SD);let e=this.points[this.points.length-1];(!e||(e.x-SD.x)**2+(e.y-SD.y)**2+(e.z-SD.z)**2>this.minDistance*this.minDistance)&&(this.points.push({x:SD.x,y:SD.y,z:SD.z,t:this.clock}),this.points.length>bD&&this.points.shift())}let n=this.mesh;if(!n)return;n.matrixWorld.identity();let r=n.material;this.color!==this.lastColor&&(this.lastColor=this.color,r.color=new G(this.color)),r.opacity=this.opacity;let i=this.points.length,a=n.geometry,o=a.getAttribute(`position`);if(i<2){a.setDrawRange(0,0);return}for(let t=0;t<i;t++){let n=this.points[t],r=this.points[Math.min(t+1,i-1)]??n;CD.set(r.x-n.x,r.y-n.y,r.z-n.z),CD.lengthSq()<1e-8&&CD.set(0,1,0),wD.set(e.camera.position.x-n.x,e.camera.position.y-n.y,e.camera.position.z-n.z),TD.crossVectors(CD,wD).normalize();let a=(this.clock-n.t)/this.seconds,s=this.width/2*Math.max(0,1-a);o.setXYZ(t*2,n.x+TD.x*s,n.y+TD.y*s,n.z+TD.z*s),o.setXYZ(t*2+1,n.x-TD.x*s,n.y-TD.y*s,n.z-TD.z*s)}if(o.needsUpdate=!0,!a.index||a.index.count<(bD-1)*6){let e=[];for(let t=0;t<bD-1;t++){let n=t*2;e.push(n,n+1,n+2,n+1,n+3,n+2)}a.setIndex(e)}a.setDrawRange(0,(i-1)*6)}get pointCount(){return this.points.length}},SD=new H,CD=new H,wD=new H,TD=new H;function ED(e){let{branch:t,leaves:n,type:r}=e,i=0,a=0,o=[{level:0,sections:t.sections[0],segments:t.segments[0]}];for(;o.length>0;){let e=o.shift();if(i+=e.sections*e.segments*2,e.level>=t.levels){a+=n.count===0?0:n.count+ +(r===`deciduous`);continue}r===`deciduous`&&o.push({level:e.level+1,sections:e.sections,segments:e.segments});let s=t.children[e.level]??0;for(let n=0;n<s;n++)o.push({level:e.level+1,sections:t.sections[e.level+1]??1,segments:t.segments[e.level+1]??3})}let s=n.billboard===`double`?2:1,c=a*s*2;return{branches:i,leaves:c,total:i+c}}var DD={ash:{type:`deciduous`,branch:{levels:3,angle:[0,48,75,60],children:[7,4,3,0],force:{direction:{x:0,y:1,z:0},strength:-.06},gnarliness:[.03,.25,.2,.09],length:[43.47,27.14,9.51,4.6],radius:[2,.63,.76,.7],sections:[12,8,6,4],segments:[12,6,4,3],start:[0,.23,.33,0],taper:[.7,.7,.7,.7],twist:[.09,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:16,start:0,size:2.67,sizeVariance:.72,alphaTest:.5}},aspen:{type:`deciduous`,branch:{levels:2,angle:[0,75,32,7],children:[10,3,3,0],force:{direction:{x:0,y:1,z:0},strength:.0148},gnarliness:[.05,.12,.12,.02],length:[50,6.07,11.19,1],radius:[.72,.41,.7,.7],sections:[12,10,8,6],segments:[8,6,4,3],start:[0,.59,.35,0],taper:[.37,.13,.7,.7],twist:[0,0,0,0]},leaves:{style:`aspen`,billboard:`double`,angle:30,count:11,start:.124,size:2.5,sizeVariance:.7,alphaTest:.5}},oak:{type:`deciduous`,branch:{levels:3,angle:[0,54,58,32],children:[6,4,3,0],force:{direction:{x:0,y:1,z:0},strength:-.01},gnarliness:[0,-.1,-.15,.09],length:[37.24,11.08,12.39,7.16],radius:[1.41,.9,.69,1.19],sections:[8,6,3,1],segments:[7,5,3,3],start:[0,.49,.06,.12],taper:[.73,.42,.69,.75],twist:[-.23,.42,0,0]},leaves:{style:`oak`,billboard:`double`,angle:42,count:18,start:.16,size:2.5,sizeVariance:.7,alphaTest:.5}},pine:{type:`evergreen`,branch:{levels:1,angle:[0,110,16,60],children:[82,3,5,0],force:{direction:{x:0,y:1,z:0},strength:-.003},gnarliness:[.05,.08,0,0],length:[50,23.87,14.08,1],radius:[1.05,.36,.7,.7],sections:[12,10,8,6],segments:[8,6,4,3],start:[0,.27,.14,.3],taper:[.7,.7,.7,.7],twist:[0,0,0,0]},leaves:{style:`pine`,billboard:`double`,angle:39,count:30,start:.09,size:1.435,sizeVariance:.201,alphaTest:.3}},bush:{type:`deciduous`,branch:{levels:3,angle:[0,21.5,62.6,60],children:[7,3,2,0],force:{direction:{x:0,y:1,z:0},strength:-.02},gnarliness:[.11,.09,.05,.09],length:[.1,15.3,5.59,4.6],radius:[.58,.95,.76,.7],sections:[6,6,4,3],segments:[4,4,4,3],start:[0,.53,.33,0],taper:[.7,.7,.7,.7],twist:[.3,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:8,start:0,size:2.45,sizeVariance:.717,alphaTest:.5}},"ash-forest":{type:`deciduous`,branch:{levels:2,angle:[0,48,75,60],children:[5,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.06},gnarliness:[.03,.25,.2,.09],length:[43.47,27.14,9.51,4.6],radius:[2,.63,.76,.7],sections:[6,5,4,4],segments:[6,4,3,3],start:[0,.3,.33,0],taper:[.7,.7,.7,.7],twist:[.09,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:15,start:0,size:3,sizeVariance:.6,alphaTest:.5}},"oak-forest":{type:`deciduous`,branch:{levels:2,angle:[0,54,58,32],children:[5,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.01},gnarliness:[0,-.1,-.15,.09],length:[37.24,11.08,12.39,7.16],radius:[1.41,.9,.69,1.19],sections:[6,4,3,1],segments:[6,4,3,3],start:[0,.49,.06,.12],taper:[.73,.42,.69,.75],twist:[-.23,.42,0,0]},leaves:{style:`oak`,billboard:`double`,angle:42,count:16,start:.1,size:2.9,sizeVariance:.7,alphaTest:.5}},"pine-forest":{type:`evergreen`,branch:{levels:1,angle:[0,110,16,60],children:[44,3,5,0],force:{direction:{x:0,y:1,z:0},strength:-.005},gnarliness:[.07,.09,0,0],length:[50,23.87,14.08,1],radius:[1.05,.36,.7,.7],sections:[6,5,8,6],segments:[6,3,4,3],start:[0,.27,.14,.3],taper:[.7,.7,.7,.7],twist:[0,0,0,0]},leaves:{style:`pine`,billboard:`double`,angle:39,count:9,start:.09,size:1.8,sizeVariance:.201,alphaTest:.3}},"bush-forest":{type:`deciduous`,branch:{levels:2,angle:[0,21.5,62.6,60],children:[6,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.02},gnarliness:[.11,.09,.05,.09],length:[.1,15.3,5.59,4.6],radius:[.58,.95,.76,.7],sections:[5,4,3,3],segments:[4,3,3,3],start:[0,.53,.33,0],taper:[.7,.7,.7,.7],twist:[.3,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:10,start:0,size:3.2,sizeVariance:.6,alphaTest:.5}}},OD=[`ash`,`aspen`,`oak`,`pine`,`bush`,`ash-forest`,`oak-forest`,`pine-forest`,`bush-forest`];function kD(e){let t=DD[e];if(!t)throw new y(`BAD_FORMAT`,`Unknown eztree preset '${e}' — must be one of [${OD.join(`, `)}].`,{prop:`preset`,validOptions:OD});return structuredClone(t)}var AD={ash:{texture:`oak`,tint:`#cecbbe`,repeat:[.5,1/5]},aspen:{texture:`birch`,tint:`#ffffff`,repeat:[1,1]},oak:{texture:`oak`,tint:`#fff3d1`,repeat:[1,1/10]},pine:{texture:`pine`,tint:`#ffffff`,repeat:[1,1]},bush:{texture:`oak`,tint:`#cecbbe`,repeat:[.5,1/5]}};function jD(e){if(!OD.includes(e))throw new y(`BAD_FORMAT`,`Unknown eztree preset '${e}' — must be one of [${OD.join(`, `)}].`,{prop:`preset`,validOptions:OD});return structuredClone(AD[e.replace(/-forest$/,``)])}var MD=.45,ND=.45,PD=.55,FD=.15,ID=.07,LD=.035;function RD(e,t){let n=Math.imul(e+1,374761393)+Math.imul(t+1,668265263)>>>0;return n=Math.imul(n^n>>>13,1274126177)>>>0,((n^n>>>16)>>>0)/4294967296}function zD(e,t,n){let r=e.length/3,i=new Float32Array(e.length),a=new Float32Array(e.length),o=1/0,s=1/0,c=1/0,l=-1/0,u=-1/0,d=-1/0;for(let t=0;t<r;t++){let n=e[t*3],r=e[t*3+1],i=e[t*3+2];n<o&&(o=n),n>l&&(l=n),r<s&&(s=r),r>u&&(u=r),i<c&&(c=i),i>d&&(d=i)}let f=(o+l)/2,p=(s+u)/2,m=(c+d)/2,h=Math.max((l-o)/2,.001),g=Math.max((u-s)/2,.001),_=Math.max((d-c)/2,.001),v=new Map;for(let n=0;n<r;n++){let r=t[n],i=v.get(r);i||(i={x:0,y:0,z:0,n:0},v.set(r,i)),i.x+=e[n*3],i.y+=e[n*3+1],i.z+=e[n*3+2],i.n++}for(let e of v.values())e.x/=e.n,e.y/=e.n,e.z/=e.n;for(let o=0;o<r;o++){let r=e[o*3],c=e[o*3+1],l=e[o*3+2],d=(r-f)/h,y=(c-p)/g,b=(l-m)/_,x,S,C,w;if(n===`evergreen`){let e=Math.hypot(r-f,l-m);if(e<1e-6)x=0,S=1,C=0;else{let t=1/Math.hypot(1,ND);x=(r-f)/e*t,S=ND*t,C=(l-m)/e*t}let t=(c-s)/Math.max(u-s,.001),n=Math.max(FD,1-t);w=Math.min(1,Math.hypot(d,b)/n)}else{let e=d/h,t=y/g,n=b/_,r=Math.hypot(e,t,n);r<1e-6?(x=0,S=1,C=0):(x=e/r,S=t/r,C=n/r),w=Math.min(1,Math.hypot(d,y,b))}let T=v.get(t[o]);if(T){let e=r-T.x,t=c-T.y,n=l-T.z,i=Math.hypot(e,t,n);if(i>1e-6){x=x*(1-PD)+e/i*PD,S=S*(1-PD)+t/i*PD,C=C*(1-PD)+n/i*PD;let r=Math.hypot(x,S,C);r>1e-6?(x/=r,S/=r,C/=r):(x=0,S=1,C=0)}}i[o*3]=x,i[o*3+1]=S,i[o*3+2]=C;let E=MD+(1-MD)*w,D=t[o],O=E*(1-ID*RD(D,1)),k=(RD(D,2)-.5)*2*LD;a[o*3]=O*(1+k),a[o*3+1]=O,a[o*3+2]=O*(1-k)}return{normals:i,colors:a}}var BD=class e{static MASK=4294967295;mW;mZ;constructor(t){this.mW=123456789+t&e.MASK,this.mZ=987654321-t&e.MASK}random(t=1,n=0){this.mZ=36969*(this.mZ&65535)+(this.mZ>>16)&e.MASK,this.mW=18e3*(this.mW&65535)+(this.mW>>16)&e.MASK;let r=((this.mZ<<16)+(this.mW&65535)>>>0)/4294967296;return(t-n)*r+n}};function VD(e,t,n){let r=new BD(t),i={branchVerts:[],branchNormals:[],branchUvs:[],branchIndices:[],leafVerts:[],leafIndices:[],leafUvs:[],leafAnchors:[],leafClusters:[],leafClusterNext:0},a=[{origin:new H,orientation:new Pi,length:e.branch.length[0],radius:e.branch.radius[0],level:0,sectionCount:e.branch.sections[0],segmentCount:e.branch.segments[0]}];for(;a.length>0;)HD(e,r,i,a,a.shift());YD(i,n);let o=new q;o.setAttribute(`position`,new K(new Float32Array(i.branchVerts),3)),o.setAttribute(`normal`,new K(new Float32Array(i.branchNormals),3)),o.setAttribute(`uv`,new K(new Float32Array(i.branchUvs),2)),o.setIndex(new K(XD(i.branchIndices,i.branchVerts),1)),o.computeBoundingSphere();let s=null;if(i.leafVerts.length>0){s=new q,s.setAttribute(`position`,new K(new Float32Array(i.leafVerts),3)),s.setAttribute(`anchor`,new K(new Float32Array(i.leafAnchors),3)),s.setAttribute(`uv`,new K(new Float32Array(i.leafUvs),2)),s.setIndex(new K(XD(i.leafIndices,i.leafVerts),1));let t=zD(i.leafVerts,i.leafClusters,e.type);s.setAttribute(`normal`,new K(t.normals,3)),s.setAttribute(`color`,new K(t.colors,3)),s.computeBoundingSphere()}return{branches:o,leaves:s}}function HD(e,t,n,r,i){let a=n.branchVerts.length/3,o=i.orientation.clone(),s=i.origin.clone(),c=i.length/i.sectionCount,l=[];for(let r=0;r<=i.sectionCount;r++){let a=i.radius;r===i.sectionCount&&i.level===e.branch.levels?a=.001:e.type===`deciduous`?a*=1-(e.branch.taper[i.level]??0)*(r/i.sectionCount):a*=1-r/i.sectionCount;let u=new H,d=new H,f=0;for(let e=0;e<i.segmentCount;e++){let t=2*Math.PI*e/i.segmentCount,c=new H(Math.cos(t),0,Math.sin(t)).multiplyScalar(a).applyEuler(o).add(s),l=new H(Math.cos(t),0,Math.sin(t)).applyEuler(o).normalize(),p=r%2==0?0:1;n.branchVerts.push(c.x,c.y,c.z),n.branchNormals.push(l.x,l.y,l.z),n.branchUvs.push(e/i.segmentCount,p),e===0&&(u=c,d=l,f=p)}n.branchVerts.push(u.x,u.y,u.z),n.branchNormals.push(d.x,d.y,d.z),n.branchUvs.push(1,f),l.push({origin:s.clone(),orientation:o.clone(),radius:a}),s.add(new H(0,c,0).applyEuler(o));let p=Math.max(1,1/Math.sqrt(a))*(e.branch.gnarliness[i.level]??0);o.x+=t.random(p,-p),o.z+=t.random(p,-p);let m=new V().setFromEuler(o),h=new V().setFromAxisAngle(new H(0,1,0),e.branch.twist[i.level]??0),g=e.branch.force,_=new V().setFromUnitVectors(new H(0,1,0),new H(g.direction.x,g.direction.y,g.direction.z));m.multiply(h),m.rotateTowards(_,g.strength/a),o.setFromQuaternion(m)}JD(n,a,i);let u=i.level===e.branch.levels?n.leafClusterNext++:0;if(e.type===`deciduous`){let a=l[l.length-1];i.level<e.branch.levels?r.push({origin:a.origin,orientation:a.orientation,length:e.branch.length[i.level+1]??0,radius:a.radius,level:i.level+1,sectionCount:i.sectionCount,segmentCount:i.segmentCount}):e.leaves.count>0&&qD(e,t,n,a.origin,a.orientation,u)}i.level===e.branch.levels?KD(e,t,n,l,u):i.level<e.branch.levels&&GD(e,t,r,e.branch.children[i.level]??0,i.level+1,l)}function UD(e,t){let n=Math.floor(t*(e.length-1)),r=e[n],i=n===e.length-1?r:e[n+1],a=(t-n/(e.length-1))/(1/(e.length-1)),o=new H().lerpVectors(r.origin,i.origin,a),s=new V().setFromEuler(r.orientation),c=new V().setFromEuler(i.orientation);return{origin:o,orientation:new Pi().setFromQuaternion(c.slerp(s,a)),radius:{a:r.radius,b:i.radius,alpha:a}}}function WD(e,t,n){let r=new V().setFromAxisAngle(new H(1,0,0),t/(180/Math.PI)),i=new V().setFromAxisAngle(new H(0,1,0),n),a=new V().setFromEuler(e);return new Pi().setFromQuaternion(a.multiply(i.multiply(r)))}function GD(e,t,n,r,i,a){let o=t.random();for(let s=0;s<r;s++){let c=t.random(1,e.branch.start[i]??0),l=UD(a,c),u=(e.branch.radius[i]??0)*((1-l.radius.alpha)*l.radius.a+l.radius.alpha*l.radius.b),d=2*Math.PI*(o+s/r),f=WD(l.orientation,e.branch.angle[i]??0,d),p=(e.branch.length[i]??0)*(e.type===`evergreen`?1-c:1);n.push({origin:l.origin,orientation:f,length:p,radius:u,level:i,sectionCount:e.branch.sections[i]??1,segmentCount:e.branch.segments[i]??3})}}function KD(e,t,n,r,i){let a=t.random();for(let o=0;o<e.leaves.count;o++){let s=UD(r,t.random(1,e.leaves.start)),c=2*Math.PI*(a+o/e.leaves.count),l=WD(s.orientation,e.leaves.angle,c);qD(e,t,n,s.origin,l,i)}}function qD(e,t,n,r,i,a){let o=n.leafVerts.length/3,s=e.leaves.size*(1+t.random(e.leaves.sizeVariance,-e.leaves.sizeVariance)),c=e=>{let t=s/2,c=[new H(-t,s,0),new H(-t,0,0),new H(t,0,0),new H(t,s,0)];for(let t of c)t.applyEuler(new Pi(0,e,0)).applyEuler(i).add(r),n.leafVerts.push(t.x,t.y,t.z),n.leafAnchors.push(r.x,r.y,r.z),n.leafClusters.push(a);n.leafUvs.push(0,1,0,0,1,0,1,1),n.leafIndices.push(o,o+1,o+2,o,o+2,o+3),o+=4};c(0),e.leaves.billboard===`double`&&c(Math.PI/2)}function JD(e,t,n){let r=n.segmentCount+1;for(let i=0;i<n.sectionCount;i++)for(let a=0;a<n.segmentCount;a++){let n=t+i*r+a,o=t+i*r+(a+1),s=n+r,c=o+r;e.branchIndices.push(n,s,o,o,s,c)}}function YD(e,t){let n=0;for(let t=1;t<e.branchVerts.length;t+=3){let r=e.branchVerts[t];r>n&&(n=r)}for(let t=1;t<e.leafVerts.length;t+=3){let r=e.leafVerts[t];r>n&&(n=r)}if(n<=0)return;let r=t/n;for(let t=0;t<e.branchVerts.length;t++)e.branchVerts[t]=e.branchVerts[t]*r;for(let t=0;t<e.leafVerts.length;t++)e.leafVerts[t]=e.leafVerts[t]*r;for(let t=0;t<e.leafAnchors.length;t++)e.leafAnchors[t]=e.leafAnchors[t]*r}function XD(e,t){return t.length/3>65535?new Uint32Array(e):new Uint16Array(e)}var ZD=[`simple`,`medium`,`high`],QD=[`conifer`,`broadleaf`,`dead`,`bush`];function $D(e,t,n){return new y(`BAD_FORMAT`,`Tree3D ${e} must be one of [${n.join(`, `)}], got '${t}'.`,{prop:e,validOptions:n})}var eO={simple:0,medium:1,high:2},tO=[5,7,10],nO=[2,3,4],rO=[6,8,12],iO=[2,3,3],aO=[0,1,2],oO=[3,4,5],sO=3;function cO(e,t){if(!ZD.includes(e))throw $D(`tier`,e,ZD);if(!QD.includes(t))throw $D(`type`,t,QD);let n=e,r=t,i=eO[n];return{tier:n,type:r,trunkRadialSegments:tO[i],canopyLayers:r===`conifer`?nO[i]:0,canopySegments:rO[i],blobCount:r===`broadleaf`||r===`bush`?iO[i]:0,blobDetail:aO[i],branchCount:r===`dead`?oO[i]:r===`conifer`&&n===`high`?sO:0,hasCanopy:r!==`dead`,canopySway:n!==`simple`}}var lO=.02,uO={conifer:{trunkHeight:.4,trunkRadiusBottom:.05,trunkRadiusTop:.035},broadleaf:{trunkHeight:.42,trunkRadiusBottom:.05,trunkRadiusTop:.032},dead:{trunkHeight:.72,trunkRadiusBottom:.045,trunkRadiusTop:.018},bush:{trunkHeight:.14,trunkRadiusBottom:.045,trunkRadiusTop:.035}};function dO(e,t,n){let{trunkHeight:r,trunkRadiusBottom:i,trunkRadiusTop:a}=uO[e.type],o=[],s=new Bs(a,i,r,e.trunkRadialSegments).toNonIndexed();if(s.translate(0,r/2,0),o.push(s),e.type===`dead`)for(let n=0;n<e.branchCount;n++){let r=.22+t.next()*.14,a=new Bs(.006,.02,r,5).toNonIndexed();a.translate(0,r/2,0);let s=.7+t.next()*.6,c=n/e.branchCount*Math.PI*2+t.next()*.8,l=.34+(n+t.next())/e.branchCount*.34;a.applyMatrix4(new W().makeRotationY(c).multiply(new W().makeRotationX(s)).setPosition(Math.sin(c)*i*.6,l,Math.cos(c)*i*.6)),o.push(a)}let c=pO(o);return hO(c,new G(n),.7,1.05,t),c}function fO(e,t,n){if(!e.hasCanopy)return null;let r=[];if(e.type===`conifer`){let n=.74;for(let i=0;i<e.canopyLayers;i++){let a=i/e.canopyLayers,o=.3*(1-a*.62)*(.92+t.next()*.16),s=n/e.canopyLayers*1.7,c=new Vs(o,s,e.canopySegments).toNonIndexed();mO(c,t,lO),c.translate(0,.26+n*a+s/2,0),r.push(c)}for(let n=0;n<e.branchCount;n++){let i=new Vs(.06,.2,5).toNonIndexed(),a=n/Math.max(e.branchCount,1)*Math.PI*2+t.next(),o=1.1+t.next()*.4;i.applyMatrix4(new W().makeRotationY(a).multiply(new W().makeRotationX(o)).setPosition(Math.sin(a)*.22,.34+t.next()*.18,Math.cos(a)*.22)),r.push(i)}}else{let{trunkHeight:n}=uO[e.type];for(let i=0;i<e.blobCount;i++){let a=new Us((i===0?.3:.24-i*.02)*(.92+t.next()*.16),e.blobDetail).toNonIndexed();a.scale(1,.72,1),mO(a,t,lO);let o=i===0?0:.13,s=t.next()*Math.PI*2;a.translate(Math.cos(s)*o,n+.16+i*.1+t.next()*.05,Math.sin(s)*o),r.push(a)}}let i=pO(r);return hO(i,new G(n),.62,1.18,t),i}function pO(e){let t=0;for(let n of e)t+=n.getAttribute(`position`).count;let n=new Float32Array(t*3),r=new Float32Array(t*3),i=0;for(let t of e)n.set(t.getAttribute(`position`).array,i),r.set(t.getAttribute(`normal`).array,i),i+=t.getAttribute(`position`).count*3,t.dispose();let a=new q;return a.setAttribute(`position`,new K(n,3)),a.setAttribute(`normal`,new K(r,3)),a}function mO(e,t,n){let r=e.getAttribute(`position`);for(let e=0;e<r.count;e++)r.setXYZ(e,r.getX(e)+t.range(-n,n),r.getY(e)+t.range(-n,n),r.getZ(e)+t.range(-n,n))}function hO(e,t,n,r,i){let a=e.getAttribute(`position`),o=new Float32Array(a.count*3),s=1/0,c=-1/0;for(let e=0;e<a.count;e++){let t=a.getY(e);t<s&&(s=t),t>c&&(c=t)}let l=Math.max(c-s,1e-6),u=new G;for(let e=0;e<a.count;e++){let c=(a.getY(e)-s)/l,d=(n+(r-n)*c)*(.96+i.next()*.08);u.copy(t).multiplyScalar(d),o[e*3]=u.r,o[e*3+1]=u.g,o[e*3+2]=u.b}e.setAttribute(`color`,new K(o,3))}var gO=500,_O=15e5,vO=[.8,1.2],yO=.28,bO=.12,xO=.055,SO=.11,CO=3,wO=101,TO=[.78,.7,.45],EO=.45,DO=.55,OO=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation`,kO=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark`,AO={high:{conifer:[`pine`,`pine`,`pine`],broadleaf:[`oak`,`ash`,`oak`],dead:[`ash`,`ash`,`ash`],bush:[`bush`,`bush`,`bush`]},medium:{conifer:[`pine-forest`,`pine-forest`,`pine-forest`],broadleaf:[`oak-forest`,`ash-forest`,`oak-forest`],dead:[`ash-forest`,`ash-forest`,`ash-forest`],bush:[`bush-forest`,`bush-forest`,`bush-forest`]}},jO=class e extends qp{static typeName=`Tree3D`;static props={tier:{default:`medium`,options:ZD},type:{default:`conifer`,options:QD},seed:{default:1},height:{default:6},count:{default:1},area:{default:[10,10]},trunkColor:{default:`#7a5a3a`},canopyColor:{default:`#4a7c3f`},leafTexture:{default:``},leafFadeStart:{default:0},leafFadeEnd:{default:0},leafShadows:{default:!0},drape:{default:null},terrain:{default:``}};tier=`medium`;type=`conifer`;seed=1;height=6;count=1;area=[10,10];trunkColor=`#7a5a3a`;canopyColor=`#4a7c3f`;leafTexture=``;leafFadeStart=0;leafFadeEnd=0;leafShadows=!0;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(cO(t.tier,t.type),!(t.height>0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' height must be > 0 meters, got ${t.height}.`,{prop:`height`});if(!Number.isInteger(t.count)||t.count<1||t.count>gO)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' count must be an integer in 1..${gO}, got ${t.count}.`,{prop:`count`});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});if(t.leafFadeEnd!==0&&!(t.leafFadeEnd>t.leafFadeStart&&t.leafFadeStart>=0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' needs leafFadeEnd > leafFadeStart >= 0 (the leaf LOD window) or 0/0 to disable, got start ${t.leafFadeStart}, end ${t.leafFadeEnd}.`,{prop:`leafFadeStart`});if(typeof t.leafShadows!=`boolean`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' leafShadows must be a boolean, got ${JSON.stringify(t.leafShadows)}.`,{prop:`leafShadows`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`});if(t.tier===`simple`)return;let n=PO(t.tier,t.type),r=n*t.count;if(r>_O)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' blows the grove triangle budget: count ${t.count} × ${n} tris/tree (tier '${t.tier}', type '${t.type}') = ${r} > ${_O}. Lower count (max ${Math.floor(_O/n)} at this tier), drop tier to 'medium'/'simple', or split the grove into multiple nodes.`,{prop:`count`})}time=0;grove=null;variants=[];simpleTrunk=null;simpleCanopy=null;swayUniform=null;leafFadeUniform=null;loadedTextures=[];groveKey=``;_createObject3D(){return new Qi}_trunk(){return this.rebuildIfNeeded(),this.simpleTrunk??this.variants[0]?.branches}_canopy(){return this.rebuildIfNeeded(),this.simpleTrunk?this.simpleCanopy:this.variants[0]?.leaves??null}_variantMeshes(){return this.rebuildIfNeeded(),this.variants}update(e){this.time+=e,this.swayUniform&&(this.swayUniform.value=this.time),this.leafFadeUniform&&(this.leafFadeUniform.start.value=this.leafFadeStart,this.leafFadeUniform.end.value=this.leafFadeEnd)}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded()}rebuildIfNeeded(){this.grove||(this.grove=new Qi,this._ensureObject3D().add(this.grove));let e=JSON.stringify([this.tier,this.type,this.seed,this.height,this.count,this.area,this.trunkColor,this.canopyColor,this.leafTexture,this.leafShadows,this.leafFadeEnd>this.leafFadeStart,this.drape,this.terrain]);e===this.groveKey&&(this.simpleTrunk||this.variants.length>0)||(this.groveKey=e,this.disposeMeshes(),this.resolveDrape(),this.tier===`simple`?this.buildSimpleGrove():this.buildEzGrove())}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=ww(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Cw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Tree3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildSimpleGrove(){let e=cO(this.tier,this.type),t=new b(this.seed),n=dO(e,t,this.trunkColor),r=fO(e,t,this.canopyColor),i=new rs(n,BO(),this.count);HO(i);let a=null;r&&(a=new rs(r,BO(),this.count),HO(a)),this.scatter(t,(e,t,n)=>{i.setMatrixAt(e,t),i.setColorAt(e,n),a?.setMatrixAt(e,t),a?.setColorAt(e,n)}),VO(i),a&&VO(a),this.simpleTrunk=i,this.simpleCanopy=a,this.grove.add(i),a&&this.grove.add(a)}buildEzGrove(){let e=AO[this.tier][this.type],t=Math.min(CO,this.count),n=Array.from({length:t},(e,n)=>Math.floor(this.count/t)+ +(n<this.count%t));this.swayUniform={value:this.time},this.leafFadeUniform=this.leafFadeEnd>this.leafFadeStart?{start:{value:this.leafFadeStart},end:{value:this.leafFadeEnd}}:null;let r=LO(this.canopyColor),i=null;typeof document<`u`&&typeof createImageBitmap==`function`&&(i=new ol,i.setOptions({imageOrientation:`flipY`}));for(let a=0;a<t;a++){let t=n[a],o=e[a],s=kD(o);this.type===`dead`&&(s.leaves.count=0);let c=VD(s,this.seed+a*wO,1),l=this.buildBarkMaterial(o,i),u=new rs(c.branches,l,t);HO(u);let d=null;if(c.leaves){let e=new nc({color:r.clone().multiply(new G(TO[0],TO[1],TO[2])),roughness:1,side:2,vertexColors:!0,alphaTest:s.leaves.alphaTest}),n=this.leafTexture||FO(s.leaves.style);i&&(e.map=NO(i,n,e=>{e.colorSpace=dr,e.flipY=!1},e=>IO(e))),fT(e,this.swayUniform,EO,this.leafFadeUniform??void 0),d=new rs(c.leaves,e,t),HO(d),this.leafShadows||(d.castShadow=!1)}this.variants.push({branches:u,leaves:d}),this.grove.add(u),d&&this.grove.add(d)}let a=Array(t).fill(0),o=new b(this.seed);this.scatter(o,(e,n,r)=>{let i=e%t,o=this.variants[i],s=a[i];a[i]=s+1,o.branches.setMatrixAt(s,n),o.branches.setColorAt(s,r),o.leaves?.setMatrixAt(s,n),o.leaves?.setColorAt(s,r)});for(let e of this.variants)VO(e.branches),e.leaves&&VO(e.leaves)}buildBarkMaterial(t,n){if(this.type===`dead`||!n)return new nc({color:new G(this.trunkColor),roughness:1});let r=jD(t),i=new nc({color:this.trunkColor===e.props.trunkColor?.default?new G(r.tint):zO(this.trunkColor),roughness:1});return dT(i,DO),i.map=this.loadBarkTexture(n,r,`color`,!0),i.normalMap=this.loadBarkTexture(n,r,`normal`,!1),i.roughnessMap=this.loadBarkTexture(n,r,`roughness`,!1),i}loadBarkTexture(e,t,n,r){return NO(e,`${kO}/${t.texture}_${n}_1k.jpg`,e=>{e.wrapS=It,e.wrapT=It,e.repeat.set(t.repeat[0],t.repeat[1]),e.anisotropy=4,e.flipY=!1,r&&(e.colorSpace=dr)})}scatter(e,t){let n=(this.area[0]??0)/2,r=(this.area[1]??0)/2;for(let i=0;i<this.count;i++){let a=this.count===1?0:e.range(-n,n),o=this.count===1?0:e.range(-r,r);GO.set(a,this.drape?this.bedY(a,o):0,o),KO.setFromAxisAngle(UO,e.range(0,Math.PI*2));let s=this.height*e.range(vO[0],vO[1]),c=s*e.range(.9,1.1);qO.set(c,s,c),WO.compose(GO,KO,qO),JO.setHSL(yO,bO,.92).offsetHSL(e.range(-.055,xO),0,e.range(-.11,SO)),t(i,WO,JO)}}disposeMeshes(){let e=[this.simpleTrunk,this.simpleCanopy];for(let t of this.variants)e.push(t.branches,t.leaves);let t=new Set;for(let n of e)n&&(n.removeFromParent(),n.geometry.dispose(),t.add(n.material),n.dispose());for(let e of t)e.dispose();for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[],this.simpleTrunk=null,this.simpleCanopy=null,this.variants=[],this.swayUniform=null,this.leafFadeUniform=null}free(){this.disposeMeshes(),this.grove=null,super.free()}},MO=new Map;function NO(e,t,n,r){let i=MO.get(t);if(i)return i;let a=new yi;return n(a),e.load(t,e=>{a.image=e,r?r(a):a.needsUpdate=!0}),MO.set(t,a),a}function PO(e,t){let n=0;for(let r of new Set(AO[e][t]??[])){let e=kD(r);t===`dead`&&(e.leaves.count=0),n=Math.max(n,ED(e).total)}return n}function FO(e){return`${OO}/${e}_color.png`}function IO(e){let t=e.image;if(!t||typeof document>`u`)return;let n=document.createElement(`canvas`);n.width=t.naturalWidth||t.width,n.height=t.naturalHeight||t.height;let r=n.getContext(`2d`,{willReadFrequently:!0});if(!r)return;r.drawImage(t,0,0);let i;try{i=r.getImageData(0,0,n.width,n.height)}catch{return}let a=i.data,o=0,s=0,c=0,l=0;for(let e=0;e<a.length;e+=4)a[e+3]>240&&(o+=a[e],s+=a[e+1],c+=a[e+2],l++);if(l!==0){o=Math.round(o/l),s=Math.round(s/l),c=Math.round(c/l);for(let e=0;e<a.length;e+=4)a[e+3]<=240&&(a[e]=o,a[e+1]=s,a[e+2]=c);r.putImageData(i,0,0),e.image=n,e.needsUpdate=!0}}function LO(e){let t=new G(e),n=Math.max(t.r,t.g,t.b);return n>0?t.multiplyScalar(1/n):t.setRGB(1,1,1),t.lerp(RO,.18)}var RO=new G(1,1,1);function zO(e){let t=new G(e),n=Math.max(t.r,t.g,t.b);return n>0?t.multiplyScalar(1/n):t.setRGB(1,1,1),t}function BO(){return new nc({vertexColors:!0,roughness:1,flatShading:!0})}function VO(e){e.instanceMatrix.needsUpdate=!0,e.instanceColor&&(e.instanceColor.needsUpdate=!0),Sw(e)}function HO(e){e.castShadow=!0,e.receiveShadow=!0}var UO=new H(0,1,0),WO=new W,GO=new H,KO=new V,qO=new H,JO=new G,YO=[[[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4]],[[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[0,.8,0],[.6,.3,0]],[[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0]],[[.6,.55,.5],[.55,.5,.45],[.5,.45,.4],[.55,.5,.45],[.65,.6,.55],[.5,.45,.4]],[[.45,.45,.4],[.4,.4,.35],[.35,.35,.3],[.4,.4,.35],[.5,.5,.45],[.35,.35,.3]],[[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2]],[[.8,.5,.2],[.75,.45,.15],[.7,.4,.1],[.75,.45,.15],[.85,.55,.25],[.7,.4,.1]],[[0,.7,.1],[0,.65,.1],[0,.6,.1],[0,.65,.1],[0,.75,.1],[0,.6,.1]],[[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3]],[[0,0,.7],[0,0,.7],[0,0,.7],[0,0,.7],[0,.2,.9],[0,0,.6]],[[.9,.3,0],[.9,.3,0],[.9,.3,0],[.9,.3,0],[1,.4,0],[.7,.2,0]],[[.9,.8,.2],[.85,.75,.18],[.85,.75,.18],[.85,.75,.18],[.95,.85,.25],[.85,.75,.18]],[[.6,.6,.6],[.55,.55,.55],[.5,.5,.5],[.55,.55,.55],[.65,.65,.65],[.5,.5,.5]],[[.7,.7,.4],[.65,.65,.35],[.6,.6,.3],[.65,.65,.35],[.75,.75,.45],[.6,.6,.3]],[[.7,.5,.5],[.65,.45,.45],[.6,.4,.4],[.65,.45,.45],[.75,.55,.55],[.6,.4,.4]],[[.35,.3,.25],[.3,.25,.2],[.25,.2,.15],[.3,.25,.2],[.4,.35,.3],[.25,.2,.15]],[[.5,.3,0],[.5,.3,0],[.5,.3,0],[.5,.3,0],[.7,.4,.1],[.7,.4,.1]],[[0,.5,0],[0,.45,0],[0,.45,0],[0,.45,0],[0,.6,0],[0,.4,0]],[[.2,.8,.8],[.15,.7,.7],[.1,.6,.6],[.15,.7,.7],[.3,.9,.9],[.1,.6,.6]],[[1,.5,.8],[.9,.4,.7],[.8,.3,.6],[.9,.4,.7],[1,.6,.9],[.8,.3,.6]],[[1,.9,.3],[.95,.85,.25],[.9,.8,.2],[.95,.85,.25],[1,1,.4],[.9,.8,.2]],[[1,0,0],[.9,0,0],[.8,0,0],[.9,0,0],[1,.2,.2],[.8,0,0]],[[.6,.4,.2],[.5,.3,.15],[.4,.25,.1],[.5,.3,.15],[.7,.45,.25],[.4,.25,.1]],[[.6,.2,.8],[.5,.15,.7],[.4,.1,.6],[.5,.15,.7],[.7,.25,.9],[.4,.1,.6]],[[1,.8,0],[.95,.75,0],[.95,.75,0],[.95,.75,0],[1,.9,0],[.9,.7,0]],[[.6,.65,.7],[.55,.6,.65],[.5,.55,.6],[.55,.6,.65],[.65,.7,.75],[.5,.55,.6]]],XO=2e5,ZO=class extends qp{static typeName=`VoxelGrid3D`;static signals=[`blocksChanged`];static props={voxels:{default:[]}};voxels=[];appliedVoxels=null;map=new Map;mesh=null;dirty=!1;blockCount(){return this.map.size}tileAt(e,t,n){return this.map.get(`${e},${t},${n}`)}setBlocks(e){this.map.clear();for(let t of e)this.map.set(`${t.x},${t.y},${t.z}`,t.tile);this.dirty=!0,this.emit(`blocksChanged`)}addBlock(e){this.map.set(`${e.x},${e.y},${e.z}`,e.tile),this.dirty=!0,this.emit(`blocksChanged`)}removeBlockAt(e,t,n){let r=this.map.delete(`${e},${t},${n}`);return r&&(this.dirty=!0,this.emit(`blocksChanged`)),r}blocks(){let e=[];for(let[t,n]of this.map){let[r,i,a]=t.split(`,`).map(Number);e.push({x:r,y:i,z:a,tile:n})}return e}_createObject3D(){let e=new Rs(1,1,1),t=new ec({vertexShader:$O,fragmentShader:ek});this.mesh=new rs(e,t,XO),this.mesh.count=0,this.mesh.frustumCulled=!1;for(let e of QO)this.mesh.geometry.setAttribute(e,new Yo(new Float32Array(XO*3),3));return this.dirty=!0,this.mesh}update(){if(this.voxels.length>0&&this.voxels!==this.appliedVoxels&&(this.appliedVoxels=this.voxels,this.setBlocks(this.voxels.map(e=>({x:e[0]??0,y:e[1]??0,z:e[2]??0,tile:e[3]??0})))),!this.dirty||!this.mesh)return;this.dirty=!1;let e=new W,t=0;for(let[n,r]of this.map){if(t>=XO)break;let[i,a,o]=n.split(`,`).map(Number);e.setPosition(i,a,o),this.mesh.setMatrixAt(t,e);let s=YO[r]??YO[0];for(let e=0;e<6;e++){let n=this.mesh.geometry.getAttribute(QO[e]),r=s[e];n.setXYZ(t,r[0],r[1],r[2]),n.needsUpdate=!0}t++}this.mesh.count=t,this.mesh.instanceMatrix.needsUpdate=!0}},QO=[`colorFront`,`colorRight`,`colorBack`,`colorLeft`,`colorTop`,`colorBottom`],$O=`
|
|
7802
|
+
`,vD=1.25,yD=.6,bD=2.5,xD=.45,SD=4,CD=12,wD=1.5,TD=.35,ED=1.2,DD=2.2,OD=2,kD=.52,AD=.3,jD=1.5,MD=7,ND=.004,PD=8,FD=.5,ID=42,LD=26,RD=6,zD=.05,BD=1.5,VD={shallow:`#74b2a2`,deep:`#123f4b`,sky:`#8ab6d8`,horizon:`#9fb6c2`,bank:`#465447`},HD=`#e9f2ef`,UD=new H,WD={rippleScale:.85,rippleStrength:.09,flowRate:.42,fresnelScale:.95,standingAmp:.11,glideAmp:.025},GD=class e extends qp{static typeName=`River3D`;static props={path:{default:[]},width:{default:6},widths:{default:[]},depth:{default:.8},flowSpeed:{default:1.6},colors:{default:{}},absorption:{default:.5},opacity:{default:.85},foam:{default:1},ripples:{default:1},sunDirection:{default:[.5,.8,.3]},sunColor:{default:`#fff6e0`},sunIntensity:{default:1},terrain:{default:``},carve:{default:!0},flowForce:{default:1},spray:{default:1}};path=[];width=6;widths=[];depth=.8;flowSpeed=1.6;colors={};absorption=.5;opacity=.85;foam=1;ripples=1;sunDirection=[.5,.8,.3];sunColor=`#fff6e0`;sunIntensity=1;terrain=``;carve=!0;flowForce=1;spray=1;renderOrder=1;time=0;rings=[];falls=[];sprayKey=``;courseKey=``;bedAt=null;fitted=!1;rocks=[];rockScanAt=-1;world=[0,0,0];_bodies=[];static validateJson(e){let t=e;if(!Array.isArray(t.path))throw new y(`BAD_FORMAT`,`River3D '${e.name}' path must be an array of [x, z] points, got ${JSON.stringify(t.path)}.`,{prop:`path`});if(t.path.length>0&&t.path.length<2)throw new y(`BAD_FORMAT`,`River3D '${e.name}' path needs at least 2 points (source → mouth), got ${t.path.length}.`,{prop:`path`});if(t.path.forEach((t,n)=>{if(!Array.isArray(t)||t.length<2||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new y(`BAD_FORMAT`,`River3D '${e.name}' path[${n}] must be [x, z] with finite numbers, got ${JSON.stringify(t)}.`,{prop:`path`})}),!(typeof t.width==`number`&&t.width>0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' width must be a positive number of meters, got ${JSON.stringify(t.width)}.`,{prop:`width`});if(!Array.isArray(t.widths)||t.widths.some(e=>!(typeof e==`number`&&e>0)))throw new y(`BAD_FORMAT`,`River3D '${e.name}' widths must be a list of positive meters (source→mouth), got ${JSON.stringify(t.widths)}.`,{prop:`widths`});if(!(t.depth>0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' depth must be > 0 meters, got ${JSON.stringify(t.depth)}.`,{prop:`depth`});if(!(t.flowSpeed>=0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' flowSpeed must be >= 0 m/s, got ${JSON.stringify(t.flowSpeed)}.`,{prop:`flowSpeed`});for(let n of[`absorption`,`foam`,`ripples`,`flowForce`,`spray`,`sunIntensity`]){let r=t[n];if(!(typeof r==`number`&&r>=0))throw new y(`BAD_FORMAT`,`River3D '${e.name}' ${n} must be a number >= 0, got ${JSON.stringify(r)}.`,{prop:n})}if(!(t.opacity>=0&&t.opacity<=1))throw new y(`BAD_FORMAT`,`River3D '${e.name}' opacity must be within [0, 1], got ${JSON.stringify(t.opacity)}.`,{prop:`opacity`});let n=t.colors;if(typeof n!=`object`||!n||Array.isArray(n))throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors must be an object of { shallow, deep, sky, horizon, bank } hex strings.`,{prop:`colors`});for(let t of Object.keys(n)){if(!(t in VD))throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors has unknown key '${t}' — expected shallow, deep, sky, horizon or bank.`,{prop:`colors`});if(typeof n[t]!=`string`)throw new y(`BAD_FORMAT`,`River3D '${e.name}' colors.${t} must be a hex string, got ${JSON.stringify(n[t])}.`,{prop:`colors`})}}_createObject3D(){return new jo(new q,this.buildMaterial())}onReady(){this.ensureCourse()}onExitTree(){Pw(this,this.terrain)?._setExternalChannel(this,null)}update(e){this.time+=e,this.ensureCourse(),this.syncSpray(),this.flowForce>0&&this.rings.length>1&&this.sweepBodies(e)}_syncObject3D(){super._syncObject3D();let e=this._ensureObject3D();this.rebuildIfNeeded(e),this.syncUniforms(e)}_onRender3D(e){if(this.rings.length===0)return;(this.rockScanAt<0||this.time-this.rockScanAt>FD)&&(this.rockScanAt=this.time,this.scanRocks());let t=this._ensureObject3D().material.uniforms;this.syncRocks(t,e.camera.getWorldPosition(UD))}sampleAt(e,t){if(this.ensureCourse(),this.rings.length===0)return null;let[n,r,i]=this.world,a=dD(this.rings,e-n,t-i);return a?{...a,surfaceY:a.surfaceY+r}:null}fallsAt(){this.ensureCourse();let[e,t,n]=this.world;return this.falls.map(r=>({...r,worldX:r.x+e,worldY:r.baseY+t,worldZ:r.z+n}))}_rings(){return this.rings}_applySunDirection(t){let n=e.props.sunDirection?.default;this.sunDirection.every((e,t)=>e===n[t])&&(this._ensureObject3D().material.uniforms?.uSunDirection?.value)?.set(t[0],t[1],t[2])}free(){let e=this._ensureObject3D();e.geometry?.dispose(),e.material?.dispose?.(),super.free()}widthProfile(){return this.widths.length>0?this.widths:[this.width]}applyCarve(e){if(!e)return;if(!this.carve||this.path.length<2){e._setExternalChannel(this,null);return}e._setExternalChannel(this,null);let[t,,n]=Nw(this),[r,,i]=Nw(e),a=this.widthProfile(),o=e._heightmap(),s=(e.size[0]??1)/Math.max(1,o.segsX),c=oD(this.path.map(e=>[(e[0]??0)+t-r,(e[1]??0)+n-i]),Math.max(s,this.depth));if(c.length<2){e._setExternalChannel(this,null);return}let l=c[c.length-1].along||1,u=c.map(t=>e._heightmap().heightAt(t.x,t.z)),d=this.depth*DD,f=this.depth*MD,p=Array(c.length);for(let e=0;e<c.length;e++){let t=u[e]-d;if(e===0){p[e]=t;continue}let n=c[e].along-c[e-1].along,r=p[e-1]-n*ND;p[e]=Math.max(Math.min(t,r),u[e]-f)}let m=[];for(let e=1;e<c.length;e++){let t=c[e-1],n=c[e],r=Math.max((u[e-1]+u[e])/2-(p[e-1]+p[e])/2,0);if(r<=.001)continue;let i=sD(a,t.along/l)/2,o=Math.max(this.depth*OD,s*jD),d=Math.max(i-o*kD,i*AD,s*.5);m.push({path:[[t.x,t.z],[n.x,n.z]],width:d*2,depth:r,taper:o})}e._setExternalChannel(this,m)}resolveTerrain(){let e=Pw(this,this.terrain);if(!e&&this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`River3D '${this.name}' terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`});return e}ensureCourse(){let e=this.resolveTerrain(),t=Nw(this),n=JSON.stringify([this.path,this.width,this.widths,this.depth,this.flowSpeed,this.carve,e?e.name:``,t]);if(n===this.courseKey)return!1;if(this.courseKey=n,this.world=t,this.bedAt=null,this.applyCarve(e),this.path.length<2)return this.rings=[],this.falls=[],!0;let[r,i,a]=t;this.bedAt=e?(t,n)=>e.heightAt(t+r,n+a)-i:()=>-this.depth,this.fitted=e!==null;let o=this.widthProfile(),s=Math.min(...o);return this.rings=cD({path:this.path,widths:o,depth:this.depth,flowSpeed:this.flowSpeed,step:Math.min(Math.max(s*xD,yD),bD),bedAt:this.bedAt,fit:this.fitted}),this.falls=pD(this.rings),!0}rebuildIfNeeded(e){if(!this.ensureCourse()&&e.geometry.getAttribute(`position`))return;if(this.rings.length===0||!this.bedAt){e.geometry.dispose();let t=new q;t.setAttribute(`position`,new K(new Float32Array,3)),e.geometry=t;return}let t=this.widthProfile(),n=Math.min(...t),r=Math.max(...t),i=lD(this.rings,{acrossSegments:Math.min(CD,Math.max(SD,Math.round(r/wD))),bankOvershoot:this.fitted?1:vD,bedBlur:Math.min(n/2*TD,ED),bedAt:this.bedAt}),a=new q;a.setAttribute(`position`,new K(i.positions,3)),a.setAttribute(`normal`,new K(i.normals,3)),a.setAttribute(`aFlowUv`,new K(i.uvs,2)),a.setAttribute(`aFlow`,new K(i.flow,2)),a.setAttribute(`aRiver`,new K(i.river,4)),a.setIndex(new K(i.indices,1)),a.computeBoundingSphere(),e.geometry.dispose(),e.geometry=a}buildMaterial(){return new ec({vertexShader:gD,fragmentShader:_D,fog:!0,uniforms:{fogColor:{value:new G(`#ffffff`)},fogNear:{value:1},fogFar:{value:1e3},fogDensity:{value:25e-5},uTime:{value:0},uShallowColor:{value:new G(VD.shallow)},uDeepColor:{value:new G(VD.deep)},uFoamColor:{value:new G(HD)},uSkyColor:{value:new G(VD.sky)},uHorizonColor:{value:new G(VD.horizon)},uBankColor:{value:new G(VD.bank)},uSunDirection:{value:new H(.5,.8,.3)},uSunColor:{value:new G(this.sunColor)},uSunIntensity:{value:this.sunIntensity},uMaxDepth:{value:this.depth},uAbsorption:{value:this.absorption},uOpacity:{value:this.opacity},uFoam:{value:this.foam},uRippleScale:{value:WD.rippleScale},uRippleStrength:{value:WD.rippleStrength*this.ripples},uFlowRate:{value:WD.flowRate},uSparkle:{value:this.ripples},uRockCount:{value:0},uRocks:{value:Array.from({length:PD},()=>new bi)},uFresnelScale:{value:WD.fresnelScale},uStandingAmp:{value:WD.standingAmp},uGlideAmp:{value:WD.glideAmp}},transparent:!0,depthTest:!0,depthWrite:!1,side:2})}scanRocks(){let e=[],[t,n,r]=this.world,i=(i,a,o,s,c)=>{if(o<=.02)return;let l=dD(this.rings,i-t,a-r);if(!l||!l.inside)return;let u=l.surfaceY+n;if(s>u)return;let d=u-this.depth;if(c<d)return;let f=Math.min(Math.max((c-d)/Math.max(this.depth,.05),.2),1);e.push({x:i,z:a,radius:o,breaks:f})},a=this;for(;a.parent;)a=a.parent;let o=e=>{if(e instanceof yE){let[t,n,r]=e.size,[a,o,s]=Nw(e);for(let c of e.transforms){let e=c[4]??1,l=a+(c[0]??0),u=o+(c[1]??0),d=s+(c[2]??0),f=(n??1)*e/2;i(l,d,Math.max(t,r)*e/2,u-f,u+f)}}else if(e instanceof hE){let[t,n,r]=e.size,[a,o,s]=Nw(e),c=(n??1)/2;i(a,s,Math.max(t,r)/2,o-c,o+c)}for(let t of e.children)o(t)};o(a),this.rocks=e}syncRocks(e,t){let n=e.uRocks?.value,r=e.uRockCount;if(!n||!r)return;if(this.rocks.length===0){r.value=0;return}let i=[...this.rocks].map(e=>({r:e,d:(e.x-t.x)**2+(e.z-t.z)**2})).sort((e,t)=>e.d-t.d).slice(0,PD),a=0;for(let{r:e,d:t}of i){let r=Math.max(e.radius*ID,LD),i=Math.min(Math.sqrt(t)/r,1),o=Math.min(Math.max((i-.6)/.4,0),1),s=1-o*o*(3-2*o);s<=.01||(n[a]?.set(e.x,e.z,e.radius,e.breaks*s),a++)}r.value=a}syncUniforms(e){let t=e.material.uniforms,n=(e,n)=>{let r=t[e];r&&(r.value=n)},r=(e,n)=>{(t[e]?.value)?.set(n)},i=this.colors;n(`uTime`,this.time),r(`uShallowColor`,i.shallow??VD.shallow),r(`uDeepColor`,i.deep??VD.deep),r(`uSkyColor`,i.sky??VD.sky),r(`uHorizonColor`,i.horizon??VD.horizon),r(`uBankColor`,i.bank??VD.bank),r(`uSunColor`,this.sunColor),(t.uSunDirection?.value)?.set(this.sunDirection[0]??.5,this.sunDirection[1]??.8,this.sunDirection[2]??.3),n(`uSunIntensity`,this.sunIntensity),n(`uMaxDepth`,this.depth),n(`uAbsorption`,this.absorption),n(`uOpacity`,this.opacity),n(`uFoam`,this.foam),n(`uRippleStrength`,WD.rippleStrength*this.ripples),n(`uSparkle`,this.ripples)}syncSpray(){let e=this.spray>0?`${this.spray}|${JSON.stringify(this.falls)}`:``;if(e!==this.sprayKey){this.sprayKey=e;for(let e of[...this.children])e.name.startsWith(`__spray`)&&e.free();this.spray<=0||this.falls.forEach((e,t)=>{let n=new UE(`__spray${t}`);n.position=[e.x+e.dirX*.6,e.baseY+.15,e.z+e.dirZ*.6];let r=Math.min(1.6,.4+e.drop*.12)*this.spray;n.rate=Math.round(Math.min(46,10+e.drop*3)*this.spray),n.maxParticles=160,n.lifetime=[1,2.1],n.speed=[55*r,170*r],n.directionDeg=-90,n.spreadDeg=58,n.gravity=[0,-240,0],n.drag=1.2,n.sizeStart=16*r,n.sizeEnd=80*r,n.colorStart=`#ffffff`,n.colorEnd=`#dfe9ec`,n.alphaStart=.2,n.alphaEnd=0,n.blend=`normal`,n.depthTest=!0,this.addChild(n)})}}sweepBodies(e){let t=this;for(;t.parent;)t=t.parent;let n=this._bodies;if(n.length=0,KD(t,n),n.length===0)return;let[r,i,a]=this.world;for(let t of n){let n=Nw(t),o=dD(this.rings,n[0]-r,n[2]-a);if(!o?.inside)continue;let s=o.surfaceY+i,c=n[1]-rp(t.collider);if(c>s+zD||c<s-this.depth-BD)continue;let l=qD(t);if(!l)continue;let u=Math.min(1,this.flowForce*RD*e),d=(o.dirX*o.speed-(l[0]??0))*u,f=(o.dirZ*o.speed-(l[2]??0))*u;if(t instanceof Zp){let e=t.mass||1;t.applyImpulse([d*e,0,f*e])}else l[0]=(l[0]??0)+d,l[2]=(l[2]??0)+f}}};function KD(e,t){(e instanceof Qp||e instanceof Zp)&&t.push(e);for(let n of e.children)KD(n,t)}function qD(e){return e.velocity??e.linearVelocity}var JD=128,YD=class extends qp{static typeName=`Trail3D`;static props={width:{default:.3},color:{default:`#ffffff`},opacity:{default:.8},seconds:{default:.6},emitting:{default:!0},additive:{default:!1},minDistance:{default:.05}};width=.3;color=`#ffffff`;opacity=.8;seconds=.6;emitting=!0;additive=!1;minDistance=.05;points=[];clock=0;mesh=null;lastColor=``;_createObject3D(){let e=new Qi,t=new q;t.setAttribute(`position`,new K(new Float32Array(JD*2*3),3));let n=new yo({color:this.color,transparent:!0,opacity:this.opacity,side:2,depthWrite:!1,blending:this.additive?2:1});return this.mesh=new jo(t,n),this.mesh.frustumCulled=!1,this.mesh.matrixAutoUpdate=!1,this.mesh.matrixWorld.identity(),this.mesh.updateMatrixWorld=()=>{},e.add(this.mesh),e}update(e){for(this.clock+=e;this.points.length>0&&this.clock-this.points[0].t>this.seconds;)this.points.shift()}_onRender3D(e){let t=this._ensureObject3D();if(this.emitting){t.getWorldPosition(XD);let e=this.points[this.points.length-1];(!e||(e.x-XD.x)**2+(e.y-XD.y)**2+(e.z-XD.z)**2>this.minDistance*this.minDistance)&&(this.points.push({x:XD.x,y:XD.y,z:XD.z,t:this.clock}),this.points.length>JD&&this.points.shift())}let n=this.mesh;if(!n)return;n.matrixWorld.identity();let r=n.material;this.color!==this.lastColor&&(this.lastColor=this.color,r.color=new G(this.color)),r.opacity=this.opacity;let i=this.points.length,a=n.geometry,o=a.getAttribute(`position`);if(i<2){a.setDrawRange(0,0);return}for(let t=0;t<i;t++){let n=this.points[t],r=this.points[Math.min(t+1,i-1)]??n;ZD.set(r.x-n.x,r.y-n.y,r.z-n.z),ZD.lengthSq()<1e-8&&ZD.set(0,1,0),QD.set(e.camera.position.x-n.x,e.camera.position.y-n.y,e.camera.position.z-n.z),$D.crossVectors(ZD,QD).normalize();let a=(this.clock-n.t)/this.seconds,s=this.width/2*Math.max(0,1-a);o.setXYZ(t*2,n.x+$D.x*s,n.y+$D.y*s,n.z+$D.z*s),o.setXYZ(t*2+1,n.x-$D.x*s,n.y-$D.y*s,n.z-$D.z*s)}if(o.needsUpdate=!0,!a.index||a.index.count<(JD-1)*6){let e=[];for(let t=0;t<JD-1;t++){let n=t*2;e.push(n,n+1,n+2,n+1,n+3,n+2)}a.setIndex(e)}a.setDrawRange(0,(i-1)*6)}get pointCount(){return this.points.length}},XD=new H,ZD=new H,QD=new H,$D=new H;function eO(e){let{branch:t,leaves:n,type:r}=e,i=0,a=0,o=[{level:0,sections:t.sections[0],segments:t.segments[0]}];for(;o.length>0;){let e=o.shift();if(i+=e.sections*e.segments*2,e.level>=t.levels){a+=n.count===0?0:n.count+ +(r===`deciduous`);continue}r===`deciduous`&&o.push({level:e.level+1,sections:e.sections,segments:e.segments});let s=t.children[e.level]??0;for(let n=0;n<s;n++)o.push({level:e.level+1,sections:t.sections[e.level+1]??1,segments:t.segments[e.level+1]??3})}let s=n.billboard===`double`?2:1,c=a*s*2;return{branches:i,leaves:c,total:i+c}}var tO={ash:{type:`deciduous`,branch:{levels:3,angle:[0,48,75,60],children:[7,4,3,0],force:{direction:{x:0,y:1,z:0},strength:-.06},gnarliness:[.03,.25,.2,.09],length:[43.47,27.14,9.51,4.6],radius:[2,.63,.76,.7],sections:[12,8,6,4],segments:[12,6,4,3],start:[0,.23,.33,0],taper:[.7,.7,.7,.7],twist:[.09,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:16,start:0,size:2.67,sizeVariance:.72,alphaTest:.5}},aspen:{type:`deciduous`,branch:{levels:2,angle:[0,75,32,7],children:[10,3,3,0],force:{direction:{x:0,y:1,z:0},strength:.0148},gnarliness:[.05,.12,.12,.02],length:[50,6.07,11.19,1],radius:[.72,.41,.7,.7],sections:[12,10,8,6],segments:[8,6,4,3],start:[0,.59,.35,0],taper:[.37,.13,.7,.7],twist:[0,0,0,0]},leaves:{style:`aspen`,billboard:`double`,angle:30,count:11,start:.124,size:2.5,sizeVariance:.7,alphaTest:.5}},oak:{type:`deciduous`,branch:{levels:3,angle:[0,54,58,32],children:[6,4,3,0],force:{direction:{x:0,y:1,z:0},strength:-.01},gnarliness:[0,-.1,-.15,.09],length:[37.24,11.08,12.39,7.16],radius:[1.41,.9,.69,1.19],sections:[8,6,3,1],segments:[7,5,3,3],start:[0,.49,.06,.12],taper:[.73,.42,.69,.75],twist:[-.23,.42,0,0]},leaves:{style:`oak`,billboard:`double`,angle:42,count:18,start:.16,size:2.5,sizeVariance:.7,alphaTest:.5}},pine:{type:`evergreen`,branch:{levels:1,angle:[0,110,16,60],children:[82,3,5,0],force:{direction:{x:0,y:1,z:0},strength:-.003},gnarliness:[.05,.08,0,0],length:[50,23.87,14.08,1],radius:[1.05,.36,.7,.7],sections:[12,10,8,6],segments:[8,6,4,3],start:[0,.27,.14,.3],taper:[.7,.7,.7,.7],twist:[0,0,0,0]},leaves:{style:`pine`,billboard:`double`,angle:39,count:30,start:.09,size:1.435,sizeVariance:.201,alphaTest:.3}},bush:{type:`deciduous`,branch:{levels:3,angle:[0,21.5,62.6,60],children:[7,3,2,0],force:{direction:{x:0,y:1,z:0},strength:-.02},gnarliness:[.11,.09,.05,.09],length:[.1,15.3,5.59,4.6],radius:[.58,.95,.76,.7],sections:[6,6,4,3],segments:[4,4,4,3],start:[0,.53,.33,0],taper:[.7,.7,.7,.7],twist:[.3,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:8,start:0,size:2.45,sizeVariance:.717,alphaTest:.5}},"ash-forest":{type:`deciduous`,branch:{levels:2,angle:[0,48,75,60],children:[5,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.06},gnarliness:[.03,.25,.2,.09],length:[43.47,27.14,9.51,4.6],radius:[2,.63,.76,.7],sections:[6,5,4,4],segments:[6,4,3,3],start:[0,.3,.33,0],taper:[.7,.7,.7,.7],twist:[.09,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:15,start:0,size:3,sizeVariance:.6,alphaTest:.5}},"oak-forest":{type:`deciduous`,branch:{levels:2,angle:[0,54,58,32],children:[5,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.01},gnarliness:[0,-.1,-.15,.09],length:[37.24,11.08,12.39,7.16],radius:[1.41,.9,.69,1.19],sections:[6,4,3,1],segments:[6,4,3,3],start:[0,.49,.06,.12],taper:[.73,.42,.69,.75],twist:[-.23,.42,0,0]},leaves:{style:`oak`,billboard:`double`,angle:42,count:16,start:.1,size:2.9,sizeVariance:.7,alphaTest:.5}},"pine-forest":{type:`evergreen`,branch:{levels:1,angle:[0,110,16,60],children:[44,3,5,0],force:{direction:{x:0,y:1,z:0},strength:-.005},gnarliness:[.07,.09,0,0],length:[50,23.87,14.08,1],radius:[1.05,.36,.7,.7],sections:[6,5,8,6],segments:[6,3,4,3],start:[0,.27,.14,.3],taper:[.7,.7,.7,.7],twist:[0,0,0,0]},leaves:{style:`pine`,billboard:`double`,angle:39,count:9,start:.09,size:1.8,sizeVariance:.201,alphaTest:.3}},"bush-forest":{type:`deciduous`,branch:{levels:2,angle:[0,21.5,62.6,60],children:[6,3,0,0],force:{direction:{x:0,y:1,z:0},strength:-.02},gnarliness:[.11,.09,.05,.09],length:[.1,15.3,5.59,4.6],radius:[.58,.95,.76,.7],sections:[5,4,3,3],segments:[4,3,3,3],start:[0,.53,.33,0],taper:[.7,.7,.7,.7],twist:[.3,-.07,0,0]},leaves:{style:`ash`,billboard:`double`,angle:55,count:10,start:0,size:3.2,sizeVariance:.6,alphaTest:.5}}},nO=[`ash`,`aspen`,`oak`,`pine`,`bush`,`ash-forest`,`oak-forest`,`pine-forest`,`bush-forest`];function rO(e){let t=tO[e];if(!t)throw new y(`BAD_FORMAT`,`Unknown eztree preset '${e}' — must be one of [${nO.join(`, `)}].`,{prop:`preset`,validOptions:nO});return structuredClone(t)}var iO={ash:{texture:`oak`,tint:`#cecbbe`,repeat:[.5,1/5]},aspen:{texture:`birch`,tint:`#ffffff`,repeat:[1,1]},oak:{texture:`oak`,tint:`#fff3d1`,repeat:[1,1/10]},pine:{texture:`pine`,tint:`#ffffff`,repeat:[1,1]},bush:{texture:`oak`,tint:`#cecbbe`,repeat:[.5,1/5]}};function aO(e){if(!nO.includes(e))throw new y(`BAD_FORMAT`,`Unknown eztree preset '${e}' — must be one of [${nO.join(`, `)}].`,{prop:`preset`,validOptions:nO});return structuredClone(iO[e.replace(/-forest$/,``)])}var oO=.45,sO=.45,cO=.55,lO=.15,uO=.07,dO=.035;function fO(e,t){let n=Math.imul(e+1,374761393)+Math.imul(t+1,668265263)>>>0;return n=Math.imul(n^n>>>13,1274126177)>>>0,((n^n>>>16)>>>0)/4294967296}function pO(e,t,n){let r=e.length/3,i=new Float32Array(e.length),a=new Float32Array(e.length),o=1/0,s=1/0,c=1/0,l=-1/0,u=-1/0,d=-1/0;for(let t=0;t<r;t++){let n=e[t*3],r=e[t*3+1],i=e[t*3+2];n<o&&(o=n),n>l&&(l=n),r<s&&(s=r),r>u&&(u=r),i<c&&(c=i),i>d&&(d=i)}let f=(o+l)/2,p=(s+u)/2,m=(c+d)/2,h=Math.max((l-o)/2,.001),g=Math.max((u-s)/2,.001),_=Math.max((d-c)/2,.001),v=new Map;for(let n=0;n<r;n++){let r=t[n],i=v.get(r);i||(i={x:0,y:0,z:0,n:0},v.set(r,i)),i.x+=e[n*3],i.y+=e[n*3+1],i.z+=e[n*3+2],i.n++}for(let e of v.values())e.x/=e.n,e.y/=e.n,e.z/=e.n;for(let o=0;o<r;o++){let r=e[o*3],c=e[o*3+1],l=e[o*3+2],d=(r-f)/h,y=(c-p)/g,b=(l-m)/_,x,S,C,w;if(n===`evergreen`){let e=Math.hypot(r-f,l-m);if(e<1e-6)x=0,S=1,C=0;else{let t=1/Math.hypot(1,sO);x=(r-f)/e*t,S=sO*t,C=(l-m)/e*t}let t=(c-s)/Math.max(u-s,.001),n=Math.max(lO,1-t);w=Math.min(1,Math.hypot(d,b)/n)}else{let e=d/h,t=y/g,n=b/_,r=Math.hypot(e,t,n);r<1e-6?(x=0,S=1,C=0):(x=e/r,S=t/r,C=n/r),w=Math.min(1,Math.hypot(d,y,b))}let T=v.get(t[o]);if(T){let e=r-T.x,t=c-T.y,n=l-T.z,i=Math.hypot(e,t,n);if(i>1e-6){x=x*(1-cO)+e/i*cO,S=S*(1-cO)+t/i*cO,C=C*(1-cO)+n/i*cO;let r=Math.hypot(x,S,C);r>1e-6?(x/=r,S/=r,C/=r):(x=0,S=1,C=0)}}i[o*3]=x,i[o*3+1]=S,i[o*3+2]=C;let E=oO+(1-oO)*w,D=t[o],O=E*(1-uO*fO(D,1)),k=(fO(D,2)-.5)*2*dO;a[o*3]=O*(1+k),a[o*3+1]=O,a[o*3+2]=O*(1-k)}return{normals:i,colors:a}}var mO=class e{static MASK=4294967295;mW;mZ;constructor(t){this.mW=123456789+t&e.MASK,this.mZ=987654321-t&e.MASK}random(t=1,n=0){this.mZ=36969*(this.mZ&65535)+(this.mZ>>16)&e.MASK,this.mW=18e3*(this.mW&65535)+(this.mW>>16)&e.MASK;let r=((this.mZ<<16)+(this.mW&65535)>>>0)/4294967296;return(t-n)*r+n}};function hO(e,t,n){let r=new mO(t),i={branchVerts:[],branchNormals:[],branchUvs:[],branchIndices:[],leafVerts:[],leafIndices:[],leafUvs:[],leafAnchors:[],leafClusters:[],leafClusterNext:0},a=[{origin:new H,orientation:new Pi,length:e.branch.length[0],radius:e.branch.radius[0],level:0,sectionCount:e.branch.sections[0],segmentCount:e.branch.segments[0]}];for(;a.length>0;)gO(e,r,i,a,a.shift());CO(i,n);let o=new q;o.setAttribute(`position`,new K(new Float32Array(i.branchVerts),3)),o.setAttribute(`normal`,new K(new Float32Array(i.branchNormals),3)),o.setAttribute(`uv`,new K(new Float32Array(i.branchUvs),2)),o.setIndex(new K(wO(i.branchIndices,i.branchVerts),1)),o.computeBoundingSphere();let s=null;if(i.leafVerts.length>0){s=new q,s.setAttribute(`position`,new K(new Float32Array(i.leafVerts),3)),s.setAttribute(`anchor`,new K(new Float32Array(i.leafAnchors),3)),s.setAttribute(`uv`,new K(new Float32Array(i.leafUvs),2)),s.setIndex(new K(wO(i.leafIndices,i.leafVerts),1));let t=pO(i.leafVerts,i.leafClusters,e.type);s.setAttribute(`normal`,new K(t.normals,3)),s.setAttribute(`color`,new K(t.colors,3)),s.computeBoundingSphere()}return{branches:o,leaves:s}}function gO(e,t,n,r,i){let a=n.branchVerts.length/3,o=i.orientation.clone(),s=i.origin.clone(),c=i.length/i.sectionCount,l=[];for(let r=0;r<=i.sectionCount;r++){let a=i.radius;r===i.sectionCount&&i.level===e.branch.levels?a=.001:e.type===`deciduous`?a*=1-(e.branch.taper[i.level]??0)*(r/i.sectionCount):a*=1-r/i.sectionCount;let u=new H,d=new H,f=0;for(let e=0;e<i.segmentCount;e++){let t=2*Math.PI*e/i.segmentCount,c=new H(Math.cos(t),0,Math.sin(t)).multiplyScalar(a).applyEuler(o).add(s),l=new H(Math.cos(t),0,Math.sin(t)).applyEuler(o).normalize(),p=r%2==0?0:1;n.branchVerts.push(c.x,c.y,c.z),n.branchNormals.push(l.x,l.y,l.z),n.branchUvs.push(e/i.segmentCount,p),e===0&&(u=c,d=l,f=p)}n.branchVerts.push(u.x,u.y,u.z),n.branchNormals.push(d.x,d.y,d.z),n.branchUvs.push(1,f),l.push({origin:s.clone(),orientation:o.clone(),radius:a}),s.add(new H(0,c,0).applyEuler(o));let p=Math.max(1,1/Math.sqrt(a))*(e.branch.gnarliness[i.level]??0);o.x+=t.random(p,-p),o.z+=t.random(p,-p);let m=new V().setFromEuler(o),h=new V().setFromAxisAngle(new H(0,1,0),e.branch.twist[i.level]??0),g=e.branch.force,_=new V().setFromUnitVectors(new H(0,1,0),new H(g.direction.x,g.direction.y,g.direction.z));m.multiply(h),m.rotateTowards(_,g.strength/a),o.setFromQuaternion(m)}SO(n,a,i);let u=i.level===e.branch.levels?n.leafClusterNext++:0;if(e.type===`deciduous`){let a=l[l.length-1];i.level<e.branch.levels?r.push({origin:a.origin,orientation:a.orientation,length:e.branch.length[i.level+1]??0,radius:a.radius,level:i.level+1,sectionCount:i.sectionCount,segmentCount:i.segmentCount}):e.leaves.count>0&&xO(e,t,n,a.origin,a.orientation,u)}i.level===e.branch.levels?bO(e,t,n,l,u):i.level<e.branch.levels&&yO(e,t,r,e.branch.children[i.level]??0,i.level+1,l)}function _O(e,t){let n=Math.floor(t*(e.length-1)),r=e[n],i=n===e.length-1?r:e[n+1],a=(t-n/(e.length-1))/(1/(e.length-1)),o=new H().lerpVectors(r.origin,i.origin,a),s=new V().setFromEuler(r.orientation),c=new V().setFromEuler(i.orientation);return{origin:o,orientation:new Pi().setFromQuaternion(c.slerp(s,a)),radius:{a:r.radius,b:i.radius,alpha:a}}}function vO(e,t,n){let r=new V().setFromAxisAngle(new H(1,0,0),t/(180/Math.PI)),i=new V().setFromAxisAngle(new H(0,1,0),n),a=new V().setFromEuler(e);return new Pi().setFromQuaternion(a.multiply(i.multiply(r)))}function yO(e,t,n,r,i,a){let o=t.random();for(let s=0;s<r;s++){let c=t.random(1,e.branch.start[i]??0),l=_O(a,c),u=(e.branch.radius[i]??0)*((1-l.radius.alpha)*l.radius.a+l.radius.alpha*l.radius.b),d=2*Math.PI*(o+s/r),f=vO(l.orientation,e.branch.angle[i]??0,d),p=(e.branch.length[i]??0)*(e.type===`evergreen`?1-c:1);n.push({origin:l.origin,orientation:f,length:p,radius:u,level:i,sectionCount:e.branch.sections[i]??1,segmentCount:e.branch.segments[i]??3})}}function bO(e,t,n,r,i){let a=t.random();for(let o=0;o<e.leaves.count;o++){let s=_O(r,t.random(1,e.leaves.start)),c=2*Math.PI*(a+o/e.leaves.count),l=vO(s.orientation,e.leaves.angle,c);xO(e,t,n,s.origin,l,i)}}function xO(e,t,n,r,i,a){let o=n.leafVerts.length/3,s=e.leaves.size*(1+t.random(e.leaves.sizeVariance,-e.leaves.sizeVariance)),c=e=>{let t=s/2,c=[new H(-t,s,0),new H(-t,0,0),new H(t,0,0),new H(t,s,0)];for(let t of c)t.applyEuler(new Pi(0,e,0)).applyEuler(i).add(r),n.leafVerts.push(t.x,t.y,t.z),n.leafAnchors.push(r.x,r.y,r.z),n.leafClusters.push(a);n.leafUvs.push(0,1,0,0,1,0,1,1),n.leafIndices.push(o,o+1,o+2,o,o+2,o+3),o+=4};c(0),e.leaves.billboard===`double`&&c(Math.PI/2)}function SO(e,t,n){let r=n.segmentCount+1;for(let i=0;i<n.sectionCount;i++)for(let a=0;a<n.segmentCount;a++){let n=t+i*r+a,o=t+i*r+(a+1),s=n+r,c=o+r;e.branchIndices.push(n,s,o,o,s,c)}}function CO(e,t){let n=0;for(let t=1;t<e.branchVerts.length;t+=3){let r=e.branchVerts[t];r>n&&(n=r)}for(let t=1;t<e.leafVerts.length;t+=3){let r=e.leafVerts[t];r>n&&(n=r)}if(n<=0)return;let r=t/n;for(let t=0;t<e.branchVerts.length;t++)e.branchVerts[t]=e.branchVerts[t]*r;for(let t=0;t<e.leafVerts.length;t++)e.leafVerts[t]=e.leafVerts[t]*r;for(let t=0;t<e.leafAnchors.length;t++)e.leafAnchors[t]=e.leafAnchors[t]*r}function wO(e,t){return t.length/3>65535?new Uint32Array(e):new Uint16Array(e)}var TO=[`simple`,`medium`,`high`],EO=[`conifer`,`broadleaf`,`dead`,`bush`];function DO(e,t,n){return new y(`BAD_FORMAT`,`Tree3D ${e} must be one of [${n.join(`, `)}], got '${t}'.`,{prop:e,validOptions:n})}var OO={simple:0,medium:1,high:2},kO=[5,7,10],AO=[2,3,4],jO=[6,8,12],MO=[2,3,3],NO=[0,1,2],PO=[3,4,5],FO=3;function IO(e,t){if(!TO.includes(e))throw DO(`tier`,e,TO);if(!EO.includes(t))throw DO(`type`,t,EO);let n=e,r=t,i=OO[n];return{tier:n,type:r,trunkRadialSegments:kO[i],canopyLayers:r===`conifer`?AO[i]:0,canopySegments:jO[i],blobCount:r===`broadleaf`||r===`bush`?MO[i]:0,blobDetail:NO[i],branchCount:r===`dead`?PO[i]:r===`conifer`&&n===`high`?FO:0,hasCanopy:r!==`dead`,canopySway:n!==`simple`}}var LO=.02,RO={conifer:{trunkHeight:.4,trunkRadiusBottom:.05,trunkRadiusTop:.035},broadleaf:{trunkHeight:.42,trunkRadiusBottom:.05,trunkRadiusTop:.032},dead:{trunkHeight:.72,trunkRadiusBottom:.045,trunkRadiusTop:.018},bush:{trunkHeight:.14,trunkRadiusBottom:.045,trunkRadiusTop:.035}};function zO(e,t,n){let{trunkHeight:r,trunkRadiusBottom:i,trunkRadiusTop:a}=RO[e.type],o=[],s=new Bs(a,i,r,e.trunkRadialSegments).toNonIndexed();if(s.translate(0,r/2,0),o.push(s),e.type===`dead`)for(let n=0;n<e.branchCount;n++){let r=.22+t.next()*.14,a=new Bs(.006,.02,r,5).toNonIndexed();a.translate(0,r/2,0);let s=.7+t.next()*.6,c=n/e.branchCount*Math.PI*2+t.next()*.8,l=.34+(n+t.next())/e.branchCount*.34;a.applyMatrix4(new W().makeRotationY(c).multiply(new W().makeRotationX(s)).setPosition(Math.sin(c)*i*.6,l,Math.cos(c)*i*.6)),o.push(a)}let c=VO(o);return UO(c,new G(n),.7,1.05,t),c}function BO(e,t,n){if(!e.hasCanopy)return null;let r=[];if(e.type===`conifer`){let n=.74;for(let i=0;i<e.canopyLayers;i++){let a=i/e.canopyLayers,o=.3*(1-a*.62)*(.92+t.next()*.16),s=n/e.canopyLayers*1.7,c=new Vs(o,s,e.canopySegments).toNonIndexed();HO(c,t,LO),c.translate(0,.26+n*a+s/2,0),r.push(c)}for(let n=0;n<e.branchCount;n++){let i=new Vs(.06,.2,5).toNonIndexed(),a=n/Math.max(e.branchCount,1)*Math.PI*2+t.next(),o=1.1+t.next()*.4;i.applyMatrix4(new W().makeRotationY(a).multiply(new W().makeRotationX(o)).setPosition(Math.sin(a)*.22,.34+t.next()*.18,Math.cos(a)*.22)),r.push(i)}}else{let{trunkHeight:n}=RO[e.type];for(let i=0;i<e.blobCount;i++){let a=new Us((i===0?.3:.24-i*.02)*(.92+t.next()*.16),e.blobDetail).toNonIndexed();a.scale(1,.72,1),HO(a,t,LO);let o=i===0?0:.13,s=t.next()*Math.PI*2;a.translate(Math.cos(s)*o,n+.16+i*.1+t.next()*.05,Math.sin(s)*o),r.push(a)}}let i=VO(r);return UO(i,new G(n),.62,1.18,t),i}function VO(e){let t=0;for(let n of e)t+=n.getAttribute(`position`).count;let n=new Float32Array(t*3),r=new Float32Array(t*3),i=0;for(let t of e)n.set(t.getAttribute(`position`).array,i),r.set(t.getAttribute(`normal`).array,i),i+=t.getAttribute(`position`).count*3,t.dispose();let a=new q;return a.setAttribute(`position`,new K(n,3)),a.setAttribute(`normal`,new K(r,3)),a}function HO(e,t,n){let r=e.getAttribute(`position`);for(let e=0;e<r.count;e++)r.setXYZ(e,r.getX(e)+t.range(-n,n),r.getY(e)+t.range(-n,n),r.getZ(e)+t.range(-n,n))}function UO(e,t,n,r,i){let a=e.getAttribute(`position`),o=new Float32Array(a.count*3),s=1/0,c=-1/0;for(let e=0;e<a.count;e++){let t=a.getY(e);t<s&&(s=t),t>c&&(c=t)}let l=Math.max(c-s,1e-6),u=new G;for(let e=0;e<a.count;e++){let c=(a.getY(e)-s)/l,d=(n+(r-n)*c)*(.96+i.next()*.08);u.copy(t).multiplyScalar(d),o[e*3]=u.r,o[e*3+1]=u.g,o[e*3+2]=u.b}e.setAttribute(`color`,new K(o,3))}var WO=500,GO=15e5,KO=[.8,1.2],qO=.28,JO=.12,YO=.055,XO=.11,ZO=3,QO=101,$O=[.78,.7,.45],ek=.45,tk=.55,nk=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation`,rk=`https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark`,ik={high:{conifer:[`pine`,`pine`,`pine`],broadleaf:[`oak`,`ash`,`oak`],dead:[`ash`,`ash`,`ash`],bush:[`bush`,`bush`,`bush`]},medium:{conifer:[`pine-forest`,`pine-forest`,`pine-forest`],broadleaf:[`oak-forest`,`ash-forest`,`oak-forest`],dead:[`ash-forest`,`ash-forest`,`ash-forest`],bush:[`bush-forest`,`bush-forest`,`bush-forest`]}},ak=class e extends qp{static typeName=`Tree3D`;static props={tier:{default:`medium`,options:TO},type:{default:`conifer`,options:EO},seed:{default:1},height:{default:6},count:{default:1},area:{default:[10,10]},trunkColor:{default:`#7a5a3a`},canopyColor:{default:`#4a7c3f`},leafTexture:{default:``},leafFadeStart:{default:0},leafFadeEnd:{default:0},leafShadows:{default:!0},drape:{default:null},terrain:{default:``}};tier=`medium`;type=`conifer`;seed=1;height=6;count=1;area=[10,10];trunkColor=`#7a5a3a`;canopyColor=`#4a7c3f`;leafTexture=``;leafFadeStart=0;leafFadeEnd=0;leafShadows=!0;drape=null;terrain=``;drapeTerrain=null;drapeWorld=[0,0,0];static validateJson(e){let t=e;if(IO(t.tier,t.type),!(t.height>0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' height must be > 0 meters, got ${t.height}.`,{prop:`height`});if(!Number.isInteger(t.count)||t.count<1||t.count>WO)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' count must be an integer in 1..${WO}, got ${t.count}.`,{prop:`count`});if(!((t.area[0]??0)>0)||!((t.area[1]??0)>0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`,{prop:`area`});if(t.leafFadeEnd!==0&&!(t.leafFadeEnd>t.leafFadeStart&&t.leafFadeStart>=0))throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' needs leafFadeEnd > leafFadeStart >= 0 (the leaf LOD window) or 0/0 to disable, got start ${t.leafFadeStart}, end ${t.leafFadeEnd}.`,{prop:`leafFadeStart`});if(typeof t.leafShadows!=`boolean`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' leafShadows must be a boolean, got ${JSON.stringify(t.leafShadows)}.`,{prop:`leafShadows`});if(t.drape!==null&&typeof t.drape!=`boolean`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`,{prop:`drape`});if(typeof t.terrain!=`string`)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`,{prop:`terrain`});if(t.tier===`simple`)return;let n=ck(t.tier,t.type),r=n*t.count;if(r>GO)throw new y(`BAD_FORMAT`,`Tree3D '${e.name}' blows the grove triangle budget: count ${t.count} × ${n} tris/tree (tier '${t.tier}', type '${t.type}') = ${r} > ${GO}. Lower count (max ${Math.floor(GO/n)} at this tier), drop tier to 'medium'/'simple', or split the grove into multiple nodes.`,{prop:`count`})}time=0;grove=null;variants=[];simpleTrunk=null;simpleCanopy=null;swayUniform=null;leafFadeUniform=null;loadedTextures=[];groveKey=``;_createObject3D(){return new Qi}_trunk(){return this.rebuildIfNeeded(),this.simpleTrunk??this.variants[0]?.branches}_canopy(){return this.rebuildIfNeeded(),this.simpleTrunk?this.simpleCanopy:this.variants[0]?.leaves??null}_variantMeshes(){return this.rebuildIfNeeded(),this.variants}update(e){this.time+=e,this.swayUniform&&(this.swayUniform.value=this.time),this.leafFadeUniform&&(this.leafFadeUniform.start.value=this.leafFadeStart,this.leafFadeUniform.end.value=this.leafFadeEnd)}_syncObject3D(){super._syncObject3D(),this.rebuildIfNeeded()}rebuildIfNeeded(){this.grove||(this.grove=new Qi,this._ensureObject3D().add(this.grove));let e=JSON.stringify([this.tier,this.type,this.seed,this.height,this.count,this.area,this.trunkColor,this.canopyColor,this.leafTexture,this.leafShadows,this.leafFadeEnd>this.leafFadeStart,this.drape,this.terrain]);e===this.groveKey&&(this.simpleTrunk||this.variants.length>0)||(this.groveKey=e,this.disposeMeshes(),this.resolveDrape(),this.tier===`simple`?this.buildSimpleGrove():this.buildEzGrove())}resolveDrape(){if(this.drapeTerrain=null,this.drape===!1)return;let e=Pw(this,this.terrain);if(e)this.drapeTerrain=e,this.drapeWorld=Nw(this);else if(this.terrain!==``)throw new y(`NODE_NOT_FOUND`,`Tree3D '${this.name}' drape terrain '${this.terrain}' is not a Terrain3D in the tree.`,{prop:`terrain`})}bedY(e,t){let n=this.drapeTerrain;return n?n.heightAt(this.drapeWorld[0]+e,this.drapeWorld[2]+t)-this.drapeWorld[1]:0}buildSimpleGrove(){let e=IO(this.tier,this.type),t=new b(this.seed),n=zO(e,t,this.trunkColor),r=BO(e,t,this.canopyColor),i=new rs(n,mk(),this.count);gk(i);let a=null;r&&(a=new rs(r,mk(),this.count),gk(a)),this.scatter(t,(e,t,n)=>{i.setMatrixAt(e,t),i.setColorAt(e,n),a?.setMatrixAt(e,t),a?.setColorAt(e,n)}),hk(i),a&&hk(a),this.simpleTrunk=i,this.simpleCanopy=a,this.grove.add(i),a&&this.grove.add(a)}buildEzGrove(){let e=ik[this.tier][this.type],t=Math.min(ZO,this.count),n=Array.from({length:t},(e,n)=>Math.floor(this.count/t)+ +(n<this.count%t));this.swayUniform={value:this.time},this.leafFadeUniform=this.leafFadeEnd>this.leafFadeStart?{start:{value:this.leafFadeStart},end:{value:this.leafFadeEnd}}:null;let r=dk(this.canopyColor),i=null;typeof document<`u`&&typeof createImageBitmap==`function`&&(i=new ol,i.setOptions({imageOrientation:`flipY`}));for(let a=0;a<t;a++){let t=n[a],o=e[a],s=rO(o);this.type===`dead`&&(s.leaves.count=0);let c=hO(s,this.seed+a*QO,1),l=this.buildBarkMaterial(o,i),u=new rs(c.branches,l,t);gk(u);let d=null;if(c.leaves){let e=new nc({color:r.clone().multiply(new G($O[0],$O[1],$O[2])),roughness:1,side:2,vertexColors:!0,alphaTest:s.leaves.alphaTest}),n=this.leafTexture||lk(s.leaves.style);i&&(e.map=sk(i,n,e=>{e.colorSpace=dr,e.flipY=!1},e=>uk(e))),ST(e,this.swayUniform,ek,this.leafFadeUniform??void 0),d=new rs(c.leaves,e,t),gk(d),this.leafShadows||(d.castShadow=!1)}this.variants.push({branches:u,leaves:d}),this.grove.add(u),d&&this.grove.add(d)}let a=Array(t).fill(0),o=new b(this.seed);this.scatter(o,(e,n,r)=>{let i=e%t,o=this.variants[i],s=a[i];a[i]=s+1,o.branches.setMatrixAt(s,n),o.branches.setColorAt(s,r),o.leaves?.setMatrixAt(s,n),o.leaves?.setColorAt(s,r)});for(let e of this.variants)hk(e.branches),e.leaves&&hk(e.leaves)}buildBarkMaterial(t,n){if(this.type===`dead`||!n)return new nc({color:new G(this.trunkColor),roughness:1});let r=aO(t),i=new nc({color:this.trunkColor===e.props.trunkColor?.default?new G(r.tint):pk(this.trunkColor),roughness:1});return xT(i,tk),i.map=this.loadBarkTexture(n,r,`color`,!0),i.normalMap=this.loadBarkTexture(n,r,`normal`,!1),i.roughnessMap=this.loadBarkTexture(n,r,`roughness`,!1),i}loadBarkTexture(e,t,n,r){return sk(e,`${rk}/${t.texture}_${n}_1k.jpg`,e=>{e.wrapS=It,e.wrapT=It,e.repeat.set(t.repeat[0],t.repeat[1]),e.anisotropy=4,e.flipY=!1,r&&(e.colorSpace=dr)})}scatter(e,t){let n=(this.area[0]??0)/2,r=(this.area[1]??0)/2;for(let i=0;i<this.count;i++){let a=this.count===1?0:e.range(-n,n),o=this.count===1?0:e.range(-r,r);yk.set(a,this.drape?this.bedY(a,o):0,o),bk.setFromAxisAngle(_k,e.range(0,Math.PI*2));let s=this.height*e.range(KO[0],KO[1]),c=s*e.range(.9,1.1);xk.set(c,s,c),vk.compose(yk,bk,xk),Sk.setHSL(qO,JO,.92).offsetHSL(e.range(-.055,YO),0,e.range(-.11,XO)),t(i,vk,Sk)}}disposeMeshes(){let e=[this.simpleTrunk,this.simpleCanopy];for(let t of this.variants)e.push(t.branches,t.leaves);let t=new Set;for(let n of e)n&&(n.removeFromParent(),n.geometry.dispose(),t.add(n.material),n.dispose());for(let e of t)e.dispose();for(let e of this.loadedTextures)e.dispose();this.loadedTextures=[],this.simpleTrunk=null,this.simpleCanopy=null,this.variants=[],this.swayUniform=null,this.leafFadeUniform=null}free(){this.disposeMeshes(),this.grove=null,super.free()}},ok=new Map;function sk(e,t,n,r){let i=ok.get(t);if(i)return i;let a=new yi;return n(a),e.load(t,e=>{a.image=e,r?r(a):a.needsUpdate=!0}),ok.set(t,a),a}function ck(e,t){let n=0;for(let r of new Set(ik[e][t]??[])){let e=rO(r);t===`dead`&&(e.leaves.count=0),n=Math.max(n,eO(e).total)}return n}function lk(e){return`${nk}/${e}_color.png`}function uk(e){let t=e.image;if(!t||typeof document>`u`)return;let n=document.createElement(`canvas`);n.width=t.naturalWidth||t.width,n.height=t.naturalHeight||t.height;let r=n.getContext(`2d`,{willReadFrequently:!0});if(!r)return;r.drawImage(t,0,0);let i;try{i=r.getImageData(0,0,n.width,n.height)}catch{return}let a=i.data,o=0,s=0,c=0,l=0;for(let e=0;e<a.length;e+=4)a[e+3]>240&&(o+=a[e],s+=a[e+1],c+=a[e+2],l++);if(l!==0){o=Math.round(o/l),s=Math.round(s/l),c=Math.round(c/l);for(let e=0;e<a.length;e+=4)a[e+3]<=240&&(a[e]=o,a[e+1]=s,a[e+2]=c);r.putImageData(i,0,0),e.image=n,e.needsUpdate=!0}}function dk(e){let t=new G(e),n=Math.max(t.r,t.g,t.b);return n>0?t.multiplyScalar(1/n):t.setRGB(1,1,1),t.lerp(fk,.18)}var fk=new G(1,1,1);function pk(e){let t=new G(e),n=Math.max(t.r,t.g,t.b);return n>0?t.multiplyScalar(1/n):t.setRGB(1,1,1),t}function mk(){return new nc({vertexColors:!0,roughness:1,flatShading:!0})}function hk(e){e.instanceMatrix.needsUpdate=!0,e.instanceColor&&(e.instanceColor.needsUpdate=!0),Mw(e)}function gk(e){e.castShadow=!0,e.receiveShadow=!0}var _k=new H(0,1,0),vk=new W,yk=new H,bk=new V,xk=new H,Sk=new G,Ck=[[[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4],[.4,.4,.4]],[[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[0,.8,0],[.6,.3,0]],[[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0],[.6,.3,0]],[[.6,.55,.5],[.55,.5,.45],[.5,.45,.4],[.55,.5,.45],[.65,.6,.55],[.5,.45,.4]],[[.45,.45,.4],[.4,.4,.35],[.35,.35,.3],[.4,.4,.35],[.5,.5,.45],[.35,.35,.3]],[[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2],[.2,.2,.2]],[[.8,.5,.2],[.75,.45,.15],[.7,.4,.1],[.75,.45,.15],[.85,.55,.25],[.7,.4,.1]],[[0,.7,.1],[0,.65,.1],[0,.6,.1],[0,.65,.1],[0,.75,.1],[0,.6,.1]],[[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3],[.3,.3,.3]],[[0,0,.7],[0,0,.7],[0,0,.7],[0,0,.7],[0,.2,.9],[0,0,.6]],[[.9,.3,0],[.9,.3,0],[.9,.3,0],[.9,.3,0],[1,.4,0],[.7,.2,0]],[[.9,.8,.2],[.85,.75,.18],[.85,.75,.18],[.85,.75,.18],[.95,.85,.25],[.85,.75,.18]],[[.6,.6,.6],[.55,.55,.55],[.5,.5,.5],[.55,.55,.55],[.65,.65,.65],[.5,.5,.5]],[[.7,.7,.4],[.65,.65,.35],[.6,.6,.3],[.65,.65,.35],[.75,.75,.45],[.6,.6,.3]],[[.7,.5,.5],[.65,.45,.45],[.6,.4,.4],[.65,.45,.45],[.75,.55,.55],[.6,.4,.4]],[[.35,.3,.25],[.3,.25,.2],[.25,.2,.15],[.3,.25,.2],[.4,.35,.3],[.25,.2,.15]],[[.5,.3,0],[.5,.3,0],[.5,.3,0],[.5,.3,0],[.7,.4,.1],[.7,.4,.1]],[[0,.5,0],[0,.45,0],[0,.45,0],[0,.45,0],[0,.6,0],[0,.4,0]],[[.2,.8,.8],[.15,.7,.7],[.1,.6,.6],[.15,.7,.7],[.3,.9,.9],[.1,.6,.6]],[[1,.5,.8],[.9,.4,.7],[.8,.3,.6],[.9,.4,.7],[1,.6,.9],[.8,.3,.6]],[[1,.9,.3],[.95,.85,.25],[.9,.8,.2],[.95,.85,.25],[1,1,.4],[.9,.8,.2]],[[1,0,0],[.9,0,0],[.8,0,0],[.9,0,0],[1,.2,.2],[.8,0,0]],[[.6,.4,.2],[.5,.3,.15],[.4,.25,.1],[.5,.3,.15],[.7,.45,.25],[.4,.25,.1]],[[.6,.2,.8],[.5,.15,.7],[.4,.1,.6],[.5,.15,.7],[.7,.25,.9],[.4,.1,.6]],[[1,.8,0],[.95,.75,0],[.95,.75,0],[.95,.75,0],[1,.9,0],[.9,.7,0]],[[.6,.65,.7],[.55,.6,.65],[.5,.55,.6],[.55,.6,.65],[.65,.7,.75],[.5,.55,.6]]],wk=2e5,Tk=class extends qp{static typeName=`VoxelGrid3D`;static signals=[`blocksChanged`];static props={voxels:{default:[]}};voxels=[];appliedVoxels=null;map=new Map;mesh=null;dirty=!1;blockCount(){return this.map.size}tileAt(e,t,n){return this.map.get(`${e},${t},${n}`)}setBlocks(e){this.map.clear();for(let t of e)this.map.set(`${t.x},${t.y},${t.z}`,t.tile);this.dirty=!0,this.emit(`blocksChanged`)}addBlock(e){this.map.set(`${e.x},${e.y},${e.z}`,e.tile),this.dirty=!0,this.emit(`blocksChanged`)}removeBlockAt(e,t,n){let r=this.map.delete(`${e},${t},${n}`);return r&&(this.dirty=!0,this.emit(`blocksChanged`)),r}blocks(){let e=[];for(let[t,n]of this.map){let[r,i,a]=t.split(`,`).map(Number);e.push({x:r,y:i,z:a,tile:n})}return e}_createObject3D(){let e=new Rs(1,1,1),t=new ec({vertexShader:Dk,fragmentShader:Ok});this.mesh=new rs(e,t,wk),this.mesh.count=0,this.mesh.frustumCulled=!1;for(let e of Ek)this.mesh.geometry.setAttribute(e,new Yo(new Float32Array(wk*3),3));return this.dirty=!0,this.mesh}update(){if(this.voxels.length>0&&this.voxels!==this.appliedVoxels&&(this.appliedVoxels=this.voxels,this.setBlocks(this.voxels.map(e=>({x:e[0]??0,y:e[1]??0,z:e[2]??0,tile:e[3]??0})))),!this.dirty||!this.mesh)return;this.dirty=!1;let e=new W,t=0;for(let[n,r]of this.map){if(t>=wk)break;let[i,a,o]=n.split(`,`).map(Number);e.setPosition(i,a,o),this.mesh.setMatrixAt(t,e);let s=Ck[r]??Ck[0];for(let e=0;e<6;e++){let n=this.mesh.geometry.getAttribute(Ek[e]),r=s[e];n.setXYZ(t,r[0],r[1],r[2]),n.needsUpdate=!0}t++}this.mesh.count=t,this.mesh.instanceMatrix.needsUpdate=!0}},Ek=[`colorFront`,`colorRight`,`colorBack`,`colorLeft`,`colorTop`,`colorBottom`],Dk=`
|
|
7707
7803
|
attribute vec3 colorFront;
|
|
7708
7804
|
attribute vec3 colorRight;
|
|
7709
7805
|
attribute vec3 colorBack;
|
|
@@ -7724,7 +7820,7 @@ void main() {
|
|
|
7724
7820
|
if (abs(n.x) > 0.5) vUv2 = p.zy; else if (abs(n.y) > 0.5) vUv2 = p.xz; else vUv2 = p.xy;
|
|
7725
7821
|
gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
|
|
7726
7822
|
}
|
|
7727
|
-
`,
|
|
7823
|
+
`,Ok=`
|
|
7728
7824
|
varying vec3 vColor;
|
|
7729
7825
|
varying vec3 vNormal;
|
|
7730
7826
|
varying vec2 vUv2;
|
|
@@ -7735,13 +7831,13 @@ void main() {
|
|
|
7735
7831
|
if (vUv2.x < edge || vUv2.x > 1.0 - edge || vUv2.y < edge || vUv2.y > 1.0 - edge) color *= 0.75;
|
|
7736
7832
|
gl_FragColor = vec4(color, 1.0);
|
|
7737
7833
|
}
|
|
7738
|
-
`;function
|
|
7834
|
+
`;function kk(){ct(),M(qp),M(UE),M(hE),M(DE),M(qS),M(JS),M(tC),M(GC),M(Tk),M(Bx),M(YD),M(nC),M(lC),M(yE),M(GD),M(yS),M(Pm),M($p),M(tE),M(Hw),M(ak),M(BE),M(TC),M(TE),M(EE),M(Yp),M(Zp),M(Xp),M(Qp)}var Ak={slowMs:20,fastMs:13,minScale:.6,step:.15,window:45},jk=class{opts;samples=[];scale=1;constructor(e={}){this.opts={...Ak,...e}}current(){return this.scale}push(e){if(!(e>0)||!Number.isFinite(e)||(this.samples.push(e),this.samples.length<this.opts.window))return null;let t=[...this.samples].sort((e,t)=>e-t),n=t[Math.floor(t.length/2)];this.samples=[];let r=this.scale;return n>this.opts.slowMs?this.scale=Math.max(this.opts.minScale,this.scale-this.opts.step):n<this.opts.fastMs&&this.scale<1&&(this.scale=Math.min(1,this.scale+this.opts.step)),this.scale===r?null:this.scale}reset(){this.samples=[]}},Mk=`
|
|
7739
7835
|
varying vec2 vUv;
|
|
7740
7836
|
void main() {
|
|
7741
7837
|
vUv = uv;
|
|
7742
7838
|
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
7743
7839
|
}
|
|
7744
|
-
`,
|
|
7840
|
+
`,Nk=`
|
|
7745
7841
|
precision highp float;
|
|
7746
7842
|
varying vec2 vUv;
|
|
7747
7843
|
uniform sampler2D tScene;
|
|
@@ -7755,7 +7851,7 @@ void main() {
|
|
|
7755
7851
|
float k = max(l - uThreshold, 0.0);
|
|
7756
7852
|
gl_FragColor = vec4(c * (k / max(l, 1e-4)), 1.0);
|
|
7757
7853
|
}
|
|
7758
|
-
`,
|
|
7854
|
+
`,Pk=`
|
|
7759
7855
|
precision highp float;
|
|
7760
7856
|
varying vec2 vUv;
|
|
7761
7857
|
uniform sampler2D tTex;
|
|
@@ -7769,7 +7865,7 @@ void main() {
|
|
|
7769
7865
|
sum += texture2D(tTex, vUv - uDir * 3.2308) * 0.0702703;
|
|
7770
7866
|
gl_FragColor = sum;
|
|
7771
7867
|
}
|
|
7772
|
-
`,
|
|
7868
|
+
`,Fk=`
|
|
7773
7869
|
precision highp float;
|
|
7774
7870
|
varying vec2 vUv;
|
|
7775
7871
|
uniform sampler2D tScene;
|
|
@@ -7799,13 +7895,13 @@ void main() {
|
|
|
7799
7895
|
gl_FragColor.rgb = max(graded, 0.0);
|
|
7800
7896
|
#include <colorspace_fragment>
|
|
7801
7897
|
}
|
|
7802
|
-
`;function
|
|
7898
|
+
`;function Ik(e,t){let n=new ec({vertexShader:Mk,fragmentShader:e,depthTest:!1,depthWrite:!1,uniforms:t}),r=new jo(new Ws(2,2),n);return r.frustumCulled=!1,r}function Lk(){let e=Ik(Nk,{tScene:{value:null},uThreshold:{value:1}});return{mesh:e,uniforms:e.material.uniforms}}function Rk(){let e=Ik(Pk,{tTex:{value:null},uDir:{value:new B}});return{mesh:e,uniforms:e.material.uniforms}}function zk(){let e=Ik(Fk,{tScene:{value:null},tBloom:{value:null},uStrength:{value:.85},uVignette:{value:0},uSaturation:{value:1},uContrast:{value:1}});return{mesh:e,uniforms:e.material.uniforms}}var Bk=`
|
|
7803
7899
|
varying vec2 vUv;
|
|
7804
7900
|
void main() {
|
|
7805
7901
|
vUv = uv;
|
|
7806
7902
|
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
7807
7903
|
}
|
|
7808
|
-
`,
|
|
7904
|
+
`,Vk=`
|
|
7809
7905
|
precision highp float;
|
|
7810
7906
|
varying vec2 vUv;
|
|
7811
7907
|
uniform sampler2D tDepth;
|
|
@@ -7967,7 +8063,7 @@ void main() {
|
|
|
7967
8063
|
// a separate full-res pass (this raymarch runs at HALF res for performance)
|
|
7968
8064
|
gl_FragColor = vec4(accum, alpha);
|
|
7969
8065
|
}
|
|
7970
|
-
`,
|
|
8066
|
+
`,Hk=`
|
|
7971
8067
|
precision highp float;
|
|
7972
8068
|
varying vec2 vUv;
|
|
7973
8069
|
uniform sampler2D tTex;
|
|
@@ -7985,7 +8081,7 @@ void main() {
|
|
|
7985
8081
|
c += texture2D(tTex, vUv - uDir * 4.0) * 0.015;
|
|
7986
8082
|
gl_FragColor = c;
|
|
7987
8083
|
}
|
|
7988
|
-
`,
|
|
8084
|
+
`,Uk=`
|
|
7989
8085
|
precision highp float;
|
|
7990
8086
|
varying vec2 vUv;
|
|
7991
8087
|
uniform sampler2D tScene;
|
|
@@ -7995,11 +8091,11 @@ void main() {
|
|
|
7995
8091
|
vec4 cloud = texture2D(tClouds, vUv); // already separable-blurred + premultiplied
|
|
7996
8092
|
gl_FragColor = vec4(scene.rgb * (1.0 - cloud.a) + cloud.rgb, 1.0);
|
|
7997
8093
|
}
|
|
7998
|
-
`;function
|
|
8094
|
+
`;function Wk(){let e=new ec({vertexShader:Bk,fragmentShader:Hk,depthTest:!1,depthWrite:!1,uniforms:{tTex:{value:null},uDir:{value:new B}}}),t=new jo(new Ws(2,2),e);return t.frustumCulled=!1,{mesh:t,uniforms:e.uniforms}}function Gk(){let e=new ec({vertexShader:Bk,fragmentShader:Vk,depthTest:!1,depthWrite:!1,uniforms:{tDepth:{value:null},uInvViewProj:{value:new W},uCameraPos:{value:new H},uTime:{value:0},uSunDir:{value:new H(0,1,0)},uSunColor:{value:new G(`#fff3da`)},uCloudColor:{value:new G(`#ffffff`)},uShadeColor:{value:new G(`#9fb0c8`)},uHorizonColor:{value:new G(`#cdd9e6`)},uBase:{value:120},uTop:{value:320},uCoverage:{value:.5},uDensity:{value:1},uScale:{value:240},uWind:{value:new B(1,.3)},uFarFade:{value:6e3}}}),t=new jo(new Ws(2,2),e);return t.frustumCulled=!1,{mesh:t,uniforms:e.uniforms}}function Kk(){let e=new ec({vertexShader:Bk,fragmentShader:Uk,depthTest:!1,depthWrite:!1,uniforms:{tScene:{value:null},tClouds:{value:null}}}),t=new jo(new Ws(2,2),e);return t.frustumCulled=!1,{mesh:t,uniforms:e.uniforms}}var qk=class extends Fc{constructor(e){super(e),this.type=Qt}parse(e){let t=function(e,t){switch(e){case 1:throw Error(`THREE.HDRLoader: Read Error: `+(t||``));case 2:throw Error(`THREE.HDRLoader: Write Error: `+(t||``));case 3:throw Error(`THREE.HDRLoader: Bad File Format: `+(t||``));default:case 4:throw Error(`THREE.HDRLoader: Memory Error: `+(t||``))}},n=function(e,t,n){t||=1024;let r=e.pos,i=-1,a=0,o=``,s=String.fromCharCode.apply(null,new Uint16Array(e.subarray(r,r+128)));for(;0>(i=s.indexOf(`
|
|
7999
8095
|
`))&&a<t&&r<e.byteLength;)o+=s,a+=s.length,r+=128,s=String.fromCharCode.apply(null,new Uint16Array(e.subarray(r,r+128)));return-1<i?(!1!==n&&(e.pos+=a+i+1),o+s.slice(0,i)):!1},r=function(e){let r=/^#\?(\S+)/,i=/^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,a=/^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,o=/^\s*FORMAT=(\S+)\s*$/,s=/^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,c={valid:0,string:``,comments:``,programtype:`RGBE`,format:``,gamma:1,exposure:1,width:0,height:0},l,u;for((e.pos>=e.byteLength||!(l=n(e)))&&t(1,`no header found`),(u=l.match(r))||t(3,`bad initial token`),c.valid|=1,c.programtype=u[1],c.string+=l+`
|
|
8000
8096
|
`;l=n(e),!1!==l;){if(c.string+=l+`
|
|
8001
8097
|
`,l.charAt(0)===`#`){c.comments+=l+`
|
|
8002
|
-
`;continue}if((u=l.match(i))&&(c.gamma=parseFloat(u[1])),(u=l.match(a))&&(c.exposure=parseFloat(u[1])),(u=l.match(o))&&(c.valid|=2,c.format=u[1]),(u=l.match(s))&&(c.valid|=4,c.height=parseInt(u[1],10),c.width=parseInt(u[2],10)),c.valid&2&&c.valid&4)break}return c.valid&2||t(3,`missing format specifier`),c.valid&4||t(3,`missing image size specifier`),c},i=function(e,n,r){let i=n;if(i<8||i>32767||e[0]!==2||e[1]!==2||e[2]&128)return new Uint8Array(e);i!==(e[2]<<8|e[3])&&t(3,`wrong scanline width`);let a=new Uint8Array(4*n*r);a.length||t(4,`unable to allocate buffer space`);let o=0,s=0,c=4*i,l=new Uint8Array(4),u=new Uint8Array(c),d=r;for(;d>0&&s<e.byteLength;){s+4>e.byteLength&&t(1),l[0]=e[s++],l[1]=e[s++],l[2]=e[s++],l[3]=e[s++],(l[0]!=2||l[1]!=2||(l[2]<<8|l[3])!=i)&&t(3,`bad rgbe scanline format`);let n=0,r;for(;n<c&&s<e.byteLength;){r=e[s++];let i=r>128;if(i&&(r-=128),(r===0||n+r>c)&&t(3,`bad scanline data`),i){let t=e[s++];for(let e=0;e<r;e++)u[n++]=t}else u.set(e.subarray(s,s+r),n),n+=r,s+=r}let f=i;for(let e=0;e<f;e++){let t=0;a[o]=u[e+t],t+=i,a[o+1]=u[e+t],t+=i,a[o+2]=u[e+t],t+=i,a[o+3]=u[e+t],o+=4}d--}return a},a=function(e,t,n,r){let i=2**(e[t+3]-128)/255;n[r+0]=e[t+0]*i,n[r+1]=e[t+1]*i,n[r+2]=e[t+2]*i,n[r+3]=1},o=function(e,t,n,r){let i=2**(e[t+3]-128)/255;n[r+0]=Va.toHalfFloat(Math.min(e[t+0]*i,65504)),n[r+1]=Va.toHalfFloat(Math.min(e[t+1]*i,65504)),n[r+2]=Va.toHalfFloat(Math.min(e[t+2]*i,65504)),n[r+3]=Va.toHalfFloat(1)},s=new Uint8Array(e);s.pos=0;let c=r(s),l=c.width,u=c.height,d=i(s.subarray(s.pos),l,u),f,p,m;switch(this.type){case Zt:m=d.length/4;let e=new Float32Array(m*4);for(let t=0;t<m;t++)a(d,t*4,e,t*4);f=e,p=Zt;break;case Qt:m=d.length/4;let t=new Uint16Array(m*4);for(let e=0;e<m;e++)o(d,e*4,t,e*4);f=t,p=Qt;break;default:throw Error(`THREE.HDRLoader: Unsupported type: `+this.type)}return{width:l,height:u,data:f,header:c.string,gamma:c.gamma,exposure:c.exposure,type:p}}setDataType(e){return this.type=e,this}load(e,t,n,r){function i(e,n){switch(e.type){case Zt:case Qt:e.colorSpace=fr,e.minFilter=Ht,e.magFilter=Ht,e.generateMipmaps=!1,e.flipY=!0;break}t&&t(e,n)}return super.load(e,i,n,r)}},
|
|
8098
|
+
`;continue}if((u=l.match(i))&&(c.gamma=parseFloat(u[1])),(u=l.match(a))&&(c.exposure=parseFloat(u[1])),(u=l.match(o))&&(c.valid|=2,c.format=u[1]),(u=l.match(s))&&(c.valid|=4,c.height=parseInt(u[1],10),c.width=parseInt(u[2],10)),c.valid&2&&c.valid&4)break}return c.valid&2||t(3,`missing format specifier`),c.valid&4||t(3,`missing image size specifier`),c},i=function(e,n,r){let i=n;if(i<8||i>32767||e[0]!==2||e[1]!==2||e[2]&128)return new Uint8Array(e);i!==(e[2]<<8|e[3])&&t(3,`wrong scanline width`);let a=new Uint8Array(4*n*r);a.length||t(4,`unable to allocate buffer space`);let o=0,s=0,c=4*i,l=new Uint8Array(4),u=new Uint8Array(c),d=r;for(;d>0&&s<e.byteLength;){s+4>e.byteLength&&t(1),l[0]=e[s++],l[1]=e[s++],l[2]=e[s++],l[3]=e[s++],(l[0]!=2||l[1]!=2||(l[2]<<8|l[3])!=i)&&t(3,`bad rgbe scanline format`);let n=0,r;for(;n<c&&s<e.byteLength;){r=e[s++];let i=r>128;if(i&&(r-=128),(r===0||n+r>c)&&t(3,`bad scanline data`),i){let t=e[s++];for(let e=0;e<r;e++)u[n++]=t}else u.set(e.subarray(s,s+r),n),n+=r,s+=r}let f=i;for(let e=0;e<f;e++){let t=0;a[o]=u[e+t],t+=i,a[o+1]=u[e+t],t+=i,a[o+2]=u[e+t],t+=i,a[o+3]=u[e+t],o+=4}d--}return a},a=function(e,t,n,r){let i=2**(e[t+3]-128)/255;n[r+0]=e[t+0]*i,n[r+1]=e[t+1]*i,n[r+2]=e[t+2]*i,n[r+3]=1},o=function(e,t,n,r){let i=2**(e[t+3]-128)/255;n[r+0]=Va.toHalfFloat(Math.min(e[t+0]*i,65504)),n[r+1]=Va.toHalfFloat(Math.min(e[t+1]*i,65504)),n[r+2]=Va.toHalfFloat(Math.min(e[t+2]*i,65504)),n[r+3]=Va.toHalfFloat(1)},s=new Uint8Array(e);s.pos=0;let c=r(s),l=c.width,u=c.height,d=i(s.subarray(s.pos),l,u),f,p,m;switch(this.type){case Zt:m=d.length/4;let e=new Float32Array(m*4);for(let t=0;t<m;t++)a(d,t*4,e,t*4);f=e,p=Zt;break;case Qt:m=d.length/4;let t=new Uint16Array(m*4);for(let e=0;e<m;e++)o(d,e*4,t,e*4);f=t,p=Qt;break;default:throw Error(`THREE.HDRLoader: Unsupported type: `+this.type)}return{width:l,height:u,data:f,header:c.string,gamma:c.gamma,exposure:c.exposure,type:p}}setDataType(e){return this.type=e,this}load(e,t,n,r){function i(e,n){switch(e.type){case Zt:case Qt:e.colorSpace=fr,e.minFilter=Ht,e.magFilter=Ht,e.generateMipmaps=!1,e.flipY=!0;break}t&&t(e,n)}return super.load(e,i,n,r)}},Jk=class extends qk{constructor(e){console.warn(`RGBELoader has been deprecated. Please use HDRLoader instead.`),super(e)}},Yk=class e extends jo{constructor(){let t=e.SkyShader,n=new ec({name:t.name,uniforms:Zs.clone(t.uniforms),vertexShader:t.vertexShader,fragmentShader:t.fragmentShader,side:1,depthWrite:!1});super(new Rs(1,1,1),n),this.isSky=!0}};Yk.SkyShader={name:`SkyShader`,uniforms:{turbidity:{value:2},rayleigh:{value:1},mieCoefficient:{value:.005},mieDirectionalG:{value:.8},sunPosition:{value:new H},up:{value:new H(0,1,0)},cloudScale:{value:2e-4},cloudSpeed:{value:1e-4},cloudCoverage:{value:.4},cloudDensity:{value:.4},cloudElevation:{value:.5},showSunDisc:{value:1},time:{value:0}},vertexShader:`
|
|
8003
8099
|
uniform vec3 sunPosition;
|
|
8004
8100
|
uniform float rayleigh;
|
|
8005
8101
|
uniform float turbidity;
|
|
@@ -8219,9 +8315,9 @@ void main() {
|
|
|
8219
8315
|
#include <tonemapping_fragment>
|
|
8220
8316
|
#include <colorspace_fragment>
|
|
8221
8317
|
|
|
8222
|
-
}`};var Sk=[`type`,`sunPosition`,`elevationDeg`,`azimuthDeg`,`turbidity`,`rayleigh`],Ck=[`color`,`near`,`far`],wk=[`coverage`,`density`,`base`,`top`,`color`,`shadeColor`,`speed`,`scale`],Tk=[`threshold`,`strength`],Ek=[`vignette`,`saturation`,`contrast`],Dk=[`mapSize`,`radius`,`static`],Ok=[1024,2048],kk=2,Ak=1,jk=50,Mk=800,Nk=`#cfd8e0`,Pk=Math.PI/180;function Fk(e){return{exposure:zk(e?.exposure),sky:Bk(e?.sky),fog:Vk(e?.fog,e?.sky!==void 0),clouds:Hk(e?.clouds),bloom:Uk(e?.bloom),post:Wk(e?.post),shadows:Gk(e?.shadows)}}function Ik(e,t){let n=(90-e)*Pk,r=t*Pk;return[Math.sin(n)*Math.sin(r),Math.cos(n),Math.sin(n)*Math.cos(r)]}function Lk(e){let[t,n,r]=e.sunPosition,i=Math.hypot(t,n,r)||1;return[t/i,n/i,r/i]}function Rk(e){let t=[191,213,232],n=[233,228,217],r=[242,201,150],i=Jk((e.turbidity-kk)/8),a=Lk(e),o=Jk((18-Math.asin(qk(a[1],-1,1))/Pk)/18)*.8,s=e=>Math.round(Yk(Yk(t[e],n[e],i),r[e],o));return`#${[s(0),s(1),s(2)].map(e=>e.toString(16).padStart(2,`0`)).join(``)}`}function zk(e){if(e===void 0)return 1;if(typeof e!=`number`||!Number.isFinite(e)||e<=0)throw new y(`BAD_FORMAT`,`environment.exposure must be a finite number > 0 (tone-mapping exposure, default 1), got ${JSON.stringify(e)}.`,{prop:`exposure`});return e}function Bk(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.sky must be an object ({ type?: "atmosphere", sunPosition? | elevationDeg?+azimuthDeg?, turbidity?, rayleigh? }), got ${JSON.stringify(e)}.`,{prop:`sky`});let t=e;for(let e of Object.keys(t))if(!Sk.includes(e))throw new y(`BAD_FORMAT`,`environment.sky has unknown key '${e}'. Valid keys: [${Sk.join(`, `)}].`,{prop:`sky`,validOptions:Sk});if(t.type!==void 0&&t.type!==`atmosphere`)throw new y(`BAD_FORMAT`,`environment.sky.type must be 'atmosphere' (the only sky type so far), got ${JSON.stringify(t.type)}.`,{prop:`sky`,validOptions:[`atmosphere`]});let n=t.elevationDeg!==void 0||t.azimuthDeg!==void 0;if(t.sunPosition!==void 0&&n)throw new y(`BAD_FORMAT`,`environment.sky takes sunPosition OR elevationDeg/azimuthDeg, not both.`,{prop:`sky`,validOptions:[`sunPosition`,`elevationDeg+azimuthDeg`]});let r;if(t.sunPosition!==void 0){let e=t.sunPosition;if(!Array.isArray(e)||e.length!==3||!e.every(e=>typeof e==`number`&&Number.isFinite(e))||Math.hypot(e[0],e[1],e[2])===0)throw new y(`BAD_FORMAT`,`environment.sky.sunPosition must be a non-zero [x, y, z] vector, got ${JSON.stringify(e)}.`,{prop:`sky`});r=[e[0],e[1],e[2]]}else{let e=Kk(t.elevationDeg,32,`sky.elevationDeg`),n=Kk(t.azimuthDeg,135,`sky.azimuthDeg`);if(e<-90||e>90)throw new y(`BAD_FORMAT`,`environment.sky.elevationDeg must be in [-90, 90] (degrees above the horizon), got ${e}.`,{prop:`sky`});r=Ik(e,n)}let i=Kk(t.turbidity,kk,`sky.turbidity`);if(i<=0)throw new y(`BAD_FORMAT`,`environment.sky.turbidity must be > 0 (atmospheric haze; 2 ≈ clear day), got ${i}.`,{prop:`sky`});let a=Kk(t.rayleigh,Ak,`sky.rayleigh`);if(a<0)throw new y(`BAD_FORMAT`,`environment.sky.rayleigh must be >= 0 (Rayleigh scattering; 1 ≈ earth-like), got ${a}.`,{prop:`sky`});return{sunPosition:r,turbidity:i,rayleigh:a}}function Vk(e,t){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.fog must be an object ({ color?, near?, far? }), got ${JSON.stringify(e)}.`,{prop:`fog`});let n=e;for(let e of Object.keys(n))if(!Ck.includes(e))throw new y(`BAD_FORMAT`,`environment.fog has unknown key '${e}'. Valid keys: [${Ck.join(`, `)}].`,{prop:`fog`,validOptions:Ck});if(n.color!==void 0&&typeof n.color!=`string`)throw new y(`BAD_FORMAT`,`environment.fog.color must be a hex color string, got ${JSON.stringify(n.color)}.`,{prop:`fog`});let r=Kk(n.near,jk,`fog.near`),i=Kk(n.far,Mk,`fog.far`);if(r<0)throw new y(`BAD_FORMAT`,`environment.fog.near must be >= 0 meters, got ${r}.`,{prop:`fog`});if(i<=r)throw new y(`BAD_FORMAT`,`environment.fog.far must be > near (got near ${r}, far ${i}).`,{prop:`fog`});return{color:n.color??(t?``:Nk),near:r,far:i}}function Hk(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.clouds must be an object ({ coverage?, density?, base?, top?, color?, shadeColor?, speed?, scale? }), got ${JSON.stringify(e)}.`,{prop:`clouds`});let t=e;for(let e of Object.keys(t))if(!wk.includes(e))throw new y(`BAD_FORMAT`,`environment.clouds has unknown key '${e}'. Valid keys: [${wk.join(`, `)}].`,{prop:`clouds`,validOptions:wk});for(let e of[`color`,`shadeColor`])if(t[e]!==void 0&&typeof t[e]!=`string`)throw new y(`BAD_FORMAT`,`environment.clouds.${e} must be a hex color string, got ${JSON.stringify(t[e])}.`,{prop:`clouds`});let n=Kk(t.coverage,.5,`clouds.coverage`);if(n<0||n>1)throw new y(`BAD_FORMAT`,`environment.clouds.coverage must be in [0, 1] (how much sky is cloudy), got ${n}.`,{prop:`clouds`});let r=Kk(t.density,1,`clouds.density`);if(r<0)throw new y(`BAD_FORMAT`,`environment.clouds.density must be >= 0 (optical thickness), got ${r}.`,{prop:`clouds`});let i=Kk(t.base,120,`clouds.base`),a=Kk(t.top,320,`clouds.top`);if(a<=i)throw new y(`BAD_FORMAT`,`environment.clouds.top must be > base (got base ${i}, top ${a}).`,{prop:`clouds`});let o=Kk(t.speed,1,`clouds.speed`),s=Kk(t.scale,240,`clouds.scale`);if(s<=0)throw new y(`BAD_FORMAT`,`environment.clouds.scale must be > 0 (feature size in world units), got ${s}.`,{prop:`clouds`});return{coverage:n,density:r,base:i,top:a,color:t.color??`#ffffff`,shadeColor:t.shadeColor??`#9fb0c8`,speed:o,scale:s}}function Uk(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.bloom must be an object ({ threshold?, strength? }), got ${JSON.stringify(e)}.`,{prop:`bloom`});let t=e;for(let e of Object.keys(t))if(!Tk.includes(e))throw new y(`BAD_FORMAT`,`environment.bloom has unknown key '${e}'. Valid keys: [${Tk.join(`, `)}].`,{prop:`bloom`,validOptions:Tk});let n=Kk(t.threshold,1,`bloom.threshold`);if(n<0||n>8)throw new y(`BAD_FORMAT`,`environment.bloom.threshold must be in [0, 8] (linear-HDR luminance; 1 = white), got ${n}.`,{prop:`bloom`});let r=Kk(t.strength,.8,`bloom.strength`);if(r<0)throw new y(`BAD_FORMAT`,`environment.bloom.strength must be >= 0, got ${r}.`,{prop:`bloom`});return{threshold:n,strength:r}}function Wk(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.post must be an object ({ vignette?, saturation?, contrast? }), got ${JSON.stringify(e)}.`,{prop:`post`});let t=e;for(let e of Object.keys(t))if(!Ek.includes(e))throw new y(`BAD_FORMAT`,`environment.post has unknown key '${e}'. Valid keys: [${Ek.join(`, `)}].`,{prop:`post`,validOptions:Ek});let n=Kk(t.vignette,0,`post.vignette`);if(n<0||n>1)throw new y(`BAD_FORMAT`,`environment.post.vignette must be in [0, 1], got ${n}.`,{prop:`post`});let r=Kk(t.saturation,1,`post.saturation`);if(r<0||r>4)throw new y(`BAD_FORMAT`,`environment.post.saturation must be in [0, 4] (1 = neutral), got ${r}.`,{prop:`post`});let i=Kk(t.contrast,1,`post.contrast`);if(i<.2||i>3)throw new y(`BAD_FORMAT`,`environment.post.contrast must be in [0.2, 3] (1 = neutral), got ${i}.`,{prop:`post`});return{vignette:n,saturation:r,contrast:i}}function Gk(e){if(e===void 0)return null;if(e===!1)return!1;if(e===!0)return{mapSize:2048,radius:1,static:!1};if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.shadows must be true, false or an object ({ mapSize?, radius? }), got ${JSON.stringify(e)}.`,{prop:`shadows`});let t=e;for(let e of Object.keys(t))if(!Dk.includes(e))throw new y(`BAD_FORMAT`,`environment.shadows has unknown key '${e}'. Valid keys: [${Dk.join(`, `)}].`,{prop:`shadows`,validOptions:Dk});let n=t.mapSize===void 0?2048:t.mapSize;if(!Ok.includes(n))throw new y(`BAD_FORMAT`,`environment.shadows.mapSize must be one of [${Ok.join(`, `)}], got ${JSON.stringify(t.mapSize)}.`,{prop:`shadows`,validOptions:Ok.map(String)});let r=Kk(t.radius,1,`shadows.radius`);if(r<0)throw new y(`BAD_FORMAT`,`environment.shadows.radius must be >= 0, got ${r}.`,{prop:`shadows`});let i=t.static===void 0?!1:t.static;if(typeof i!=`boolean`)throw new y(`BAD_FORMAT`,`environment.shadows.static must be a boolean, got ${JSON.stringify(t.static)}.`,{prop:`shadows`});return{mapSize:n,radius:r,static:i}}function Kk(e,t,n){if(e===void 0)return t;if(typeof e!=`number`||!Number.isFinite(e))throw new y(`BAD_FORMAT`,`environment.${n} must be a finite number, got ${JSON.stringify(e)}.`,{prop:n});return e}function qk(e,t,n){return Math.min(Math.max(e,t),n)}function Jk(e){return qk(e,0,1)}function Yk(e,t,n){return e+(t-e)*n}var Xk=`https://agent8-games.verse8.io/assets/3D/default/textures/hdri`,Zk={apartment:`lebombo_1k.hdr`,city:`potsdamer_platz_1k.hdr`,dawn:`kiara_1_dawn_1k.hdr`,forest:`forest_slope_1k.hdr`,lobby:`st_fagans_interior_1k.hdr`,night:`dikhololo_night_1k.hdr`,park:`rooitou_park_1k.hdr`,studio:`studio_small_03_1k.hdr`,sunset:`venice_sunset_1k.hdr`,warehouse:`empty_warehouse_01_1k.hdr`};function Qk(e){if(typeof e.hdri==`string`&&e.hdri!==``)return e.hdri;if(typeof e.preset==`string`){let t=Zk[e.preset];if(!t)throw Error(`Unknown environment preset '${e.preset}'. Available: ${Object.keys(Zk).join(`, `)}.`);return`${Xk}/${t}`}return null}var $k=75,eA=class{scene;ambient=new rl(`#ffffff`,0);envKey=null;config=Fk(void 0);hdriUrl=null;hdriTexture=null;_sky=null;skyKey=``;skyEnvKey=``;skyEnvTarget=null;fog=new oa(`#ffffff`,1,1e3);underwaterFog=null;underwaterBg=new G;constructor(e){this.scene=e,this.scene.add(this.ambient)}get sunDirection(){return this.config.sky?Lk(this.config.sky):null}get clouds(){return this.config.clouds}get bloom(){return this.config.bloom}get post(){return this.config.post}get sceneFog(){return this.scene.fog instanceof oa?this.scene.fog:null}apply(e,t){let n=e===void 0?``:JSON.stringify(e);n!==this.envKey&&(this.envKey=n,this.config=Fk(e));let r=this.config,i=e?.ambient;if(this.ambient.color.set(i?.color??`#ffffff`),this.ambient.intensity=i?.intensity??0,t&&(t.toneMappingExposure=r.exposure,t.shadowMap.enabled=r.shadows!==!1,r.shadows!==!1&&r.shadows!==null&&r.shadows.static?t.shadowMap.autoUpdate&&(t.shadowMap.autoUpdate=!1,t.shadowMap.needsUpdate=!0):t.shadowMap.autoUpdate||(t.shadowMap.autoUpdate=!0)),this.applyHdri(e),this.applySky(r.sky,t),this._sky&&(this._sky.visible=!0),this.applyFog(r),this.scene.environment=this.hdriTexture??this.skyEnvTarget?.texture??null,this.scene.environmentIntensity=(this.scene.environment===this.skyEnvTarget?.texture&&this.skyEnvTarget?.55:1)*tA(e?.iblIntensity),e?.skybox===!0&&this.hdriTexture)this.scene.background=this.hdriTexture;else{let t=e?.background;this.scene.background=typeof t==`string`?new G(t):null}}applySunLight(e,t=null){if(!e)return;let n=this.sunDirection;if(t){let r=e.position.length()||100,i,a,o;if(n)[i,a,o]=n;else{i=e.position.x-e.target.position.x,a=e.position.y-e.target.position.y,o=e.position.z-e.target.position.z;let t=Math.hypot(i,a,o)||1;i/=t,a/=t,o/=t}e.target.position.set(t.x,t.y,t.z),e.target.updateMatrixWorld(),e.position.set(t.x+i*r,t.y+a*r,t.z+o*r)}else if(n){let t=e.position.length()||100;e.position.set(n[0],n[1],n[2]).multiplyScalar(t)}let r=this.config.shadows;if(r&&typeof r==`object`){if(!e.castShadow){let t=e.shadow.camera;`left`in t&&t.left===-5&&(t.left=-75,t.right=$k,t.top=$k,t.bottom=-75,t.near=.5,t.far=500,t.updateProjectionMatrix()),e.castShadow=!0}e.shadow.mapSize.x!==r.mapSize&&(e.shadow.mapSize.set(r.mapSize,r.mapSize),e.shadow.map?.dispose(),e.shadow.map=null),e.shadow.radius=r.radius}}applyUnderwater(e){e&&(this.underwaterFog||=new oa(`#000000`,.5,e.visibility),this.underwaterFog.color.set(e.color),this.underwaterFog.near=.5,this.underwaterFog.far=e.visibility,this.scene.fog=this.underwaterFog,this.scene.background=this.underwaterBg.set(e.color),this._sky&&(this._sky.visible=!1))}applyHdri(e){let t=Qk(e??{});t!==this.hdriUrl&&(this.hdriUrl=t,this.hdriTexture?.dispose(),this.hdriTexture=null,t&&new bk().load(t,e=>{if(this.hdriUrl!==t){e.dispose();return}e.mapping=303,this.hdriTexture=e}))}applySky(e,t){let n=e?JSON.stringify(e):``;if(n!==this.skyKey&&(this.skyKey=n,this._sky&&=(this.scene.remove(this._sky),this._sky.material.dispose(),this._sky.geometry.dispose(),null),e)){this._sky=new xk,this._sky.scale.setScalar(45e4);let t=this._sky.material.uniforms;(t.sunPosition?.value).set(...e.sunPosition),t.turbidity&&(t.turbidity.value=e.turbidity),t.rayleigh&&(t.rayleigh.value=e.rayleigh),this.scene.add(this._sky)}if(e&&t&&this._sky&&this.skyEnvKey!==n){this.skyEnvKey=n,this.skyEnvTarget?.dispose();let e=new ru(t),r=new sa;r.add(this._sky),this.skyEnvTarget=e.fromScene(r),e.dispose(),this.scene.add(this._sky)}!e&&this.skyEnvTarget&&(this.skyEnvTarget.dispose(),this.skyEnvTarget=null,this.skyEnvKey=``)}applyFog(e){if(!e.fog){this.scene.fog=null;return}let t=e.fog.color||(e.sky?Rk(e.sky):`#cfd8e0`);this.fog.color.set(t),this.fog.near=e.fog.near,this.fog.far=e.fog.far,this.scene.fog=this.fog}dispose(){this.hdriTexture?.dispose(),this.hdriTexture=null,this.skyEnvTarget?.dispose(),this.skyEnvTarget=null,this._sky&&=(this.scene.remove(this._sky),this._sky.material.dispose(),this._sky.geometry.dispose(),null)}};function tA(e){if(e===void 0)return 1;if(typeof e!=`number`||!Number.isFinite(e)||e<0)throw new y(`BAD_FORMAT`,`environment.iblIntensity must be a finite number >= 0 (multiplies the image-based ambience: sky-derived base 0.55, HDRI base 1; default 1), got ${JSON.stringify(e)}.`,{prop:`iblIntensity`});return e}var nA=new Sa,rA=new H,iA=.4,aA=new Float32Array(72);function oA(e){if(!(e instanceof qp))return null;let t=e._ensureObject3D();if(t.updateWorldMatrix(!0,!0),nA.setFromObject(t),nA.getSize(rA),!Number.isFinite(rA.x)||rA.x===0&&rA.y===0&&rA.z===0){let e=new H().setFromMatrixPosition(t.matrixWorld);nA.min.set(e.x-iA,e.y-iA,e.z-iA),nA.max.set(e.x+iA,e.y+iA,e.z+iA)}else nA.expandByScalar(.02);let{min:n,max:r}=nA,i=0,a=(e,t,n,r,a,o)=>{aA[i++]=e,aA[i++]=t,aA[i++]=n,aA[i++]=r,aA[i++]=a,aA[i++]=o};return a(n.x,n.y,n.z,r.x,n.y,n.z),a(r.x,n.y,n.z,r.x,n.y,r.z),a(r.x,n.y,r.z,n.x,n.y,r.z),a(n.x,n.y,r.z,n.x,n.y,n.z),a(n.x,r.y,n.z,r.x,r.y,n.z),a(r.x,r.y,n.z,r.x,r.y,r.z),a(r.x,r.y,r.z,n.x,r.y,r.z),a(n.x,r.y,r.z,n.x,r.y,n.z),a(n.x,n.y,n.z,n.x,r.y,n.z),a(r.x,n.y,n.z,r.x,r.y,n.z),a(r.x,n.y,r.z,r.x,r.y,r.z),a(n.x,n.y,r.z,n.x,r.y,r.z),aA}function sA(e){return e.spatial===!0&&typeof e._setSpatialPose==`function`}function cA(){let e=new Set,t=[],n=[],r=[];return{visited:e,cameras:t,renderHooks:n,emitters:r,state:{visited:e,cameras:t,renderHooks:n,emitters:r,assets:void 0,sunDirection:null,sunLight:null,alpha:1,ignoreStatic:!1}}}function lA(e,t,n,r,i){let a=i??cA();a.visited.clear(),a.cameras.length=0,a.renderHooks.length=0,a.emitters.length=0;let o=a.state;o.assets=n,o.sunDirection=r?.sunDirection??null,o.ignoreStatic=r?.ignoreStatic===!0,o.sunLight=null,o.alpha=r?.alpha??1,hA(e,t,o),vA(t,a.visited);let s=null;for(let e=0;e<a.cameras.length;e++){let t=a.cameras[e];if(t.current){s=t;break}}s||=a.cameras[0]??null;let c=s?s._ensureObject3D():null;return mA(a.emitters,c),{activeCamera:c,renderHooks:a.renderHooks,sunLight:o.sunLight}}var uA=new H,dA=new H,fA=new H,pA=new H;function mA(e,t){if(e.length===0||!t)return;t.updateWorldMatrix(!0,!1),t.getWorldPosition(dA),t.getWorldDirection(fA),pA.set(0,1,0).applyQuaternion(t.quaternion);let n={position:[dA.x,dA.y,dA.z],forward:[fA.x,fA.y,fA.z],up:[pA.x,pA.y,pA.z]};for(let{node:t,parent:r}of e)r.updateWorldMatrix(!0,!1),r.getWorldPosition(uA),t._setSpatialPose({position:[uA.x,uA.y,uA.z],listener:n})}function hA(e,t,n){let r=t;if(e instanceof qp){let i=e._ensureObject3D();if(e.static&&!n.ignoreStatic&&i.userData.incantoStaticSynced===!0){i.userData.incantoStatic=!0,n.visited.add(i);return}if(i.parent!==t&&t.add(i),e._syncObject3D(n.alpha),n.assets&&e instanceof AE&&e._syncModel(n.assets),typeof e._onRender3D==`function`&&n.renderHooks.push(e),n.sunDirection){let t=e._applySunDirection;typeof t==`function`&&t.call(e,n.sunDirection)}e instanceof hE&&(!n.sunLight||e.intensity>n.sunLight.intensity)&&(n.sunLight=e),n.visited.add(i),e instanceof hC&&n.cameras.push(e),r=i}else sA(e)&&n.emitters.push({node:e,parent:r});for(let t of e.children)hA(t,r,n);if(e instanceof qp){let t=e._ensureObject3D();e.static&&!n.ignoreStatic?(t.userData.incantoStaticSynced=!0,t.userData.incantoStatic=!0,_A(e)):t.userData.incantoStaticSynced===!0&&(t.userData.incantoStaticSynced=!1,t.userData.incantoStatic=!1)}}var gA=new WeakSet;function _A(e){if(gA.has(e))return;gA.add(e);let t=[],n=e=>{(typeof e._onRender3D==`function`||e instanceof hC)&&t.push(`${e.name} (${e.constructor.typeName??`?`})`);for(let t of e.children)n(t)};n(e),t.length>0&&console.warn(`[incanto] static subtree '${e.name}' freezes animated/per-frame nodes: ${t.join(`, `)} — they will stop updating. Unmark static or move them out.`)}function vA(e,t){let n=e.children;for(let r=n.length-1;r>=0;r--){let i=n[r];i.userData.incantoNode&&!t.has(i)?e.remove(i):i.userData.incantoStatic!==!0&&vA(i,t)}}var yA=class{viewOverride=null;overrideCam=new Yc(60,1,.05,5e3);lastCamera=null;lastSize={w:1,h:1};webgl;threeScene=new sa;environment=new eA(this.threeScene);engine;disconnect;canvas;assets;ownsAssets;loadedAssetScenes=new WeakSet;compiledScene=null;syncScratch=cA();ignoreStatic=!1;renderCtx=null;causticsTarget=null;causticsScene=null;causticsUniforms=null;cloudsTarget=null;cloudsHalfTarget=null;cloudsBlurTarget=null;cloudsScene=null;cloudsUniforms=null;cloudsBlurScene=null;cloudsBlurUniforms=null;cloudsCompositeScene=null;cloudsCompositeUniforms=null;bloomTarget=null;bloomBrightTarget=null;bloomBlurTarget=null;bloomBrightScene=null;bloomBrightUniforms=null;bloomBlurScene=null;bloomBlurUniforms=null;bloomCompositeScene=null;bloomCompositeUniforms=null;constructor(e){this.canvas=e.canvas,this.engine=e.engine,this.ownsAssets=!e.assets,this.assets=e.assets??new Sx;let t=lt(e.engine.scene?.environment,{antialias:!0,pixelRatio:Math.min(globalThis.devicePixelRatio??1,2)},globalThis.devicePixelRatio??1,{pixelRatio:e.pixelRatio});this.webgl=new Zf({canvas:e.canvas,antialias:t.antialias}),this.basePixelRatio=t.pixelRatio,this.webgl.setPixelRatio(t.pixelRatio),this.adaptive=e.adaptiveResolution===!1?null:new rk,this.webgl.shadowMap.enabled=!0,this.webgl.shadowMap.type=1,this.webgl.toneMapping=4,this.webgl.toneMappingExposure=1,this.debugLines=new ws(new q,new fs({color:`#00ff6e`,depthTest:!1})),this.debugLines.frustumCulled=!1,this.debugLines.renderOrder=9999,this.debugLines.visible=!1,this.threeScene.add(this.debugLines),this.selectionLines=new ws(new q,new fs({color:`#ffb020`,transparent:!0,depthTest:!1})),this.selectionLines.frustumCulled=!1,this.selectionLines.renderOrder=1e4,this.selectionLines.visible=!1,this.threeScene.add(this.selectionLines),this.disconnect=this.engine.updated.connect(()=>this.render())}basePixelRatio;adaptive;lastFrameAt=0;debugLines;selectionLines;syncSelectionOutline(){let e=this.engine.debugSelection;e&&e.tree!==this.engine.scene?.tree&&(this.engine.debugSelection=null);let t=this.engine.debugSelection,n=t?oA(t):null;if(this.selectionLines.visible=n!==null,n){this.selectionLines.geometry.setAttribute(`position`,new K(n,3));let e=this.selectionLines.geometry.getAttribute(`position`);e.needsUpdate=!0}}syncDebugLines(){let e=null;for(let t of fh(`3d`))if(e=t.debugLines(),e)break;this.debugLines.visible=e!==null,e&&this.debugLines.geometry.setAttribute(`position`,new K(e,3))}governResolution(){let e=this.adaptive;if(!e)return;let t=globalThis.performance?.now?.()??0,n=this.lastFrameAt;if(this.lastFrameAt=t,n===0)return;let r=t-n;if(r>500){e.reset();return}let i=e.push(r);if(i===null)return;this.webgl.setPixelRatio(this.basePixelRatio*i);let a=this.lastSize;a.w>0&&a.h>0&&this.webgl.setSize(a.w,a.h,!1)}render(){let e=this.engine.scene;if(!e)return;this.governResolution(),this.syncDebugLines(),this.syncSelectionOutline(),e.assets&&!this.loadedAssetScenes.has(e)&&(this.assets.load(e.assets),this.loadedAssetScenes.add(e)),this.environment.apply(e.environment,this.webgl);let{activeCamera:t,renderHooks:n,sunLight:r}=lA(e.root,this.threeScene,this.assets,{sunDirection:this.environment.sunDirection,alpha:this.engine.interpolationAlpha,ignoreStatic:this.ignoreStatic},this.syncScratch),i=t;if(this.viewOverride){let[e,t,n]=this.viewOverride.position,[r,a,o]=this.viewOverride.target;this.overrideCam.position.set(e,t,n),this.overrideCam.lookAt(xA.set(r,a,o)),i=this.overrideCam}if(!i)return;this.lastCamera=i,i.updateWorldMatrix(!0,!1);let a=i.getWorldPosition(EA),o=r?r._ensureObject3D():null,s=!!o&&r.shadowFollowsCamera===!0;this.environment.applySunLight(o,s?a:null),this.compiledScene!==e&&(this.compiledScene=e,this.webgl.compile(this.threeScene,i));let c=this.canvas.clientWidth||this.canvas.width,l=this.canvas.clientHeight||this.canvas.height,u=this.webgl.getSize(bA);(u.x!==c||u.y!==l)&&this.webgl.setSize(c,l,!1),this.lastSize={w:c,h:l};let d=l===0?1:c/l;i.aspect!==d&&(i.aspect=d,i.updateProjectionMatrix()),this.renderCtx||={gl:this.webgl,scene:this.threeScene,camera:i};let f=this.renderCtx;f.camera=i,o?(o.updateWorldMatrix(!0,!1),o.target.updateWorldMatrix(!0,!1),f.sunDir=CA.setFromMatrixPosition(o.matrixWorld).sub(wA.setFromMatrixPosition(o.target.matrixWorld)).normalize()):f.sunDir=null;for(let e=0;e<n.length;e++)n[e]?._onRender3D(f);let p=null;for(let e=0;e<n.length;e++){let t=n[e].underwaterAt?.(a.x,a.y,a.z);if(t){p=t;break}}this.environment.applyUnderwater(p);let m=this.environment.clouds,h=this.environment.bloom,g=this.environment.post;p?.caustics.enabled?this.renderWithCaustics(i,p):m&&!p?this.renderWithClouds(i,m,o):(h||g)&&!p?this.renderWithBloom(i,h,g):this.webgl.render(this.threeScene,i)}renderWithBloom(e,t,n=null){let r=this.webgl.getDrawingBufferSize(bA),i=Math.max(1,r.x),a=Math.max(1,r.y),o=Math.max(1,Math.ceil(i/2)),s=Math.max(1,Math.ceil(a/2));if(this.bloomTarget&&(this.bloomTarget.width!==i||this.bloomTarget.height!==a)&&(this.bloomTarget.dispose(),this.bloomTarget=null,this.bloomBrightTarget?.dispose(),this.bloomBrightTarget=null,this.bloomBlurTarget?.dispose(),this.bloomBlurTarget=null),this.bloomTarget||(this.bloomTarget=new Si(i,a,{type:Qt}),this.bloomBrightTarget=new Si(o,s,{type:Qt}),this.bloomBlurTarget=new Si(o,s,{type:Qt})),!this.bloomBrightScene){let e=lk();this.bloomBrightScene=new sa,this.bloomBrightScene.add(e.mesh),this.bloomBrightUniforms=e.uniforms;let t=uk();this.bloomBlurScene=new sa,this.bloomBlurScene.add(t.mesh),this.bloomBlurUniforms=t.uniforms;let n=dk();this.bloomCompositeScene=new sa,this.bloomCompositeScene.add(n.mesh),this.bloomCompositeUniforms=n.uniforms}let c=this.bloomBrightTarget,l=this.bloomBlurTarget;if(this.webgl.setRenderTarget(this.bloomTarget),this.webgl.render(this.threeScene,e),t){let n=this.bloomBrightUniforms;n.tScene.value=this.bloomTarget.texture,n.uThreshold.value=t.threshold,this.webgl.setRenderTarget(c),this.webgl.render(this.bloomBrightScene,e);let r=this.bloomBlurUniforms;r.tTex.value=c.texture,r.uDir.value.set(1/o,0),this.webgl.setRenderTarget(l),this.webgl.render(this.bloomBlurScene,e),r.tTex.value=l.texture,r.uDir.value.set(0,1/s),this.webgl.setRenderTarget(c),this.webgl.render(this.bloomBlurScene,e)}let u=this.bloomCompositeUniforms;u.tScene.value=this.bloomTarget.texture,u.tBloom.value=t?c.texture:this.bloomTarget.texture,u.uStrength.value=t?t.strength:0,u.uVignette.value=n?.vignette??0,u.uSaturation.value=n?.saturation??1,u.uContrast.value=n?.contrast??1,this.webgl.setRenderTarget(null),this.webgl.render(this.bloomCompositeScene,e)}renderWithClouds(e,t,n){let r=this.webgl.getDrawingBufferSize(bA),i=Math.max(1,r.x),a=Math.max(1,r.y),o=Math.max(1,Math.ceil(i/3)),s=Math.max(1,Math.ceil(a/3));if(this.cloudsTarget&&(this.cloudsTarget.width!==i||this.cloudsTarget.height!==a)&&(this.cloudsTarget.depthTexture?.dispose(),this.cloudsTarget.dispose(),this.cloudsTarget=null,this.cloudsHalfTarget?.dispose(),this.cloudsHalfTarget=null,this.cloudsBlurTarget?.dispose(),this.cloudsBlurTarget=null),!this.cloudsTarget){let e=new Fs(i,a);e.type=Zt,this.cloudsTarget=new Si(i,a,{depthTexture:e,depthBuffer:!0})}if(this.cloudsHalfTarget||(this.cloudsHalfTarget=new Si(o,s,{depthBuffer:!1}),this.cloudsBlurTarget=new Si(o,s,{depthBuffer:!1})),!this.cloudsScene){let{mesh:e,uniforms:t}=_k();this.cloudsScene=new sa,this.cloudsScene.add(e),this.cloudsUniforms=t}if(!this.cloudsBlurScene){let{mesh:e,uniforms:t}=gk();this.cloudsBlurScene=new sa,this.cloudsBlurScene.add(e),this.cloudsBlurUniforms=t}if(!this.cloudsCompositeScene){let{mesh:e,uniforms:t}=vk();this.cloudsCompositeScene=new sa,this.cloudsCompositeScene.add(e),this.cloudsCompositeUniforms=t}this.webgl.setRenderTarget(this.cloudsTarget),this.webgl.render(this.threeScene,e);let c=this.cloudsUniforms;c.tDepth.value=this.cloudsTarget.depthTexture,c.uInvViewProj.value.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse).invert(),e.getWorldPosition(c.uCameraPos.value),c.uTime.value=(globalThis.performance?.now()??0)*.001*t.speed;let l=this.environment.sunDirection??[.4,.8,.3];c.uSunDir.value.set(l[0],l[1],l[2]).normalize(),n&&c.uSunColor.value.copy(n.color),c.uCloudColor.value.set(t.color),c.uShadeColor.value.set(t.shadeColor);let u=this.environment.sceneFog;u?(c.uHorizonColor.value.copy(u.color),c.uFarFade.value=u.far):(c.uHorizonColor.value.set(`#cdd9e6`),c.uFarFade.value=6e3),c.uBase.value=t.base,c.uTop.value=t.top,c.uCoverage.value=t.coverage,c.uDensity.value=t.density,c.uScale.value=t.scale,c.uWind.value.set(1,.35),this.webgl.setRenderTarget(this.cloudsHalfTarget),this.webgl.render(this.cloudsScene,e);let d=this.cloudsBlurUniforms,f=this.cloudsBlurScene;d.tTex.value=this.cloudsHalfTarget.texture,d.uDir.value.set(1/o,0),this.webgl.setRenderTarget(this.cloudsBlurTarget),this.webgl.render(f,e),d.tTex.value=this.cloudsBlurTarget.texture,d.uDir.value.set(0,1/s),this.webgl.setRenderTarget(this.cloudsHalfTarget),this.webgl.render(f,e),this.webgl.setRenderTarget(null);let p=this.cloudsCompositeUniforms;p.tScene.value=this.cloudsTarget.texture,p.tClouds.value=this.cloudsHalfTarget.texture,this.webgl.render(this.cloudsCompositeScene,e)}renderWithCaustics(e,t){let n=this.webgl.getDrawingBufferSize(bA),r=Math.max(1,n.x),i=Math.max(1,n.y);if(this.causticsTarget&&(this.causticsTarget.width!==r||this.causticsTarget.height!==i)&&(this.causticsTarget.depthTexture?.dispose(),this.causticsTarget.dispose(),this.causticsTarget=null),!this.causticsTarget){let e=new Fs(r,i);e.type=Zt,this.causticsTarget=new Si(r,i,{depthTexture:e,depthBuffer:!0})}if(!this.causticsScene){let{mesh:e,uniforms:t}=yp();this.causticsScene=new sa,this.causticsScene.add(e),this.causticsUniforms=t}this.webgl.setRenderTarget(this.causticsTarget),this.webgl.render(this.threeScene,e),this.webgl.setRenderTarget(null);let a=this.causticsUniforms;a.tColor.value=this.causticsTarget.texture,a.tDepth.value=this.causticsTarget.depthTexture,a.uInvViewProj.value.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse).invert(),e.getWorldPosition(a.uCameraPos.value),a.uWaterLevel.value=t.surfaceY,a.uTime.value=(globalThis.performance?.now()??0)*.001*t.caustics.speed,a.uCausticColor.value.set(t.caustics.color),a.uCausticIntensity.value=t.caustics.intensity,a.uCausticScale.value=t.caustics.scale,a.uMaxDist.value=t.visibility;let o=this.environment.sunDirection;o&&a.uSunDirection.value.set(o[0],o[1],o[2]),a.uRayStrength.value=t.rays.enabled?t.rays.strength:0,this.webgl.render(this.causticsScene,e)}screenFromWorld(e,t,n){let r=this.lastCamera;return r?(SA.set(e,t,n).project(r),{x:(SA.x+1)/2*this.lastSize.w,y:(1-SA.y)/2*this.lastSize.h,behind:SA.z>1}):{x:0,y:0,behind:!0}}pick(e,t){let n=this.lastCamera;if(!n)return null;OA.set(e/this.lastSize.w*2-1,-(t/this.lastSize.h*2-1)),DA.setFromCamera(OA,n);let r=DA.intersectObjects(this.threeScene.children,!0);for(let e of r){let t=e.object;for(;t&&!t.userData.incantoNode;)t=t.parent;let n=t?.userData.incantoNode;if(n)return n}return null}stats(){let e=this.webgl.info;return{triangles:e.render.triangles,drawCalls:e.render.calls,geometries:e.memory.geometries,textures:e.memory.textures}}cameraBasis(){let e=this.lastCamera,t=e?e.getWorldQuaternion(TA):TA.identity();return{right:new H(1,0,0).applyQuaternion(t),up:new H(0,1,0).applyQuaternion(t),forward:new H(0,0,-1).applyQuaternion(t)}}refreshShadows(){this.webgl.shadowMap.needsUpdate=!0}dispose(){this.disconnect(),this.threeScene.traverse(e=>{let t=e;if(!(!t.isMesh||t.userData?.incantoModelShared))if(t.geometry?.dispose(),Array.isArray(t.material))for(let e of t.material)e.dispose();else t.material?.dispose()}),this.causticsTarget?.depthTexture?.dispose(),this.causticsTarget?.dispose();let e=this.causticsScene?.children[0];e?.geometry?.dispose(),e?.material?.dispose(),this.cloudsTarget?.depthTexture?.dispose(),this.cloudsTarget?.dispose(),this.cloudsHalfTarget?.dispose(),this.cloudsBlurTarget?.dispose(),this.bloomTarget?.dispose(),this.bloomBrightTarget?.dispose(),this.bloomBlurTarget?.dispose();for(let e of[this.cloudsScene,this.cloudsBlurScene,this.cloudsCompositeScene,this.bloomBrightScene,this.bloomBlurScene,this.bloomCompositeScene]){let t=e?.children[0];t?.geometry?.dispose(),t?.material?.dispose()}this.ownsAssets&&this.assets.dispose(),this.environment.dispose(),this.webgl.dispose()}},bA=new B,xA=new H,SA=new H,CA=new H,wA=new H,TA=new V,EA=new H,DA=new kl,OA=new B,kA=e({DEFAULT_TERRAIN_TEXTURE_BASE:()=>Yx,WATER_MAX_RIPPLES:()=>8,enablePhysics3D:()=>mS}),AA=new WeakMap,jA=class e{account;roomId;roomState=new t;allUserStates=new t;userJoined=new t;userLeft=new t;globalState=new t;globalMyState=new t;asset=new t;latestUserStates={};latestRoomState={};latestGlobalState={};latestGlobalMyState={};latestAsset={};server;engine;throttleMs;subs=[];messageSignals=new Map;collectionSignals=new Map;latestCollections=new Map;globalMessageSignals=new Map;globalCollectionSignals=new Map;latestGlobalCollections=new Map;scenes=new Map;lastSent=new Map;sendAccumulator=0;detachReplication=null;lastOwner=null;boundScene=null;static get(e){return AA.get(e)??null}static async create(t,n={}){await AA.get(t)?.dispose();let r=n.transport??await IA(n.config);await r.connect();let i=n.room??t.scene?.multiplayer?.room??`auto`,a=new e(t,r,await r.remoteFunction(`joinRoom`,[i===`auto`?void 0:i],{needResponse:!0}),n.throttleMs??50);return AA.set(t,a),a}constructor(e,t,n,r){this.engine=e,this.server=t,this.roomId=n,this.account=t.account,this.throttleMs=Math.max(30,r),this.boundScene=e.scene,this.subs.push(t.subscribeRoomState(n,e=>{this.latestRoomState=e,this.roomState.emit(e)}),t.subscribeRoomAllUserStates(n,e=>{this.latestUserStates=e,this.allUserStates.emit(e)}),t.onRoomUserJoin(n,e=>this.userJoined.emit(e)),t.onRoomUserLeave(n,e=>this.userLeft.emit(e))),t.subscribeGlobalState&&this.subs.push(t.subscribeGlobalState(e=>{this.latestGlobalState=e,this.globalState.emit(e)})),t.subscribeGlobalMyState&&this.subs.push(t.subscribeGlobalMyState(e=>{this.latestGlobalMyState=e,this.globalMyState.emit(e)})),t.subscribeAsset&&this.subs.push(t.subscribeAsset(this.account,e=>{this.latestAsset=e,this.asset.emit(e)})),this.detachReplication=e.fixedUpdated.connect(e=>this.replicate(e))}message(e){let n=this.messageSignals.get(e);return n||(n=new t,this.messageSignals.set(e,n),this.subs.push(this.server.onRoomMessage(this.roomId,e,e=>n?.emit(e)))),n}collection(e){let n=this.collectionSignals.get(e);return n||(n=new t,this.collectionSignals.set(e,n),this.subs.push(this.server.subscribeRoomCollection(this.roomId,e,t=>{this.latestCollections.set(e,t),n?.emit(t)}))),n}latestCollection(e){return this.collection(e),this.latestCollections.get(e)??{}}globalMessage(e){let n=this.globalMessageSignals.get(e);if(!n){n=new t,this.globalMessageSignals.set(e,n);let r=this.server.onGlobalMessage?.(e,e=>n?.emit(e));r&&this.subs.push(r)}return n}globalCollection(e){let n=this.globalCollectionSignals.get(e);if(!n){n=new t,this.globalCollectionSignals.set(e,n);let r=this.server.subscribeGlobalCollection?.(e,t=>{this.latestGlobalCollections.set(e,t),n?.emit(t)});r&&this.subs.push(r)}return n}latestGlobalCollection(e){return this.globalCollection(e),this.latestGlobalCollections.get(e)??{}}setMyState(e){return this.server.remoteFunction(`setMyState`,[this.roomId,e],{throttle:this.throttleMs,throttleKey:`incanto:myState`})}patchRoomState(e){return this.server.remoteFunction(`patchRoomState`,[this.roomId,e])}addEntity(e,t){return this.server.remoteFunction(`addEntity`,[this.roomId,e,t])}updateEntity(e,t,n){return this.server.remoteFunction(`updateEntity`,[this.roomId,e,t,n])}removeEntity(e,t){return this.server.remoteFunction(`removeEntity`,[this.roomId,e,t])}sendEvent(e,t){return this.server.remoteFunction(`sendEvent`,[this.roomId,e,t])}call(e,...t){return this.server.remoteFunction(e,[this.roomId,...t],{needResponse:!0})}registerScene(e,t){this.scenes.set(e,t)}resolveScene(e){let t=this.scenes.get(e);if(!t)throw new y(`UNRESOLVED_INSTANCE`,`No scene registered for '${e}'. Registered: [${[...this.scenes.keys()].join(`, `)}]. Call manager.registerScene('${e}', sceneJson).`);return t}async dispose(){this.detachReplication?.();for(let e of this.subs)e();await this.server.remoteFunction(`leaveRoom`,[this.roomId]),AA.delete(this.engine)}replicate(e){let t=this.engine.scene;if(!t||t!==this.boundScene)return;this.sendAccumulator+=e*1e3;let n=MA(t.root,!0);if(!n)return;n!==this.lastOwner&&(this.lastOwner=n,this.lastSent.clear());let r=n.network,i=Math.max(30,typeof r.throttleMs==`number`?r.throttleMs:this.throttleMs),a=Array.isArray(r.sync)?r.sync:[],o={};for(let e of a){let t=PA(n,e);t!==void 0&&(de(this.lastSent.get(e)??null,t)||(o[e]=j(t)))}if(!(this.sendAccumulator<i)&&Object.keys(o).length!==0){for(let[e,t]of Object.entries(o))this.lastSent.set(e,j(t));this.sendAccumulator=0,this.setMyState({sync:o})}}};function MA(e,t=!1){let n=[];if(NA(e,n),t&&n.length>1)throw new y(`BAD_FORMAT`,`Multiple network owner nodes found (${n.map(e=>e.getPath()).join(`, `)}). Exactly ONE node per player may declare network.mode 'owner' — replicate spawned entities through collections instead.`);return n[0]??null}function NA(e,t){e.network?.mode===`owner`&&t.push(e);for(let n of e.children)NA(n,t)}function PA(e,t){let n=t.lastIndexOf(`.`),r=n===-1?e:e.getNodeOrNull(t.slice(0,n))??void 0,i=n===-1?t:t.slice(n+1);if(r)return r[i]}function FA(e,t,n){for(let[r,i]of Object.entries(t)){let t=r.lastIndexOf(`.`),a=t===-1?e:e.getNodeOrNull(r.slice(0,t)),o=t===-1?r:r.slice(t+1);a&&n(a,o,i)}}async function IA(e){let{createAgent8Server:t}=await _h(async()=>{let{createAgent8Server:e}=await import(`./agent8-DzaYTNiK.js`);return{createAgent8Server:e}},[],import.meta.url);return t(e)}var LA=class extends Pe{static typeName=`NetworkSpawner`;static signals=[`spawned`,`despawned`];static props={source:{default:`users`},scene:{default:``},interpolate:{default:!0}};source=`users`;scene=``;interpolate=!0;spawned=new Map;positionTargets=new Map;failedKeys=new Set;update(e){let t=this.tree?.engine;if(!t)return;let n=jA.get(t);if(!n||this.scene===``)return;let r=this.currentEntries(n);for(let[e,t]of Object.entries(r)){let r=this.spawned.get(e);if(!r){if(this.failedKeys.has(e))continue;try{r=St(n.resolveScene(this.scene).root)}catch(t){throw this.failedKeys.add(e),t}r.name=RA(e),this.addChild(r),this.spawned.set(e,r),this.emit(`spawned`,r,e)}let i=t.sync;i&&FA(r,i,(e,t,n)=>this.setProp(e,t,n))}for(let[e,t]of[...this.spawned.entries()])e in r||(this.spawned.delete(e),this.positionTargets.delete(t),this.emit(`despawned`,t,e),t.free());this.interpolate&&this.stepInterpolation(e)}currentEntries(e){if(this.source===`users`){let t={};for(let[n,r]of Object.entries(e.latestUserStates))n!==e.account&&(t[n]=r);return t}return this.source.startsWith(`collection:`)?e.latestCollection(this.source.slice(11)):{}}setProp(e,t,n){if(this.interpolate&&t===`position`&&Array.isArray(n)){this.positionTargets.set(e,n);return}e[t]=n}stepInterpolation(e){let t=Math.min(1,e*8);for(let[e,n]of this.positionTargets){let r=e.position;Array.isArray(r)&&(e.position=r.map((e,r)=>e+((n[r]??e)-e)*t))}}};function RA(e){return e.replace(/[/%]/g,`_`)||`remote`}function zA(){ct(),M(LA)}var BA=80,VA=` `;function HA(e){return`${UA(e,0)}\n`}function UA(e,t){if(typeof e!=`object`||!e)return JSON.stringify(e);let n=WA(e);if(t*2+n.length<=BA)return n;let r=VA.repeat(t+1),i=VA.repeat(t);if(Array.isArray(e))return e.length===0?`[]`:`[\n${e.map(e=>r+UA(e,t+1)).join(`,
|
|
8223
|
-
`)}\n${i}]`;let a=Object.entries(e);return a.length===0?`{}`:`{\n${a.map(([e,n])=>`${r}${JSON.stringify(e)}: ${
|
|
8224
|
-
`)}\n${i}}`}function WA(e){if(typeof e!=`object`||!e)return JSON.stringify(e);if(Array.isArray(e))return e.length===0?`[]`:`[${e.map(WA).join(`, `)}]`;let t=Object.entries(e);return t.length===0?`{}`:`{ ${t.map(([e,t])=>`${JSON.stringify(e)}: ${WA(t)}`).join(`, `)} }`}async function GA(e){if(!e.ok)throw Error(`HTTP ${e.status} — ${await e.text()}`);return e}async function KA(){return await(await GA(await fetch(`/api/meta`))).json()}async function qA(){return await(await GA(await fetch(`/api/scenes`))).json()}async function JA(e){return await(await GA(await fetch(`/api/scenes`,{method:`POST`,body:JSON.stringify({path:e})}))).json()}function YA(e){return e?`/api/scene?file=${encodeURIComponent(e)}`:`/api/scene`}async function XA(e){return await(await GA(await fetch(YA(e)))).json()}async function ZA(e,t){await GA(await fetch(YA(t),{method:`PUT`,body:HA(e)}))}var QA=localStorage.getItem(`incanto-editor-lang`)??`en`,$A=new Set;function ej(){return QA}function tj(e){QA=e,localStorage.setItem(`incanto-editor-lang`,e);for(let e of $A)e()}function nj(e){$A.add(e)}function rj(e){return e[QA]}var ij={node:{paths:[`M5 5h14v14H5z`]},move:{paths:[`M12 3v18M3 12h18`,`M8 7l4-4 4 4M8 17l4 4 4-4M7 8l-4 4 4 4M17 8l4 4-4 4`]},image:{paths:[`M4 5h16v14H4z`,`M4 15l5-5 4 4 3-3 4 4`],circles:[[9,9,1.6]]},film:{paths:[`M4 4h16v16H4z`,`M4 9h16M4 15h16`,`M9 4v16M15 4v16`]},video:{paths:[`M3 7h12v10H3z`,`M15 10l6-3v10l-6-3`]},text:{paths:[`M5 7V5h14v2`,`M12 5v14`,`M9 19h6`]},layers:{paths:[`M12 3 3 8l9 5 9-5-9-5z`,`M3 12l9 5 9-5`,`M3 16l9 5 9-5`]},square:{paths:[`M5 5h14v14H5z`,`M5 12h14`]},ball:{paths:[`M12 8v0`],circles:[[12,12,8],[12,12,1.4]]},person:{paths:[`M5 21v-1a7 7 0 0 1 14 0v1`],circles:[[12,7,4]]},area:{paths:[`M5 5h14v14H5z`],dashed:!0},gamepad:{paths:[`M7 9h-0M6 12h4M8 10v4`,`M4 8h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2z`],circles:[[16,11,1],[18.5,13.5,1]]},clock:{paths:[`M12 7v5l3 2`],circles:[[12,12,9]]},cube:{paths:[`M21 16V8l-9-5-9 5v8l9 5 9-5z`,`M3.3 7.5 12 12.5l8.7-5`,`M12 22V12.5`]},sun:{paths:[`M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9 17 7M7 17l-2.1 2.1`],circles:[[12,12,4]]},bulb:{paths:[`M9 18h6M10 21h4`,`M8 13a6 6 0 1 1 8 0c-1 1-1.5 2-1.5 3h-5c0-1-.5-2-1.5-3z`]},globe:{paths:[`M2 12h20`,`M12 2a15 15 0 0 1 0 20a15 15 0 0 1 0-20z`],circles:[[12,12,10]]},link:{paths:[`M10 14a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1`,`M14 10a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1`]},speaker:{paths:[`M11 5 6 9H3v6h3l5 4V5z`,`M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13`]},swatch:{paths:[`M4 4h16v16H4z`,`M4 4l16 16`]},sparkles:{paths:[`M12 4v5M12 15v5M5 12h5M14 12h5`],circles:[[6,5,1],[18,19,1]]},waves:{paths:[`M2 8c3-3 5 3 8 0s5 3 8 0`,`M2 14c3-3 5 3 8 0s5 3 8 0`,`M2 20c3-3 5 3 8 0s5 3 8 0`]},plant:{paths:[`M12 21v-8`,`M12 13c0-4-3-6-7-6 0 4 3 6 7 6z`,`M12 11c0-4 3-6 7-6 0 4-3 6-7 6z`]},flower:{paths:[`M12 21v-7`],circles:[[12,9,2],[12,4.5,2.2],[16.3,7.5,2.2],[14.7,12.6,2.2],[9.3,12.6,2.2],[7.7,7.5,2.2]]},voxels:{paths:[`M4 14h8v8H4z`,`M12 14h8v8h-8z`,`M8 6h8v8H8z`]}},aj={Node:`node`,Timer:`clock`,AudioPlayer:`speaker`,ColorRect2D:`swatch`,Particles2D:`sparkles`,Particles3D:`sparkles`,Water3D:`waves`,Foliage3D:`plant`,Flowers3D:`flower`,VoxelGrid3D:`voxels`,ModelInstance3D:`person`,CharacterController3D:`gamepad`,Node2D:`move`,Sprite2D:`image`,AnimatedSprite2D:`film`,Camera2D:`video`,Label:`text`,UILayer:`layers`,StaticBody2D:`square`,RigidBody2D:`ball`,CharacterBody2D:`person`,Area2D:`area`,CharacterController2D:`gamepad`,Node3D:`move`,Billboard3D:`layers`,MeshInstance3D:`cube`,LoftMesh3D:`cube`,Camera3D:`video`,DirectionalLight3D:`sun`,OmniLight3D:`bulb`,StaticBody3D:`square`,RigidBody3D:`ball`,CharacterBody3D:`person`,Area3D:`area`,NetworkSpawner:`globe`};function oj(e){let t=ij[aj[e??``]??(e?`node`:`link`)],n=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);n.setAttribute(`viewBox`,`0 0 24 24`),n.setAttribute(`width`,`13`),n.setAttribute(`height`,`13`),n.setAttribute(`fill`,`none`),n.setAttribute(`stroke`,`currentColor`),n.setAttribute(`stroke-width`,`2`),n.setAttribute(`stroke-linecap`,`round`),n.setAttribute(`stroke-linejoin`,`round`),t.dashed&&n.setAttribute(`stroke-dasharray`,`3 2.4`);for(let e of t.paths){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);t.setAttribute(`d`,e),n.appendChild(t)}for(let[e,r,i]of t.circles??[]){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`circle`);t.setAttribute(`cx`,String(e)),t.setAttribute(`cy`,String(r)),t.setAttribute(`r`,String(i)),n.appendChild(t)}return n}function sj(){let e=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);e.setAttribute(`viewBox`,`0 0 24 24`),e.setAttribute(`width`,`12`),e.setAttribute(`height`,`12`),e.setAttribute(`fill`,`none`),e.setAttribute(`stroke`,`currentColor`),e.setAttribute(`stroke-width`,`2.4`),e.setAttribute(`aria-hidden`,`true`);let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);return t.setAttribute(`d`,`m6 9 6 6 6-6`),e.appendChild(t),e}var cj=[{type:`texture`,label:`image (texture)`,metaHints:[`filter`]},{type:`spritesheet`,label:`spritesheet`,metaHints:[`filter`,`frameWidth`,`frameHeight`]},{type:`model`,label:`3D model (GLB/VRM)`,metaHints:[]},{type:`animation`,label:`animation (GLB clips)`,metaHints:[`clip`]}],lj=new Set,uj=null,dj=null;function fj(e,t,n){let r=document.createElement(`input`);r.className=`rename-input`,r.value=e;let i=()=>{let i=r.value.trim().replace(/\//g,``);i&&i!==e?t(i):n()};r.addEventListener(`keydown`,e=>{e.stopPropagation(),e.key===`/`&&e.preventDefault(),e.key===`Enter`&&i(),e.key===`Escape`&&n()});for(let e of[`click`,`pointerdown`,`dblclick`,`mousedown`])r.addEventListener(e,e=>e.stopPropagation());return r.addEventListener(`blur`,i),queueMicrotask(()=>{r.focus(),r.select()}),r}function pj(e,t){let n={path:``,name:``,folders:new Map,assets:[]},r=e=>{let t=n;if(e===``)return t;for(let n of e.split(`/`)){let e=t.folders.get(n);e||(e={path:t.path?`${t.path}/${n}`:n,name:n,folders:new Map,assets:[]},t.folders.set(n,e)),t=e}return t};for(let t of e){let e=t.lastIndexOf(`/`);r(e===-1?``:t.slice(0,e)).assets.push(t)}for(let e of t)r(e);return n}function mj(e){let t=e.assets.length;for(let n of e.folders.values())t+=mj(n);return t}function hj(e,t){e.textContent=``;let n=t.working.assets??{},r=Object.keys(n);if(r.length===0&&t.pendingGroups.size===0&&!t.addingAsset&&!t.addingGroup){let t=document.createElement(`div`);t.className=`muted-note explorer-empty`,t.textContent=`no assets yet — + adds textures, models, animations`,e.appendChild(t);return}let i=(e,n)=>{e.addEventListener(`dragover`,t=>{t.preventDefault(),t.stopPropagation(),e.classList.add(`drop-target`)}),e.addEventListener(`dragleave`,()=>e.classList.remove(`drop-target`)),e.addEventListener(`drop`,r=>{r.preventDefault(),r.stopPropagation(),e.classList.remove(`drop-target`);let i=r.dataTransfer?.getData(`text/incanto-asset`);i&&t.moveAsset(i,n);let a=r.dataTransfer?.getData(`text/incanto-group`);a&&t.moveGroup(a,n)})};i(e,``);let a=(e,r)=>{let i=n[e],a=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,o=document.createElement(`div`);o.className=`tree-row asset-row${t.selectedAsset===e?` selected`:``}`,o.draggable=!0,o.addEventListener(`dragstart`,t=>{t.dataTransfer?.setData(`text/incanto-asset`,e)});let s=document.createElement(`span`);if(s.className=`tree-icon`,s.appendChild(Dj(i.type??``)),s.addEventListener(`click`,e=>{e.stopPropagation(),Oj(s,i.type??``)}),uj===e){let n=e.includes(`/`)?e.slice(0,e.lastIndexOf(`/`)+1):``;o.appendChild(fj(a,r=>{uj=null,t.renameAssetKey(e,n+r)},()=>{uj=null,t.selectAsset(t.selectedAsset)})),o.draggable=!1,o.insertBefore(s,o.firstChild),r.appendChild(o);return}let c=document.createElement(`span`);c.className=`tree-name asset-key`,c.textContent=`$${a}`,c.title=`$${e}`,c.addEventListener(`dblclick`,n=>{n.stopPropagation(),uj=e,t.selectAsset(e)}),o.append(s,c),o.addEventListener(`click`,()=>t.selectAsset(e)),r.appendChild(o)},o=(e,n)=>{let r=lj.has(e.path),s=document.createElement(`div`);s.className=`asset-folder${r?` collapsed`:``}${t.selectedGroup===e.path?` selected`:``}`,s.draggable=!0,s.addEventListener(`dragstart`,t=>{t.stopPropagation(),t.dataTransfer?.setData(`text/incanto-group`,e.path)});let c=document.createElement(`span`);c.className=`chev`,c.appendChild(sj());let l=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);l.setAttribute(`viewBox`,`0 0 24 24`),l.setAttribute(`width`,`12`),l.setAttribute(`height`,`12`),l.setAttribute(`fill`,`none`),l.setAttribute(`stroke`,`currentColor`),l.setAttribute(`stroke-width`,`1.8`),l.setAttribute(`aria-hidden`,`true`);let u=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);if(u.setAttribute(`d`,`M3 6a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`),l.appendChild(u),dj===e.path){let i=e.path.includes(`/`)?e.path.slice(0,e.path.lastIndexOf(`/`)+1):``;if(s.append(c,l,fj(e.name,n=>{dj=null,t.renameGroup(e.path,i+n)},()=>{dj=null,t.selectGroup(t.selectedGroup)})),s.draggable=!1,n.appendChild(s),!r){let t=document.createElement(`div`);t.className=`tree-children`;for(let n of e.folders.values())o(n,t);for(let n of e.assets)a(n,t);t.children.length>0&&n.appendChild(t)}return}let d=document.createElement(`span`);d.textContent=e.name,d.addEventListener(`dblclick`,n=>{n.stopPropagation(),dj=e.path,t.selectGroup(e.path)});let f=document.createElement(`span`);if(f.className=`count`,f.textContent=`(${mj(e)})`,s.append(c,l,d,f),s.addEventListener(`click`,()=>{lj.has(e.path)?lj.delete(e.path):lj.add(e.path),t.selectGroup(e.path)}),i(s,e.path),n.appendChild(s),!r){let t=document.createElement(`div`);t.className=`tree-children`;for(let n of e.folders.values())o(n,t);for(let n of e.assets)a(n,t);t.children.length>0&&n.appendChild(t)}},s=pj(r,t.pendingGroups);for(let t of s.assets)a(t,e);for(let t of s.folders.values())o(t,e)}function gj(e,t,n){if(t.selection!==null)return!1;if(t.addingGroup){e.appendChild(Mj(t.newGroupParent?`NEW GROUP IN ${t.newGroupParent}/`:`NEW GROUP`));let n=document.createElement(`input`);n.placeholder=t.newGroupParent?`heroes`:`characters (or a/b to nest)`,n.className=`mono`,e.appendChild(Sj(`name`,n));let r=document.createElement(`button`);r.type=`button`,r.className=`primary`,r.textContent=`add`;let i=()=>{let e=n.value.trim().replace(/^\/+|\/+$/g,``);e&&(t.cancelAddForms(),t.addGroup(t.newGroupParent?`${t.newGroupParent}/${e}`:e))};r.addEventListener(`click`,i),n.addEventListener(`keydown`,e=>{e.key===`Enter`&&i()});let a=document.createElement(`div`);return a.className=`pop-actions`,a.appendChild(r),e.appendChild(a),setTimeout(()=>n.focus(),0),!0}if(t.addingAsset)return bj(e,t);if(t.selectedGroup!==null){let r=t.selectedGroup,i=t.groupCount(r);e.appendChild(Mj(`GROUP (${i} asset${i===1?``:`s`})`));let a=r.includes(`/`)?r.slice(0,r.lastIndexOf(`/`)+1):``,o=r.includes(`/`)?r.slice(r.lastIndexOf(`/`)+1):r;e.appendChild(Cj(`name`,o,e=>{let n=e.trim().replace(/\/+/g,``);n&&n!==o&&t.renameGroup(r,a+n)}));let s=document.createElement(`button`);return s.type=`button`,s.className=`ghost danger`,s.textContent=`delete group`,s.addEventListener(`click`,()=>{if(i===0){t.deleteGroup(r);return}n(`'${r}/' contains ${i} asset${i===1?``:`s`} — deleting the group deletes them too.`,`delete group & assets`,()=>t.deleteGroup(r))}),e.appendChild(s),!0}let r=t.selectedAsset;if(r===null)return!1;let i=t.working.assets??{};if(!(r in i))return!1;e.appendChild(Mj(`ASSET — ${String(i[r].type??`?`)}`)),e.appendChild(kj(r)),e.appendChild(Aj(t,r)),e.appendChild(_j(t,i,r));let a=document.createElement(`button`);return a.type=`button`,a.className=`ghost danger`,a.textContent=`delete asset`,a.addEventListener(`click`,()=>{t.selectAsset(null),t.mutate(()=>{delete i[r],Object.keys(i).length===0&&delete t.working.assets})}),e.appendChild(a),!0}function _j(e,t,n){let r=t[n],i=document.createElement(`div`);i.className=`asset-editor`;let a=n.includes(`/`)?n.slice(n.lastIndexOf(`/`)+1):n,o=n.includes(`/`)?n.slice(0,n.lastIndexOf(`/`)+1):``,s=Cj(`name`,a,t=>{let r=t.trim().replace(/^\$/,``).replace(/\//g,``);r&&r!==a&&e.renameAssetKey(n,o+r)});jj(s.querySelector(`input`)),i.appendChild(s),i.appendChild(Cj(`url`,String(r.url??``),t=>{e.mutate(()=>{r.url=t.trim()})}));let c=document.createElement(`div`);c.className=`muted-note`,c.textContent=`meta (key · value)`,i.appendChild(c);for(let[t,n]of Object.entries(r))t===`type`||t===`url`||i.appendChild(vj(e,r,t,n));return i.appendChild(yj(e,r)),i}function vj(e,t,n,r){let i=document.createElement(`div`);i.className=`meta-row`;let a=document.createElement(`input`);a.value=n,a.className=`mono`;let o=document.createElement(`input`);o.value=typeof r==`string`?r:JSON.stringify(r),o.className=`mono`;let s=()=>{let r=a.value.trim();e.mutate(()=>{delete t[n],r&&(t[r]=wj(o.value))})};a.addEventListener(`change`,s),o.addEventListener(`change`,s);let c=document.createElement(`button`);return c.type=`button`,c.className=`linklike danger-link`,c.textContent=`✕`,c.addEventListener(`click`,()=>{e.mutate(()=>{delete t[n]})}),i.append(a,o,c),i}function yj(e,t){let n=document.createElement(`div`);n.className=`meta-row`;let r=document.createElement(`input`);r.placeholder=`filter…`,r.className=`mono`;let i=document.createElement(`input`);i.placeholder=`nearest`,i.className=`mono`;let a=()=>{let n=r.value.trim();!n||i.value.trim()===``||e.mutate(()=>{t[n]=wj(i.value)})};return r.addEventListener(`change`,a),i.addEventListener(`change`,a),n.append(r,i,document.createElement(`span`)),n}function bj(e,t){return e.appendChild(Mj(`NEW ASSET`)),e.appendChild(xj(t)),!0}function xj(e){let t=document.createElement(`div`);t.className=`asset-editor`;let n=document.createElement(`select`);for(let e of cj){let t=document.createElement(`option`);t.value=e.type,t.textContent=e.label,n.appendChild(t)}t.appendChild(Sj(`type`,n));let r=document.createElement(`input`);r.placeholder=`(optional) characters`,r.className=`mono`,r.value=e.newAssetGroup;let i=`asset-groups-list`;r.setAttribute(`list`,i);let a=document.createElement(`datalist`);a.id=i;let o=new Set;for(let t of Object.keys(e.working.assets??{})){let e=t.lastIndexOf(`/`);e!==-1&&o.add(t.slice(0,e))}for(let t of e.pendingGroups)o.add(t);for(let e of o){let t=document.createElement(`option`);t.value=e,a.appendChild(t)}t.appendChild(Sj(`group`,r)),t.appendChild(a);let s=document.createElement(`input`);s.placeholder=`coin`,s.className=`mono`,jj(s),t.appendChild(Sj(`key`,s));let c=document.createElement(`input`);c.placeholder=`/textures/coin.png · https://… · data:…`,c.className=`mono`,t.appendChild(Sj(`url`,c));let l=document.createElement(`textarea`);l.rows=2,l.placeholder=`or paste a JSON object: { "type": "model", "url": "/m.glb" }`,t.appendChild(l);let u=document.createElement(`button`);u.type=`button`,u.className=`primary`,u.textContent=`add`,u.addEventListener(`click`,()=>{let t=s.value.trim().replace(/^\$/,``);if(!t)return;let i=r.value.trim().replace(/\/+$/,``),a=i?`${i}/${t}`:t,o=null,u=l.value.trim();if(u)try{o=JSON.parse(u)}catch{l.classList.add(`invalid`);return}else c.value.trim()&&(o={type:n.value,url:c.value.trim()});o&&(e.cancelAddForms(),e.selectedAsset=a,e.mutate(()=>{e.working.assets||(e.working.assets={});let t=e.working.assets;t[a]=o}))});let d=document.createElement(`div`);return d.className=`pop-actions`,d.appendChild(u),t.appendChild(d),t}function Sj(e,t){let n=document.createElement(`label`);n.className=`field`;let r=document.createElement(`span`);return r.textContent=e,n.append(r,t),n}function Cj(e,t,n){let r=document.createElement(`input`);return r.value=t,r.className=`mono`,r.addEventListener(`change`,()=>n(r.value)),Sj(e,r)}function wj(e){let t=e.trim();if(t===`true`)return!0;if(t===`false`)return!1;if(t!==``&&Number.isFinite(Number(t)))return Number(t);if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return e}return e}var Tj={texture:`M3 5h18v14H3z M3 15l5-5 4 4 3-3 6 6 M8.5 9.5h.01`,spritesheet:`M3 4h18v16H3z M9 4v16 M15 4v16 M3 12h18`,model:`M12 2l9 5v10l-9 5-9-5V7z M12 12l9-5 M12 12L3 7 M12 12v10`,animation:`M12 2a10 10 0 1 0 10 10 M22 12l-3-3m3 3l3-3 M12 7v5l3 3`},Ej={texture:{en:`image (texture) — Sprite2D.texture references it as "$key".`,ko:`이미지(텍스처) — Sprite2D.texture에서 "$키"로 참조합니다.`},spritesheet:{en:`spritesheet — AnimatedSprite2D slices it into named frame animations.`,ko:`스프라이트시트 — AnimatedSprite2D가 이름 붙은 프레임 애니메이션으로 자릅니다.`},model:{en:`3D model (GLB/glTF/VRM) — ModelInstance3D.model references it as "$key".`,ko:`3D 모델(GLB/glTF/VRM) — ModelInstance3D.model에서 "$키"로 참조합니다.`},animation:{en:`animation clips (GLB, in memory — drawn nowhere) — any model can play them; mixamo retargets onto VRM.`,ko:`애니메이션 클립(GLB, 메모리 전용 — 그려지지 않음) — 어떤 모델이든 재생 가능, mixamo는 VRM에 자동 리타게팅.`}};function Dj(e){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);t.setAttribute(`viewBox`,`0 0 24 24`),t.setAttribute(`width`,`13`),t.setAttribute(`height`,`13`),t.setAttribute(`fill`,`none`),t.setAttribute(`stroke`,`currentColor`),t.setAttribute(`stroke-width`,`1.8`),t.setAttribute(`aria-hidden`,`true`);let n=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);return n.setAttribute(`d`,Tj[e]??`M4 4h16v16H4z`),t.appendChild(n),t.classList.add(`asset-icon-${e}`),t}function Oj(e,t){document.querySelector(`.balloon`)?.remove();let n=Ej[t];if(!n)return;let r=document.createElement(`div`);r.className=`balloon floating`;let i=document.createElement(`div`);i.className=`balloon-title`,i.textContent=t;let a=document.createElement(`span`);a.textContent=rj(n),r.append(i,a),document.body.appendChild(r);let o=e.getBoundingClientRect();r.style.left=`${o.right+8}px`,r.style.top=`${Math.max(8,o.top-8)}px`;let s=()=>{r.remove(),document.removeEventListener(`pointerdown`,s,!0)};setTimeout(()=>document.addEventListener(`pointerdown`,s,!0),0)}function kj(e){let t=document.createElement(`div`);t.className=`field uid-line`;let n=document.createElement(`span`);n.textContent=`key`;let r=document.createElement(`div`);r.className=`uid-value`;let i=document.createElement(`code`);i.textContent=`$${e}`;let a=document.createElement(`button`);return a.type=`button`,a.className=`uid-copy`,a.title=`Copy key`,a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,a.addEventListener(`click`,()=>{navigator.clipboard?.writeText(`$${e}`),a.classList.add(`copied`),setTimeout(()=>a.classList.remove(`copied`),600)}),r.append(i,a),t.append(n,r),t}function Aj(e,t){let n=t.includes(`/`)?t.slice(0,t.lastIndexOf(`/`)):``,r=document.createElement(`select`),i=new Set([``]);for(let t of Object.keys(e.working.assets??{})){let e=t.split(`/`);for(let t=1;t<e.length;t++)i.add(e.slice(0,t).join(`/`))}for(let t of e.pendingGroups)i.add(t);for(let e of[...i].sort()){let t=document.createElement(`option`);t.value=e,t.textContent=e===``?`(root)`:`${e}/`,e===n&&(t.selected=!0),r.appendChild(t)}r.addEventListener(`change`,()=>{e.moveAsset(t,r.value)});let a=document.createElement(`label`);a.className=`field`;let o=document.createElement(`span`);return o.textContent=`group`,a.append(o,r),a}function jj(e){e&&(e.addEventListener(`keydown`,e=>{e.key===`/`&&e.preventDefault()}),e.addEventListener(`input`,()=>{e.value.includes(`/`)&&(e.value=e.value.replace(/\//g,``))}))}function Mj(e){let t=document.createElement(`div`);t.className=`section-title`,t.textContent=e;let n=document.createElement(`span`);return n.className=`rule`,t.appendChild(n),t}var Nj=window.parent!==window,Pj=new URLSearchParams(window.location.search).get(`parentOrigin`),Fj=!1;function Ij(e){if(Nj){if(!Pj){Fj||(Fj=!0,console.warn(`incanto-editor: embedded without ?parentOrigin=<origin> — postMessage disabled`));return}window.parent.postMessage(e,Pj)}}var Lj={ready(e,t,n){Ij({type:`incanto-editor:ready`,input:e,output:t,version:n})},open(e,t){Ij({type:`incanto-editor:open`,input:e,output:t})},change(e){Ij({type:`incanto-editor:change`,dirty:e})},save(e,t,n){Ij({type:`incanto-editor:save`,input:e,output:t,data:n})},error(e){Ij({type:`incanto-editor:error`,message:e})}},Rj=[[`Core`,e=>!e.endsWith(`2D`)&&!e.endsWith(`3D`)&&e!==`Label`&&e!==`UILayer`&&e!==`NetworkSpawner`],[`2D`,e=>e.endsWith(`2D`)&&!/Body|Area|Controller/.test(e)||e===`Label`||e===`UILayer`],[`2D Physics`,e=>e.endsWith(`2D`)&&/Body|Area|Controller/.test(e)],[`3D`,e=>e.endsWith(`3D`)&&!/Body|Area|Controller/.test(e)],[`3D Physics`,e=>e.endsWith(`3D`)&&/Body|Area|Controller/.test(e)],[`Network`,e=>e===`NetworkSpawner`]],zj=[...Rj,[`Other`,e=>Rj.every(([,t])=>!t(e))]],Bj={title:{en:`How Incanto scenes work`,ko:`Incanto 씬은 어떻게 동작하나`},sections:[{heading:{en:`Everything is a node in a tree`,ko:`모든 것은 트리 위의 노드`},text:{en:`A scene is ONE tree of typed nodes (Godot-style). Each node has a name (unique among its siblings), a type that defines its props and behavior, optional children, and an optional scene-wide-unique uid. The whole structure lives in a *.scene.json file — there is no hidden state: what you see in this editor IS the file.`,ko:`씬은 타입을 가진 노드들의 단일 트리입니다(Godot 방식). 각 노드는 이름(형제 간 유일), props와 동작을 결정하는 타입, 선택적 자식들, 그리고 선택적인 씬 전역 유일 uid를 가집니다. 전체 구조가 *.scene.json 파일 하나에 들어있고 숨겨진 상태는 없습니다 — 이 에디터에서 보는 것이 곧 파일 그 자체입니다.`}},{heading:{en:`Props are delta-only`,ko:`Props는 변경분만 기록`},text:{en:`Every prop has a default defined by the engine. The JSON only stores values that DIFFER from the default — so files stay small and diffs stay meaningful. This editor follows the same rule: set a value back to its default and it disappears from the file.`,ko:`모든 prop에는 엔진이 정의한 기본값이 있습니다. JSON에는 기본값과 다른 값만 기록되어 파일이 작고 diff가 의미를 가집니다. 이 에디터도 같은 규칙을 따릅니다 — 값을 기본값으로 되돌리면 파일에서 사라집니다.`}},{heading:{en:`Addressing: paths, names, uid, groups`,ko:`노드 찾기: 경로·이름·uid·그룹`},text:{en:`Code reaches nodes four ways: a path like "Player/Skin" (relative) or "%Unique" (marked-unique name), getNodesByName("Enemy") which returns a LIST (names repeat across the tree), getNodeByUid("n_x1y2") which returns exactly one node and survives moves/renames, and groups — free tags for queries like "every coin".`,ko:`코드는 네 가지 방법으로 노드에 접근합니다: "Player/Skin" 같은 경로(상대) 또는 "%Unique"(유일 표시 이름), 트리 전체에서 같은 이름을 모두 찾는 getNodesByName("Enemy") — 이름은 중복될 수 있어 리스트가 돌아옵니다 —, 정확히 한 노드를 돌려주고 이동/개명에도 살아남는 getNodeByUid("n_x1y2"), 그리고 "모든 코인"처럼 묶어 조회하는 자유 태그 groups.`}},{heading:{en:`Signals connect, behaviors act`,ko:`시그널로 잇고 비헤이비어로 움직인다`},text:{en:`Nodes emit signals (an Area2D fires triggerEnter, a Timer fires timeout). The scene's "connections" wire a signal to a handler — declaratively, in JSON. Game logic itself is a Behavior: a TypeScript class in YOUR game, attached by name via "script". The editor shows and edits these links but the code lives in the game.`,ko:`노드는 시그널을 발산합니다(Area2D의 triggerEnter, Timer의 timeout). 씬의 "connections"가 시그널을 핸들러에 선언적으로(JSON으로) 연결합니다. 게임 로직 자체는 Behavior — 게임 쪽 TypeScript 클래스이며 "script"에 이름으로 연결됩니다. 에디터는 이 연결을 보여주고 편집하지만 코드는 게임에 있습니다.`}},{heading:{en:`Assets are declared, then referenced`,ko:`에셋은 선언하고 $키로 참조`},text:{en:`The scene header declares assets (textures, spritesheets, 3D models, animation clips) under a key; nodes reference them as "$key". Animations are data too: an {type:"animation"} asset loads GLB clips into memory and any ModelInstance3D can play them — Mixamo clips retarget onto VRM avatars automatically.`,ko:`씬 헤더에서 에셋(텍스처·스프라이트시트·3D 모델·애니메이션 클립)을 키로 선언하고, 노드는 "$key"로 참조합니다. 애니메이션도 데이터입니다 — {type:"animation"} 에셋이 GLB 클립을 메모리에 올리고 어떤 ModelInstance3D든 재생할 수 있으며, Mixamo 클립은 VRM 아바타에 자동 리타게팅됩니다.`}}]},Z=(e,t,...n)=>({type:e,summary:t,body:n}),Vj=[{id:`core`,label:{en:`Core`,ko:`Core`},intro:{en:`Dimension-free building blocks: plain containers and the game clock. They render nothing themselves.`,ko:`차원과 무관한 기본 블록 — 순수 컨테이너와 게임 시계입니다. 스스로는 아무것도 그리지 않습니다.`},nodes:[Z(`Node`,{en:`A plain container with no transform.`,ko:`변환 없이 자식을 묶는 순수 컨테이너.`},{en:`Use it to group related nodes (all coins, all UI) without affecting their positions. Lifecycle, signals, groups, script — everything works; it just has no visual or spatial meaning of its own.`,ko:`위치에 영향을 주지 않으면서 관련 노드(코인 전부, UI 전부)를 묶을 때 씁니다. 라이프사이클·시그널·그룹·스크립트가 모두 동작하며, 시각적·공간적 의미만 없습니다.`}),Z(`Timer`,{en:"A serializable countdown that emits `timeout`.",ko:"`timeout` 시그널을 쏘는 직렬화 가능한 카운트다운."},{en:`Set waitTime (seconds), optionally autostart or oneShot, and connect its timeout signal to any handler. Because it is a node, the whole timing setup lives in the scene file — agents can read and tune it.`,ko:`waitTime(초)을 정하고 autostart·oneShot을 선택한 뒤 timeout 시그널을 핸들러에 연결하세요. 노드이기 때문에 타이밍 설정 전체가 씬 파일에 남아 에이전트가 읽고 조정할 수 있습니다.`}),Z(`HudLayer`,{en:`Screen-space HUD overlay above the canvas — parent for UiText/UiBar/UiBanner.`,ko:`캔버스 위 화면 고정 HUD 오버레이 — UiText/UiBar/UiBanner의 부모.`},{en:`A DOM overlay (position:fixed) that never blocks pointer input. Put UI widgets as children; each picks one of 9 anchors (topLeft…bottomRight). Works identically over 2D and 3D renderers; in headless/tests it is a silent no-op. zIndex lifts it above the canvas.`,ko:`포인터 입력을 가로막지 않는 DOM 오버레이(position:fixed)입니다. UI 위젯을 자식으로 두면 각자 9개 앵커(topLeft…bottomRight) 중 하나에 붙습니다. 2D·3D 렌더러 어디서나 동일하게 동작하고, 헤드리스/테스트에서는 조용히 no-op입니다. zIndex로 캔버스 위에 올립니다.`}),Z(`UiText`,{en:`A HUD text line — score, timers, hints.`,ko:`HUD 텍스트 한 줄 — 점수, 타이머, 힌트.`},{en:`Child of HudLayer. Set text/size/color in JSON; update from behaviors: (getNode('%Score') as UiText).text = String(score). shadow adds a soft outline for readability over any scene.`,ko:`HudLayer의 자식. text/size/color를 JSON으로 정하고, 비헤이비어에서 (getNode('%Score') as UiText).text = String(score) 로 갱신하세요. shadow는 어떤 화면 위에서도 읽히도록 부드러운 그림자를 더합니다.`}),Z(`UiBar`,{en:`A labeled progress bar — health, stamina, reload, boss HP.`,ko:`라벨 달린 진행 바 — 체력, 스태미나, 재장전, 보스 HP.`},{en:`Child of HudLayer. Drive value/max from behaviors; the fill animates and turns lowColor under lowThreshold (default 30%). width/height/color/background style it; label prefixes a small caption.`,ko:`HudLayer의 자식. 비헤이비어에서 value/max를 갱신하면 채움이 애니메이션되고 lowThreshold(기본 30%) 아래로 떨어지면 lowColor로 바뀝니다. width/height/color/background로 스타일, label로 작은 캡션을 붙입니다.`}),Z(`UiBanner`,{en:`Center-screen announcements with fade and a queue — "WAVE 2", "YOU DIED".`,ko:`페이드·큐가 있는 중앙 공지 — "WAVE 2", "YOU DIED".`},{en:`Child of HudLayer. Call show('WAVE 2', { color, seconds }) from behaviors; messages queue and fade in/out. seconds 0 = sticky until the next show(). clear() drops everything. Emits bannerShown(text).`,ko:`HudLayer의 자식. 비헤이비어에서 show('WAVE 2', { color, seconds })를 호출하면 메시지가 큐에 쌓여 페이드 인/아웃됩니다. seconds 0이면 다음 show()까지 고정, clear()로 전부 제거. bannerShown(text) 시그널을 냅니다.`}),Z(`UiButton`,{en:`A clickable HUD button — menus, START screens, dialog choices.`,ko:`클릭 가능한 HUD 버튼 — 메뉴, 시작 화면, 대화 선택지.`},{en:`Child of HudLayer. Set text/size/color/background; disabled greys it out. Emits the 'pressed' signal (behaviors: node.on('pressed', ...)); press() triggers it programmatically (gamepad menus, tests).`,ko:`HudLayer의 자식. text/size/color/background를 설정하고 disabled로 비활성화합니다. 'pressed' 시그널을 내며(비헤이비어에서 node.on('pressed', ...)), press()로 코드에서도 누를 수 있습니다(게임패드 메뉴, 테스트).`}),Z(`UiDialogue`,{en:`A typewriter dialogue box with a queue and choice buttons — the RPG conversation layer.`,ko:`타자기 효과·큐·선택지 버튼을 갖춘 대화창 — RPG 대화 레이어.`},{en:`Child of HudLayer (anchor bottom by default). say(speaker, text, choices?) queues lines; clicking (or advance()) reveals then advances; choice lines wait for choose(i). Signals: lineShown(text), choiceMade(index), dialogueFinished. charsPerSecond 0 = instant. Check .active to pause player input during conversations.`,ko:`HudLayer의 자식(기본 anchor bottom). say(화자, 텍스트, 선택지?)로 줄을 큐에 넣고, 클릭(또는 advance())이 전체 공개→다음 줄로 진행하며, 선택지 줄은 choose(i)를 기다립니다. 시그널: lineShown(text), choiceMade(index), dialogueFinished. charsPerSecond 0이면 즉시 표시. 대화 중 플레이어 입력을 멈추려면 .active를 확인하세요.`}),Z(`AudioPlayer`,{en:`Plays a sound: zero-asset procedural SFX, BGM loops, or one-shot effects.`,ko:`소리 재생 — 무에셋 절차적 효과음, 배경음 루프, 단발 효과음.`},{en:`Set preset (coin/jump/hurt/explosion/…) for an instant zero-asset SFX (pitch/seed vary it), or leave it "custom" and set src (URL or "$assetKey"). volume 0..1; bus routes through engine.audio (sfx|music) for global volume/mute; loop for music; autoplay starts on ready (browsers may hold it until the first user gesture). Call play()/stop() from game code. Dimension-free — 2D and 3D alike.`,ko:`preset(coin/jump/hurt/explosion/…)을 설정하면 즉시 무에셋 효과음이 납니다(pitch·seed로 변형). 아니면 "custom"으로 두고 src(URL 또는 "$에셋키")를 쓰세요. volume은 0..1, bus는 engine.audio(sfx|music)를 통해 전역 볼륨/음소거에 연결, 음악은 loop, autoplay는 준비되면 재생합니다(브라우저가 첫 입력까지 보류 가능). 게임 코드에서 play()/stop()을 부르세요. 2D·3D 어디서나 동작합니다.`})]},{id:`2d`,label:{en:`2D`,ko:`2D`},intro:{en:`The 2D world is y-down pixels: 1 unit = 1 px, (0,0) top-left, rotation in clockwise degrees. Rendering needs a current Camera2D.`,ko:`2D 세계는 y-아래 픽셀 좌표입니다: 1유닛=1px, (0,0)은 좌상단, 회전은 시계방향 도(degree). 렌더링에는 current 카메라(Camera2D)가 필요합니다.`},nodes:[Z(`Node2D`,{en:`The 2D transform container (position/rotation/scale).`,ko:`2D 변환 컨테이너(position/rotation/scale).`},{en:`Children inherit its transform — move the parent, everything follows. renderOrder orders drawing; visible hides the subtree.`,ko:`자식은 변환을 상속합니다 — 부모를 움직이면 전부 따라옵니다. renderOrder로 그리기 순서를, visible로 서브트리 표시를 제어합니다.`}),Z(`Sprite2D`,{en:`A textured quad.`,ko:`텍스처 사각형(스프라이트).`},{en:`texture is "$assetKey" from the scene assets. anchor [0.5,0.5] centers; flipX/flipY mirror; tint multiplies color; opacity fades. Size comes from the texture × scale.`,ko:`texture는 씬 에셋의 "$키"입니다. anchor [0.5,0.5]면 중앙 기준, flipX/flipY로 반전, tint로 색 곱, opacity로 투명도. 크기는 텍스처 × scale로 정해집니다.`}),Z(`ColorRect2D`,{en:`A flat colored rectangle — no texture needed.`,ko:`단색 사각형 — 텍스처 불필요.`},{en:`size [w,h] px, color, opacity, anchor. Backgrounds, platforms, walls, UI panels, generated-level tiles (maze2d/dungeon2d emit these) — blocky art without any asset.`,ko:`size [w,h] px, color, opacity, anchor. 배경·플랫폼·벽·UI 패널·생성 레벨 타일(maze2d/dungeon2d가 이걸 만듭니다) — 에셋 없이 만드는 블록 그래픽입니다.`}),Z(`TileMap2D`,{en:`A whole tile level as ONE node — grid render + merged static colliders.`,ko:`타일 레벨 전체를 노드 하나로 — 그리드 렌더 + 병합된 정적 콜라이더.`},{en:`Author cells as rows of characters: "." / space = empty, digits 0-9 = atlas tile index, other chars map through legend ({"G": 12}). texture is a "$atlas" asset read left-to-right top-to-bottom in tileSize squares (columns: 0 derives from the texture width). Tile indices listed in solid become static colliders, greedy-merged into a few rectangles. Cell (0,0) hangs its top-left on the node origin.`,ko:`cells를 문자 행으로 작성합니다: "."/공백 = 빈 칸, 숫자 0-9 = 아틀라스 타일 번호, 그 외 문자는 legend({"G": 12})로 매핑. texture는 tileSize 정사각형을 좌→우, 상→하로 읽는 "$아틀라스" 에셋입니다(columns: 0이면 텍스처 폭에서 유도). solid에 나열된 타일 번호는 정적 콜라이더가 되며 소수의 직사각형으로 탐욕 병합됩니다. (0,0) 칸의 좌상단이 노드 원점에 걸립니다.`}),Z(`AnimatedSprite2D`,{en:`Spritesheet animation player.`,ko:`스프라이트시트 애니메이션 플레이어.`},{en:`Point sheet at a "$sheet" asset, define animations as named frame ranges with fps/loop in JSON, set autoplay. Emits animationFinished(name) for one-shot chains.`,ko:`sheet에 "$시트" 에셋을 연결하고, JSON에 fps/loop를 가진 이름별 프레임 구간으로 animations를 정의한 뒤 autoplay를 지정하세요. 단발 애니메이션 연결을 위해 animationFinished(name)를 발산합니다.`}),Z(`Camera2D`,{en:`The 2D view: follow, zoom, limits.`,ko:`2D 시점 — 추적·줌·경계.`},{en:`position is the view CENTER. follow tracks a node path with smoothing (0..1, higher = snappier). limits [minX,minY,maxX,maxY] clamps the view inside a world region. current: true makes it THE camera.`,ko:`position은 화면의 중심입니다. follow가 노드 경로를 smoothing(0..1, 높을수록 빠릿)으로 추적합니다. limits [minX,minY,maxX,maxY]가 시점을 월드 영역 안에 가둡니다. current: true인 카메라가 실제 시점이 됩니다.`}),Z(`Particles2D`,{en:`A 2D particle emitter (fire, sparks, smoke…).`,ko:`2D 파티클 이미터(불·스파크·연기…).`},{en:`Start from a preset (fire/smoke/sparks/…) then override any prop: rate, lifetime/speed ranges, direction + spread, gravity, size/color/alpha start→end, additive blend. burst > 0 with emitting: false makes a one-shot that emits finished. Animates LIVE in this editor.`,ko:`preset(fire/smoke/sparks/…)에서 시작해 어떤 prop이든 덮어쓰세요: rate, lifetime/speed 구간, direction+spread, gravity, size/color/alpha 시작→끝, additive blend. emitting: false에 burst > 0이면 단발 발사 후 finished를 발산합니다. 이 에디터에서 라이브로 움직입니다.`}),Z(`Label`,{en:`Text rendered to a quad.`,ko:`텍스트를 그리는 노드.`},{en:`text/fontSize/color/font/align — rendered via CanvasTexture, so any system font string works. Inside a UILayer it pins to the screen (HUD).`,ko:`text/fontSize/color/font/align — CanvasTexture로 그려져 시스템 폰트 문자열을 그대로 쓸 수 있습니다. UILayer 아래에 두면 화면에 고정됩니다(HUD).`}),Z(`UILayer`,{en:`A screen-space subtree (HUD).`,ko:`화면 고정 서브트리(HUD).`},{en:`Everything under it ignores the camera: positions are screen pixels from the top-left. Score counters, prompts, menus go here.`,ko:`이 아래의 모든 것은 카메라를 무시합니다 — 좌상단 기준 화면 픽셀 좌표입니다. 점수, 안내 문구, 메뉴를 여기에 둡니다.`})]},{id:`2d-physics`,label:{en:`2D Physics`,ko:`2D 물리`},intro:{en:`Rapier-backed. Colliders are PROPS ({shape, …}) — the green dashed wireframes in this editor. Physics runs when the game calls enablePhysics2D (and in play mode). Gravity lives on the scene row.`,ko:`Rapier 기반입니다. 콜라이더는 prop({shape, …})이며 에디터의 초록 점선이 그것입니다. 물리는 게임이 enablePhysics2D를 부를 때(그리고 플레이 모드에서) 돌고, 중력은 씬 행에 있습니다.`},nodes:[Z(`StaticBody2D`,{en:`Immovable collision: ground, walls, platforms.`,ko:`움직이지 않는 충돌체 — 바닥·벽·플랫폼.`},{en:`Other bodies collide with it; it never moves. Cheapest body type — use it for all level geometry.`,ko:`다른 바디가 부딪히지만 자신은 절대 움직이지 않습니다. 가장 저렴한 바디 — 레벨 지형 전부에 쓰세요.`}),Z(`RigidBody2D`,{en:`Fully simulated: falls, bounces, pushes.`,ko:`완전 시뮬레이션 — 떨어지고 튕기고 밀립니다.`},{en:`Gravity and collisions drive it. Set linearVelocity to launch. For player characters prefer CharacterBody2D (direct control).`,ko:`중력과 충돌이 움직임을 결정합니다. linearVelocity로 발사하세요. 플레이어 캐릭터에는 직접 제어가 가능한 CharacterBody2D를 권합니다.`}),Z(`CharacterBody2D`,{en:`Kinematic character: you set velocity, it slides.`,ko:`키네마틱 캐릭터 — 속도를 주면 미끄러지듯 이동.`},{en:`moveAndSlide() resolves collisions without physics pushing back; isOnFloor() gates jumps. Sensors (Area2D) do not block it but still fire triggers.`,ko:`moveAndSlide()가 밀려나지 않으면서 충돌을 처리하고 isOnFloor()로 점프를 판정합니다. 센서(Area2D)는 길을 막지 않으면서 트리거를 발사합니다.`}),Z(`Area2D`,{en:`A sensor: overlap triggers, no collision response.`,ko:`센서 — 겹침 감지만, 충돌 반응 없음.`},{en:`Fires triggerEnter(other)/triggerExit(other). Coins, checkpoints, damage zones. Filter with other.isInGroup("player").`,ko:`triggerEnter(other)/triggerExit(other)를 발산합니다. 코인·체크포인트·데미지 존에 쓰고, other.isInGroup("player")로 거릅니다.`}),Z(`CharacterController2D`,{en:`Zero-code platformer/top-down movement.`,ko:`코드 없는 플랫포머/탑다운 이동.`},{en:`Put it UNDER a CharacterBody2D. mode "platformer" (gravity + jump via jumpAction) or "topDown" (free 2-axis). Reads the scene input map actions (moveAction/jumpAction). maxSpeed/jumpHeight are intent-level numbers.`,ko:`CharacterBody2D의 자식으로 두세요. mode는 "platformer"(중력+jumpAction 점프) 또는 "topDown"(자유 2축)이며 씬 입력 맵의 액션(moveAction/jumpAction)을 읽습니다. maxSpeed/jumpHeight는 의도 그대로의 숫자입니다.`}),Z(`Joint2D`,{en:`A physics joint linking its parent body to a target body — weld, hinge, rope, spring.`,ko:`부모 바디와 대상 바디를 잇는 물리 조인트 — 용접, 힌지, 로프, 스프링.`},{en:`Child of body A (a physics body); "target" is a node path to body B. type: fixed (rigid weld) / revolute (pin at the anchors) / rope (caps anchor distance at length px; 0 = measured at creation) / spring (pulls toward length with stiffness/damping). anchor/targetAnchor are LOCAL px offsets.`,ko:`바디 A(물리 바디)의 자식으로 두고 "target"에 바디 B의 노드 경로를 줍니다. type: fixed(강체 용접) / revolute(앵커 핀 힌지) / rope(앵커 간 거리를 length px로 제한, 0이면 생성 시 실측) / spring(stiffness/damping으로 length를 향해 당김). anchor/targetAnchor는 로컬 px 오프셋.`})]},{id:`3d`,label:{en:`3D`,ko:`3D`},intro:{en:`Meters, y-up, rotations in degrees. Standard materials need LIGHT — add a DirectionalLight3D or scene ambient, or you get silhouettes.`,ko:`미터 단위, y-위, 회전은 도(degree)입니다. 표준 머티리얼은 빛이 필요합니다 — DirectionalLight3D나 씬 ambient가 없으면 실루엣만 보입니다.`},nodes:[Z(`Node3D`,{en:`The 3D transform container.`,ko:`3D 변환 컨테이너.`},{en:`position [x,y,z] in meters, rotation [x,y,z] in degrees, scale per axis. Children inherit.`,ko:`position [x,y,z] 미터, rotation [x,y,z] 도, scale은 축별. 자식이 상속합니다.`}),Z(`MeshInstance3D`,{en:`A primitive mesh + material.`,ko:`프리미티브 메시 + 머티리얼.`},{en:`mesh: box/sphere/plane/cylinder…, size per primitive, material {color, roughness, metalness, emissive, emissiveIntensity, wireframe, map, normalMap, repeat} (this editor gives it swatches, sliders, texture-URL fields, and a repeat [u,v] tiling vector). map/normalMap are texture URLs; repeat only takes effect with a map. castShadow/receiveShadow per node.`,ko:`mesh: box/sphere/plane/cylinder…, 프리미티브별 size, material {color, roughness, metalness, emissive, emissiveIntensity, wireframe, map, normalMap, repeat}(에디터가 스와치·슬라이더·텍스처 URL 입력·repeat [u,v] 타일링 벡터 제공). map/normalMap은 텍스처 URL, repeat는 map이 있을 때만 적용. 그림자는 castShadow/receiveShadow.`}),Z(`LoftMesh3D`,{en:`A smooth swept hull (loft).`,ko:`부드러운 스윕 선체(로프트).`},{en:`sections: ≥2 cross-section stations {z, width, height, y, corner 0..1} interpolated into ONE smooth curved surface — vehicle bodies, glass canopies, boat hulls. slices/smooth control tessellation. Same material as MeshInstance3D minus textures (no UVs); pair clearcoat paint or high-envMapIntensity glass with the smooth normals for the automotive look.`,ko:`sections: 단면 스테이션 {z, width, height, y, corner 0..1} 2개 이상을 보간해 하나의 매끈한 곡면을 만듭니다 — 차체, 유리 캐노피, 선체. slices/smooth로 테셀레이션 조절. material은 MeshInstance3D와 동일하되 텍스처 제외(UV 없음). clearcoat 도장이나 높은 envMapIntensity 유리를 곡면 법선과 조합하면 자동차 룩이 납니다.`}),Z(`ModelInstance3D`,{en:`A GLB/glTF/VRM model file.`,ko:`GLB/glTF/VRM 모델 파일.`},{en:'model: "$assetKey" or URL. targetHeight scales the model to stand N units tall (run `npx incanto-model file.glb` to read its real size first). animation plays an embedded clip name OR an "$animation" asset — Mixamo clips retarget onto VRM humanoids automatically. One node per VRM asset (the avatar runtime mounts live).',ko:'model은 "$에셋키" 또는 URL입니다. targetHeight가 모델을 N유닛 높이로 맞춥니다(먼저 `npx incanto-model 파일.glb`로 실제 크기를 확인하세요). animation은 내장 클립 이름 또는 "$애니메이션" 에셋을 재생하며, Mixamo 클립은 VRM 휴머노이드에 자동 리타게팅됩니다. VRM 에셋은 노드 하나만 쓸 수 있습니다(아바타 런타임이 라이브로 마운트됨).'}),Z(`Sprite3D`,{en:`A 2D image as a camera-facing billboard (the 2.5D look).`,ko:`카메라를 향하는 2D 빌보드 스프라이트(2.5D 룩).`},{en:`A textured quad that turns to face the camera inside the 3D world (Octopath / Don't Starve / MapleStory-in-3D). texture is an image URL; size is [w,h] in METERS. billboard: "y" stays upright with a screen-aligned yaw — off-center sprites never roll (characters/props), "full" faces it completely (items/FX), "none" is fixed to the node rotation. anchor [0.5,0] plants the feet on the ground. pixelArt nearest-filters for crisp pixels; alphaTest is a hard cutout that depth-sorts against 3D geometry (a tree occludes it); flipX mirrors left/right; tint/opacity recolor.`,ko:`3D 월드 안에서 카메라를 향해 도는 텍스처 쿼드(Octopath/Don't Starve, 3D 속 메이플스토리 룩). texture는 이미지 URL, size는 [너비,높이] 미터. billboard: "y"는 세로로 선 채 카메라 방향과 정렬된 yaw — 화면 가장자리에서도 기울지 않음(캐릭터/사물), "full"은 완전히 향함(아이템/FX), "none"은 노드 회전에 고정. anchor [0.5,0]은 발을 바닥에 둡니다. pixelArt는 nearest 필터로 픽셀을 또렷하게, alphaTest는 3D 지형과 깊이정렬되는 하드 컷아웃(나무가 가림), flipX는 좌우 반전, tint/opacity로 색·투명도.`}),Z(`AnimatedSprite3D`,{en:`A billboard sprite that plays spritesheet animations.`,ko:`스프라이트시트 애니를 재생하는 빌보드 스프라이트.`},{en:`Everything Sprite3D does, plus frame animation. sheet is a spritesheet image URL whose cells are frameWidth×frameHeight; animations maps a name to {frames, fps, loop} where frames is an inclusive [start,end] range or an explicit list; autoplay starts one on load. Game code calls play("walk") / stop(); a non-looping clip clamps on its last frame and emits animationFinished(name) — chain attack→idle from it.`,ko:`Sprite3D의 모든 기능 + 프레임 애니. sheet는 frameWidth×frameHeight 칸을 가진 스프라이트시트 URL, animations는 이름→{frames, fps, loop}(frames는 포함 [시작,끝] 범위 또는 명시 목록), autoplay는 로드 시 하나를 시작. 게임 코드에서 play("walk")/stop() 호출, 비반복 클립은 마지막 프레임에 머물며 animationFinished(name)를 emit(attack→idle 연결).`}),Z(`Billboard3D`,{en:`A group that turns toward the camera — children follow.`,ko:`카메라를 향해 도는 그룹 — 자식들이 함께 회전.`},{en:`A transform container that orients itself toward the camera every frame; children inherit the rotation, so hang world-space UI under it — HP bars, markers, floating icons (text is a canvas-rendered texture on a child Sprite3D). mode: "screen" (default) copies the camera orientation so a child rectangle stays an upright rectangle anywhere on screen (a yaw-only look-at visibly tilts off-center shapes under a pitched camera); "y" stays upright with a screen-aligned yaw (no off-center roll); "none" turns billboarding off. While billboarding, the node's own rotation prop (and the rotate gizmo) is overwritten every frame — switch to "none" to pose children, then switch back. Unlike Sprite3D (a textured quad that spins only its own image), Billboard3D rotates the whole group.`,ko:`매 프레임 카메라를 향해 자신을 회전시키는 변환 컨테이너로, 자식이 회전을 상속합니다 — HP바·마커·아이콘 같은 월드 UI를 자식으로 붙이세요(텍스트는 캔버스로 그린 텍스처를 자식 Sprite3D에). mode: "screen"(기본)은 카메라 자세를 그대로 복사해 자식 직사각형이 화면 어디서든 똑바른 직사각형으로 보입니다(yaw만 도는 look-at은 기울어진 카메라에서 중앙 밖 도형이 눈에 띄게 비스듬해짐); "y"는 세로로 선 채 카메라로 yaw만; "none"은 빌보드 끔. 빌보드 중에는 노드 자신의 rotation(회전 기즈모 포함)이 매 프레임 덮어써집니다 — 자식을 배치할 땐 "none"으로 바꿨다가 되돌리세요. 자기 그림만 도는 Sprite3D(텍스처 쿼드)와 달리 그룹 전체가 회전합니다.`}),Z(`Camera3D`,{en:`The 3D view.`,ko:`3D 시점.`},{en:`Perspective camera; fov in degrees; current: true selects it. Use the editor's "game cam" (0) to preview exactly what it renders.`,ko:`원근 카메라이며 fov는 도 단위, current: true가 실제 시점이 됩니다. 에디터의 "game cam"(0)으로 정확한 렌더 결과를 미리 보세요.`}),Z(`DirectionalLight3D`,{en:`Sun-like light from a direction.`,ko:`태양광 — 방향에서 평행하게.`},{en:`Position sets the direction toward the origin. intensity/color; pair with scene ambient for soft fill.`,ko:`위치가 원점을 향한 방향을 정합니다. intensity/color를 조절하고 부드러운 채움광은 씬 ambient와 함께 쓰세요.`}),Z(`OmniLight3D`,{en:`A point light radiating everywhere.`,ko:`점광 — 사방으로 퍼지는 빛.`},{en:`Lamps, torches, glows. range limits reach; intensity/color shape the falloff.`,ko:`램프·횃불·발광체. range로 도달 거리를, intensity/color로 감쇠를 만듭니다.`}),Z(`Particles3D`,{en:`A 3D particle emitter (fire, magic, weather…).`,ko:`3D 파티클 이미터(불·마법·날씨…).`},{en:`The same preset + override model as Particles2D, in meters with [x,y,z] gravity. Camera-facing billboard quads, instanced — hundreds are cheap. Animates LIVE in this editor.`,ko:`Particles2D와 같은 preset+덮어쓰기 모델을 미터 단위와 [x,y,z] 중력으로. 카메라를 향하는 빌보드 쿼드를 인스턴싱해 수백 개도 가볍습니다. 이 에디터에서 라이브로 움직입니다.`}),Z(`Terrain3D`,{en:`Procedural heightfield terrain with biome texture splatting.`,ko:`바이옴 텍스처 스플래팅이 적용된 절차적 하이트필드 지형.`},{en:`Seeded simplex hills displaced once on the CPU; theme (island/alpine/plains/desert/custom) picks the 4 blended biome textures by height and slope. heightAt(x,z) answers the surface height anywhere. For physics, parent it under a StaticBody3D with collider {shape:'heightfield'}.`,ko:`시드 기반 심플렉스 언덕을 CPU에서 한 번 변위합니다. theme(island/alpine/plains/desert/custom)이 높이·경사로 블렌딩되는 바이옴 텍스처 4장을 고릅니다. heightAt(x,z)로 어디서든 지표 높이를 얻고, 물리는 StaticBody3D 아래에 두고 collider {shape:'heightfield'}를 쓰세요.`}),Z(`Water3D`,{en:`A shader-water surface with splash signals.`,ko:`스플래시 신호를 내는 셰이더 물 표면.`},{en:`size [w,d] meters on XZ. quality 'fancy' (default) = FBM wave shader with a trough/surface/peak ramp (colors), CubeCamera reflections (reflection/reflectionInterval) and opt-in shoreline foam; 'simple' = the cheap sine material (color). Bodies crossing the surface emit entered/exited(body) and raise ripples (interaction). Volumetric gameplay still wants an Area3D. Waves animate LIVE in this editor.`,ko:`XZ 평면에 size [w,d] 미터. quality 'fancy'(기본)는 FBM 파도 셰이더 — trough/surface/peak 램프(colors), CubeCamera 반사(reflection/reflectionInterval), 옵트인 해안 거품(foam). 'simple'은 저사양용 사인파 머티리얼(color). 바디가 수면을 지나면 entered/exited(body) 신호와 물결이 일어납니다(interaction). 부피 기반 게임플레이엔 여전히 Area3D를 쓰세요. 이 에디터에서 파도가 라이브로 움직입니다.`}),Z(`River3D`,{en:`Running water derived from a path and the ground under it.`,ko:`경로와 그 아래 지형에서 유도되는 흐르는 물.`},{en:`Author a centerline path [[x,z],…] plus width/widths (a profile source→mouth) and depth; the node samples the Terrain3D underneath and derives the rest — a surface that follows the bed's descending envelope (water never climbs), a current that speeds up where the channel pinches or tips (flowSpeed is the mean), whitewater from grade, bank shear and thinning column, and banks cut by the ground itself (each vertex carries its own water column). Cut the bed first with a Terrain3D channels entry on the SAME path, or the water lies on the ground as a film. flowForce drags bodies downstream (drag, never thrust) and sampleAt(x,z) answers where a world point sits in the channel. No extra render passes — a map can carry a dozen.`,ko:`중심선 path [[x,z],…]와 width/widths(상류→하류 프로파일), depth만 주면 나머지는 아래 Terrain3D를 샘플링해 유도합니다 — 강바닥의 하강 포락선을 따르는 수면(물은 절대 거슬러 오르지 않음), 폭이 좁아지거나 경사가 급해지면 빨라지는 유속(flowSpeed는 평균), 경사·둑 전단·얕아지는 수심에서 생기는 흰 물살, 그리고 지형 자체가 깎아내는 강둑(정점마다 자기 수심을 지님). 같은 path로 Terrain3D의 channels를 먼저 파세요 — 아니면 물이 지면 위에 얇은 막처럼 깔립니다. flowForce가 바디를 하류로 끌고(밀지 않고 끌어당김), sampleAt(x,z)로 월드 좌표가 수로 어디에 있는지 알 수 있습니다. 추가 렌더 패스가 없어 한 맵에 여러 개를 둘 수 있습니다.`}),Z(`Foliage3D`,{en:`An instanced grass/flower carpet that sways.`,ko:`바람에 흔들리는 인스턴스 풀밭/꽃밭.`},{en:`kind grass/flowers/reeds scattered over area [w,d] at density (capped by maxInstances — instanced, tens of thousands of blades cheap). Grass defaults to style 'mesh': every instance is a REAL tapered blade curved by a bezier vertex shader — Voronoi-clump hue/lean, groundColor soil roots (match the terrain), sunDirection tip sheen, 2-octave rolling wind, fadeStart/fadeEnd camera LOD, and (interaction) blade-bending around moving bodies. style 'blades' keeps the 8-SDF-blades-per-quad ported shader, 'simple' the legacy quads. colorA/colorB tint bottom→top, sway sets the wind, seed makes the scatter reproducible.`,ko:`kind grass/flowers/reeds를 area [w,d]에 density로 흩뿌립니다(maxInstances 상한 — 인스턴싱이라 수만 가닥도 가벼움). grass는 기본 style 'mesh': 인스턴스 하나하나가 베지어 버텍스 셰이더로 휘어지는 진짜 잎 메시 — 보로노이 클럼프 색/기울기, groundColor 흙빛 뿌리(지형 색에 맞추세요), sunDirection 잎끝 광택, 2옥타브 굽이치는 바람, fadeStart/fadeEnd 카메라 LOD, (interaction) 움직이는 바디 주변 풀 눕힘까지. style 'blades'는 쿼드당 8가닥 SDF 셰이더, 'simple'은 기존 쿼드 룩. colorA/colorB가 아래→위 색, sway가 바람 세기, seed가 배치를 재현 가능하게 합니다.`}),Z(`Flowers3D`,{en:`Instanced flower PLANTS — stems, leaves, multi-petal heads.`,ko:`인스턴스 꽃밭 — 줄기·잎·여러 장 꽃잎의 진짜 꽃 식물.`},{en:`Real procedural flower plants (curved stem, 2-3 leaves, a 5-8 petal head around a contrasting center disc, 1-3 blooms per plant) scattered over area [w,d]. density is the vibe dial: 'lush' / 'sparse' (default) / 'none', or a number in plants/m². varieties picks a subset of daisy/cosmos/bellflower ([] = all three); palette sets the head colors ([] = white/yellow/violet). clustering 0-1 gathers plants into Voronoi patches that bloom one species + color together; sway bobs the heads in a gentle wind; seed makes the field reproducible. ≤3 varieties → ≤6 draw calls.`,ko:`진짜 프로시저럴 꽃 식물(휘어진 줄기, 잎 2-3장, 대비되는 중심 원반을 두른 꽃잎 5-8장 머리, 포기당 꽃 1-3송이)을 area [w,d]에 흩뿌립니다. density가 바이브 다이얼: 'lush'(풍성하게) / 'sparse'(듬성듬성, 기본) / 'none'(없게) 또는 m²당 개수. varieties는 daisy/cosmos/bellflower 부분집합([] = 셋 다), palette는 꽃 색([] = 흰/노랑/보라). clustering 0-1이 보로노이 패치로 모아 한 패치가 같은 종·같은 색으로 피고, sway가 바람에 머리를 끄덕이며, seed로 배치가 재현됩니다. 품종 ≤3 → 드로우 콜 ≤6.`}),Z(`Tree3D`,{en:`Procedural ez-tree groves — branchy trunks, textured leaves.`,ko:`프로시저럴 ez-tree 나무 — 가지 달린 줄기와 텍스처 잎까지.`},{en:`type conifer/broadleaf/dead picks the recipe family; tier is the cost dial: simple = primitive low-poly, medium = light forest presets (≤3k tris/tree), high = full ez-tree presets (8–20k, hero trees). count > 1 scatters a forest patch over area [w,d] — up to 3 seed variants, each branches + leaves InstancedMesh (≤6 draw calls); count × tris/tree is budget-checked at load. seed makes every branch and leaf reproducible; height jitters ±20% per instance; leaves sway in a simplex wind.`,ko:`type conifer/broadleaf/dead가 수종을, tier가 비용을 정합니다: simple = 기존 로우폴리, medium = 가벼운 forest 프리셋(나무당 ≤3k tris), high = 풀 ez-tree 프리셋(8–20k, 주인공 나무). count > 1이면 area [w,d]에 숲 패치를 흩뿌립니다 — 시드 변형 최대 3종, 변형마다 가지+잎 InstancedMesh(드로우 콜 ≤6), count × tris는 로드 시 예산 검사. seed로 가지와 잎이 전부 재현되고 height는 인스턴스마다 ±20% 지터링, 잎은 심플렉스 바람에 흔들립니다.`}),Z(`VoxelGrid3D`,{en:`A Minecraft-style block grid in ONE node.`,ko:`마인크래프트식 블록 그리드 — 노드 하나로.`},{en:`voxels is a list of [x,y,z,palette] integer cells (terrain/island generators emit these). Greedy-meshed and instanced — large worlds stay one draw batch. Game code edits blocks via setBlock/getBlock; emits blocksChanged.`,ko:`voxels는 [x,y,z,팔레트] 정수 셀 목록입니다(terrain/island 생성기가 만들어 냅니다). 그리디 메싱+인스턴싱으로 큰 월드도 드로우 배치 하나를 유지합니다. 게임 코드는 setBlock/getBlock으로 수정하고 blocksChanged가 발산됩니다.`})]},{id:`3d-physics`,label:{en:`3D Physics`,ko:`3D 물리`},intro:{en:`Same model as 2D, in meters with y-up gravity ([0,-9.81,0] default). Colliders: box {size}, sphere {radius}, capsule {radius,height}.`,ko:`2D와 같은 모델을 미터·y-위 중력([0,-9.81,0] 기본)으로. 콜라이더는 box {size}, sphere {radius}, capsule {radius,height}.`},nodes:[Z(`StaticBody3D`,{en:`Immovable 3D collision.`,ko:`움직이지 않는 3D 충돌체.`},{en:`Floors, walls, level geometry.`,ko:`바닥·벽·레벨 지형.`}),Z(`RigidBody3D`,{en:`Simulated 3D body.`,ko:`시뮬레이션되는 3D 바디.`},{en:`Crates, balls, debris — gravity and impacts drive it.`,ko:`상자·공·파편 — 중력과 충격이 움직입니다.`}),Z(`CharacterBody3D`,{en:`Kinematic 3D character.`,ko:`키네마틱 3D 캐릭터.`},{en:`moveAndSlide with up = +y; isOnFloor for jumps.`,ko:`+y를 위로 moveAndSlide, 점프 판정은 isOnFloor.`}),Z(`Area3D`,{en:`3D overlap sensor.`,ko:`3D 겹침 센서.`},{en:`triggerEnter/Exit — pickups, zones, goals.`,ko:`triggerEnter/Exit — 아이템·존·골인 지점.`}),Z(`CharacterController3D`,{en:`Zero-code 3D movement + camera rig.`,ko:`코드 없는 3D 이동 + 카메라 리그.`},{en:`Put it UNDER a CharacterBody3D. view: thirdPerson (orbit + zoom), firstPerson (eyeHeight, mouseLook), sideView or flightView. Reads moveAction/jumpAction/sprintAction from the scene input map; skinPath turns the visual child to face travel. Intent-level numbers: maxSpeed, jumpVelocity, camDistance.`,ko:`CharacterBody3D의 자식으로 두세요. view는 thirdPerson(궤도+줌), firstPerson(eyeHeight, mouseLook), sideView, flightView 중 하나입니다. 씬 입력 맵의 moveAction/jumpAction/sprintAction을 읽고 skinPath의 비주얼 자식을 진행 방향으로 돌립니다. maxSpeed·jumpVelocity·camDistance 같은 의도 수준의 숫자만 만집니다.`}),Z(`BoneLookAt3D`,{en:`Look-at IK for one bone — the head turns toward a target on top of the animation.`,ko:`본 하나의 룩앳 IK — 애니메이션 위에서 머리가 대상을 향해 돌아갑니다.`},{en:`"target" = ModelInstance3D path, "bone" = bone name (default Head), "lookAt" = the node to watch (e.g. "%Player"). Blends in/out smoothly and DISENGAGES beyond maxAngleDeg (no owl necks); weight sets how far it commits. forwardAxis names the bone's facing axis (mixamo heads: +z). Purely visual — headless no-op.`,ko:`"target"에 ModelInstance3D 경로, "bone"에 본 이름(기본 Head), "lookAt"에 바라볼 노드(예: "%Player")를 줍니다. 부드럽게 페이드 인/아웃하고 maxAngleDeg 밖에서는 해제됩니다(목이 돌아가지 않음). weight로 몰입도를 조절하고 forwardAxis는 본의 정면 축입니다(mixamo 머리: +z). 순수 시각 기능 — 헤드리스에서는 no-op.`}),Z(`InstancedMesh3D`,{en:`Hundreds of copies of one mesh in ONE draw call — rocks, posts, crates.`,ko:`메시 하나의 수백 개 복사본을 드로우콜 1개로 — 바위, 말뚝, 상자.`},{en:`Same mesh/size/material surface as MeshInstance3D; "transforms" places the copies — each row [x, y, z, yawDeg?, scale?]. Replace the whole array to update (mutations are not watched). The scattering workhorse for open worlds.`,ko:`MeshInstance3D와 같은 mesh/size/material 표면에 "transforms"로 복사본을 배치합니다 — 각 행은 [x, y, z, yawDeg?, scale?]. 갱신은 배열 전체 교체로 하세요(내부 변경은 감지되지 않음). 오픈월드 스캐터링의 주력입니다.`}),Z(`BoneAttachment3D`,{en:`Rides a skeleton bone of an animated model — swords in hands, hats on heads.`,ko:`애니메이션 모델의 스켈레톤 본을 따라다님 — 손에 쥔 검, 머리 위 모자.`},{en:`"target" is a node path to the ModelInstance3D, "bone" the bone name ("RightHand" also matches the Mixamo spellings). Children inherit the live animated transform; this node's own position/rotation become a bone-space offset. Purely visual — headless it stays where its props put it, so keep gameplay checks range-based.`,ko:`"target"에 ModelInstance3D 노드 경로, "bone"에 본 이름을 줍니다("RightHand"는 Mixamo 표기도 자동 매칭). 자식들이 살아있는 애니메이션 트랜스폼을 물려받고, 이 노드의 position/rotation은 본 기준 오프셋이 됩니다. 순수 시각 기능 — 헤드리스에서는 prop 위치에 머무니 게임 판정은 거리 기반으로 유지하세요.`}),Z(`Trail3D`,{en:`A fading world-space ribbon behind the parent — wingtip trails, sword arcs, tyre streaks.`,ko:`부모 뒤로 남는 페이드아웃 월드 리본 — 날개끝 궤적, 검격 궤적, 타이어 자국.`},{en:"Child of the moving node. Records the world position over `seconds` and renders a camera-facing strip that tapers and fades to the tail. width (m), color, opacity, additive for glowing energy trails, minDistance filters jitter. emitting: false stops laying new ribbon while the old tail fades out.",ko:`움직이는 노드의 자식으로 두세요. seconds 동안의 월드 위치를 기록해 꼬리로 갈수록 가늘어지고 투명해지는 카메라 지향 스트립을 그립니다. width(m), color, opacity, 빛나는 에너지 궤적에는 additive, minDistance로 떨림을 걸러냅니다. emitting: false면 새 리본만 멈추고 기존 꼬리는 자연스럽게 사라집니다.`}),Z(`Joint3D`,{en:`A physics joint linking its parent body to a target body — weld, ball joint, rope, spring.`,ko:`부모 바디와 대상 바디를 잇는 물리 조인트 — 용접, 볼 조인트, 로프, 스프링.`},{en:`Child of body A; "target" is a node path to body B. type: fixed (rigid weld) / spherical (ball joint at the anchors) / rope (caps anchor distance at length m; 0 = measured at creation) / spring (pulls toward length with stiffness/damping). anchor/targetAnchor are LOCAL meter offsets.`,ko:`바디 A의 자식으로 두고 "target"에 바디 B의 노드 경로를 줍니다. type: fixed(강체 용접) / spherical(앵커 볼 조인트) / rope(앵커 간 거리를 length m로 제한, 0이면 생성 시 실측) / spring(stiffness/damping으로 length를 향해 당김). anchor/targetAnchor는 로컬 미터 오프셋.`})]},{id:`network`,label:{en:`Network`,ko:`네트워크`},intro:{en:`Multiplayer is transport-agnostic: the engine speaks one NetworkTransport interface (built-in offline Loopback + an @agent8/gameserver adapter). The scene declares replication; one owner node per player broadcasts its sync keys.`,ko:`멀티플레이어는 트랜스포트 불가지론입니다 — 엔진은 NetworkTransport 인터페이스 하나만 사용합니다(내장 오프라인 Loopback + @agent8/gameserver 어댑터). 복제는 씬이 선언하며, 플레이어당 하나의 owner 노드가 sync 키를 송출합니다.`},nodes:[Z(`NetworkSpawner`,{en:`Spawns a registered scene per remote player/entity.`,ko:`원격 플레이어/엔티티마다 등록된 씬을 생성.`},{en:`source "users" mirrors every OTHER account in the room (self skipped); "collection:<id>" mirrors a room collection. Replicated sync patches apply to each instance; position interpolates. Emits spawned/despawned.`,ko:`source "users"는 방의 다른 모든 계정을 미러링하고(자신 제외) "collection:<id>"는 방 컬렉션을 미러링합니다. 복제 sync 패치가 인스턴스에 적용되고 position은 보간됩니다. spawned/despawned를 발산합니다.`})]}],Hj=`overview`,Uj=null;function Wj(){document.querySelector(`#docs`)?.removeAttribute(`hidden`),qj()}function Gj(){document.querySelector(`#docs`)?.setAttribute(`hidden`,``)}function Kj(){let e=document.querySelector(`#docs`);e&&(e.addEventListener(`pointerdown`,t=>{t.target===e&&Gj()}),document.querySelector(`#docs-close`)?.addEventListener(`click`,Gj))}function qj(){let e=document.querySelector(`#docs-tabs`),t=document.querySelector(`#docs-body`);if(!e||!t)return;e.textContent=``;let n=(t,n)=>{let r=document.createElement(`button`);r.type=`button`,r.className=`docs-tab${Hj===t?` active`:``}`,r.textContent=n,r.addEventListener(`click`,()=>{Hj=t,Uj=null,qj()}),e.appendChild(r)};n(`overview`,rj({en:`Overview`,ko:`개요`}));for(let e of Vj)n(e.id,rj(e.label));if(t.textContent=``,Hj===`overview`){Jj(t);return}let r=Vj.find(e=>e.id===Hj);r&&Yj(t,r)}function Jj(e){let t=document.createElement(`h2`);t.textContent=rj(Bj.title),e.appendChild(t);for(let t of Bj.sections){let n=document.createElement(`h3`);n.textContent=rj(t.heading);let r=document.createElement(`p`);r.textContent=rj(t.text),e.append(n,r)}}function Yj(e,t){let n=document.createElement(`p`);n.className=`docs-intro`,n.textContent=rj(t.intro),e.appendChild(n);for(let n of t.nodes){let t=document.createElement(`div`);t.className=`docs-node${Uj===n.type?` open`:``}`;let r=document.createElement(`button`);r.type=`button`,r.className=`docs-node-head`;let i=document.createElement(`span`);i.className=`tree-icon`,i.appendChild(oj(n.type));let a=document.createElement(`strong`);a.textContent=n.type;let o=document.createElement(`span`);if(o.className=`docs-summary`,o.textContent=rj(n.summary),r.append(i,a,o),r.addEventListener(`click`,()=>{Uj=Uj===n.type?null:n.type,qj()}),t.appendChild(r),Uj===n.type){let e=document.createElement(`div`);e.className=`docs-detail`;for(let t of n.body){let n=document.createElement(`p`);n.textContent=rj(t),e.appendChild(n)}e.appendChild(Xj(n.type)),t.appendChild(e)}e.appendChild(t)}}function Xj(e){let t=document.createElement(`table`);t.className=`docs-props`;let n=document.createElement(`tr`);for(let e of[rj({en:`prop`,ko:`prop`}),rj({en:`default`,ko:`기본값`})]){let t=document.createElement(`th`);t.textContent=e,n.appendChild(t)}t.appendChild(n);try{let n=ge(e);for(let[e,r]of Object.entries(n)){let n=document.createElement(`tr`),i=document.createElement(`td`);i.className=`mono`,i.textContent=e;let a=document.createElement(`td`);a.className=`mono`,a.textContent=JSON.stringify(r.default),n.append(i,a),t.appendChild(n)}}catch{}return t}function Q(e){return Math.round(e*100)/100}function Zj(e,t,n,r,i){return{name:e,type:`StaticBody3D`,props:{collider:{shape:`box`,size:t},position:n,...i?{rotation:i}:{}},children:[{name:`Skin`,type:`MeshInstance3D`,props:{mesh:`box`,size:t,...r}}]}}function Qj(e,t,n,r,i,a){let o=Q(r.range(i[0],i[1])),s=Q(r.range(.5,.7));return{name:`Rock${e}`,type:`MeshInstance3D`,props:{mesh:`sphere`,size:[1,1,1],position:[t,Q(o*s*.6),n],rotation:[0,r.int(0,359),0],scale:[o,Q(o*s),Q(o*r.range(.8,1.1))],material:{color:a??$j(r),roughness:1},castShadow:!0}}}function $j(e){let t=Math.round(e.range(110,160)).toString(16).padStart(2,`0`);return`#${t}${t}${t}`}function eM(e){return[{name:`Sun`,type:`DirectionalLight3D`,props:{position:[Q(e*.8),Q(e*1.5),Q(e*.6)],intensity:1,castShadow:!0,shadowArea:Q(e*1.2)}},{name:`FillLight`,type:`DirectionalLight3D`,props:{position:[Q(-e*.8),Q(e*.8),Q(-e*.6)],intensity:.4,color:`#b9d4ff`}}]}function tM(e,t){return e===void 0?t:typeof e==`number`?[e,e]:e}function nM(e,t,n){return Math.min(Math.max(e,t),n)}var rM=[`boxes`,`ruins`,`garden`],iM=.5,aM=.1,oM=2,sM={boxes:{floor:`#3f3f3f`,wall:`#55504a`,obstacles:[`#b0413e`,`#5b8266`,`#3e6990`,`#a26b38`,`#6d5a96`,`#878787`]},ruins:{floor:`#7d766b`,wall:`#8a8378`,obstacles:[`#8a8378`,`#979085`,`#a39a8d`,`#7b746a`]},garden:{floor:`#4d7c3a`,wall:`#2f6b2f`,obstacles:[`#2f6b2f`,`#3a7a38`,`#356e33`]}};function cM(e){let{seed:t,width:n=30,depth:r=30,wallHeight:i=3,obstacles:a=8,theme:o=`boxes`}=e;if(!rM.includes(o))throw new y(`BAD_FORMAT`,`generateArena theme must be one of [${rM.join(`, `)}], got '${o}'.`,{prop:`theme`,validOptions:[...rM]});let s=sM[o],c=new b(t),l=[Zj(`Floor`,[n,aM,r],[0,-.1/2,0],{material:{color:s.floor,roughness:1},receiveShadow:!0})],u=i/2,d=[n+iM*2,i,iM],f=[iM,i,r],p={material:{color:s.wall,roughness:.9},receiveShadow:!0};l.push(Zj(`Wall1`,d,[0,u,-(r+iM)/2],p),Zj(`Wall2`,d,[0,u,(r+iM)/2],p),Zj(`Wall3`,f,[-(n+iM)/2,u,0],p),Zj(`Wall4`,f,[(n+iM)/2,u,0],p)),o===`ruins`?l.push(...uM(c,s,n,r,i,a)):l.push(...lM(c,s,n,r,i,a,o)),o===`garden`&&l.push(...dM(c,n,r));let m=Math.max(n,r);return l.push({name:`Sun`,type:`DirectionalLight3D`,props:{position:[Q(m*.8),Q(m*1.5),Q(m*.6)],intensity:1,castShadow:!0,shadowArea:Q(m*1.2)}},{name:`FillLight`,type:`DirectionalLight3D`,props:{position:[Q(-m*.8),Q(m*.8),Q(-m*.6)],intensity:.4,color:`#b9d4ff`}},{name:`Lamp`,type:`OmniLight3D`,props:{position:[0,Q(i+2),0],intensity:.5,color:`#fff3d6`,range:Q(m)}}),{name:`Arena`,type:`Node3D`,children:l}}function lM(e,t,n,r,i,a,o){let s=[],c=o===`garden`?Math.min(n,r)*.16:0;for(let o=1;o<=a;o++){let a=[Q(e.range(.8,2.6)),Q(e.range(.8,Math.max(1.2,i*.8))),Q(e.range(.8,2.6))],l=Q(e.range(-(n/2-oM),n/2-oM)),u=Q(e.range(-(r/2-oM),r/2-oM));if(c>0&&Math.hypot(l,u)<c+1.5){let t=Math.max(Math.hypot(l,u),.001);l=Q(l/t*(c+1.5+e.range(0,2))),u=Q(u/t*(c+1.5+e.range(0,2)))}let d=e.int(0,359);s.push(Zj(`Obstacle${o}`,a,[l,Q(a[1]/2),u],{material:{color:e.pick(t.obstacles),roughness:.8},castShadow:!0},[0,d,0]))}return s}function uM(e,t,n,r,i,a){let o=[];if(a<=0)return o;let s=Math.max(1,Math.round(Math.sqrt(a/2))),c=Math.ceil(a/s),l=n-oM*2,u=r-oM*2,d=0;for(let n=0;n<s&&d<a;n++){let r=Q(s===1?0:-u/2+n/(s-1)*u);for(let n=0;n<c&&d<a;n++){d++;let a=Q((c===1?0:-l/2+n/(c-1)*l)+e.range(-.4,.4)),s=Q(e.next()>.35?e.range(i*.7,i*1.2):e.range(.4,.9)),u=Q(e.range(.8,1.2));o.push(Zj(`Obstacle${d}`,[u,s,u],[a,Q(s/2),Q(r+e.range(-.4,.4))],{material:{color:e.pick(t.obstacles),roughness:.95},castShadow:!0},[0,e.int(-8,8),0]))}}return o}function dM(e,t,n){let r=[],i=Math.min(t,n)*.16,a=r=>{let a=Math.min(t,n)/2-r/2-1,o=Q(e.range(-a,a)),s=Q(e.range(-a,a)),c=Math.max(Math.hypot(o,s),.001);return c<i+r/2&&(o=Q(o/c*(i+r/2+.5)),s=Q(s/c*(i+r/2+.5))),[o,s]};for(let i=1;i<=3;i++){let o=Q(Math.min(t,n)*e.range(.18,.26)),[s,c]=a(o);r.push({name:`Grass${i}`,type:`Foliage3D`,props:{kind:`grass`,area:[o,o],density:10,seed:e.int(1,1e9),position:[s,0,c]}})}for(let i=1;i<=2;i++){let o=Q(Math.min(t,n)*e.range(.12,.18)),[s,c]=a(o);r.push({name:`FlowerBed${i}`,type:`Flowers3D`,props:{density:`lush`,clustering:.3,area:[o,o],seed:e.int(1,1e9),position:[s,0,c]}})}return r.push({name:`Pool`,type:`Water3D`,props:{size:[Q(i*2),Q(i*2)],position:[0,.3,0],waveHeight:.04}}),r}var fM=32,pM=[4,8],mM=`#332f3a`,hM=`#6b6357`;function gM(e){let{seed:t,rooms:n=5}=e,[r,i]=tM(e.size,[960,720]),a=Math.max(8,Math.floor(r/fM)),o=Math.max(8,Math.floor(i/fM)),s=new b(t),c=[];for(let e=0;e<n*12&&c.length<n;e++){let e=s.int(pM[0],pM[1]),t=s.int(pM[0],pM[1]),n={x:s.int(1,Math.max(1,a-e-1)),y:s.int(1,Math.max(1,o-t-1)),w:e,h:t};c.some(e=>_M(e,n,1))||c.push(n)}let l=new Set,u=e=>{for(let t=e.y;t<e.y+e.h;t++)for(let n=e.x;n<e.x+e.w;n++)l.add(`${n},${t}`)};for(let e of c)u(e);let d=[];for(let e=1;e<c.length;e++){let[t,n]=vM(c[e-1]),[r,i]=vM(c[e]),a={x:Math.min(t,r),y:n,w:Math.abs(t-r)+1,h:1},o={x:r,y:Math.min(n,i),w:1,h:Math.abs(n-i)+1};for(let[t,n]of[[`H`,a],[`V`,o]])u(n),(n.w>1||n.h>1)&&d.push({name:`Corridor${e}${t}`,rect:n})}let f=new Set;for(let e of l){let[t,n]=e.split(`,`).map(Number);for(let e=-1;e<=1;e++)for(let r=-1;r<=1;r++){let i=`${t+r},${n+e}`;l.has(i)||f.add(i)}}let p=-(a*fM)/2,m=-(o*fM)/2,h=(e,t,n)=>({name:e,type:`ColorRect2D`,props:{position:[p+(t.x+t.w/2)*fM,m+(t.y+t.h/2)*fM],size:[t.w*fM,t.h*fM],color:n}}),g=c.map((e,t)=>h(`Room${t+1}`,e,mM));for(let e of d)g.push(h(e.name,e.rect,mM));let _=0;for(let e=-1;e<=o;e++){let t=-1;for(;t<=a;){if(!f.has(`${t},${e}`)){t++;continue}let n=1;for(;t+n<=a&&f.has(`${t+n},${e}`);)n++;_++;let r=[n*fM,fM];g.push({name:`Wall${_}`,type:`StaticBody2D`,props:{position:[p+(t+n/2)*fM,m+(e+.5)*fM],collider:{shape:`rect`,size:r}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:r,color:hM}}]}),t+=n}}return{name:`Dungeon`,type:`Node2D`,children:g}}function _M(e,t,n){return e.x-n<t.x+t.w&&e.x+e.w+n>t.x&&e.y-n<t.y+t.h&&e.y+e.h+n>t.y}function vM(e){return[Math.floor(e.x+e.w/2),Math.floor(e.y+e.h/2)]}var yM=[[0,-1],[1,0],[0,1],[-1,0]];function bM(e,t,n){let r=2*t+1,i=2*n+1,a=Array.from({length:i},()=>Array(r).fill(!1)),o=(e,t)=>{a[t][e]=!0};o(1,1);let s=new Set([`0,0`]),c=[[0,0]];for(;c.length>0;){let[r,i]=c[c.length-1],a=[];for(let[e,o]of yM){let c=r+e,l=i+o;c>=0&&c<t&&l>=0&&l<n&&!s.has(`${c},${l}`)&&a.push([c,l])}if(a.length===0){c.pop();continue}let[l,u]=e.pick(a);s.add(`${l},${u}`),o(2*l+1,2*u+1),o(r+l+1,i+u+1),c.push([l,u])}return o(0,1),o(2*t,2*n-1),{cols:t,rows:n,cells:a}}var xM=[`stone`,`hedge`,`canyon`],SM=.1,CM=`https://agent8-games.verse8.io/assets/3D/default/textures/wall`,wM=`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,TM={stone:{wall:{color:`#e8e2d8`,map:`${CM}/blocks.png`,normalMap:`${CM}/blocks_normal.png`,tile:2,roughness:.95},floor:{color:`#99938a`,map:`${wM}/stone.png`,normalMap:`${wM}/stone_normal.png`,tile:3,roughness:1},cap:`#6b5848`,pillar:`#cfc8bb`,path:`#665f55`,sun:{color:`#c9d6ea`,intensity:.75,height:.5},fill:`#9fb4cc`,mood:{sky:{elevationDeg:10,azimuthDeg:150,turbidity:16,rayleigh:3.2},fog:{near:.5,far:3.5,color:`#86909c`},exposure:.82,ambient:{color:`#c9d4e2`,intensity:.12}}},hedge:{wall:{color:`#55a83e`,map:`${wM}/grass.png`,normalMap:`${wM}/grass_normal.png`,tile:1.4,roughness:1},floor:{color:`#86b06d`,map:`${wM}/grass.png`,normalMap:`${wM}/grass_normal.png`,tile:3,roughness:1},pillar:`#3d7531`,path:`#7d6845`,sun:{color:`#e9eee6`,intensity:.7,height:1},fill:`#b9c8b4`,mood:{sky:{elevationDeg:35,azimuthDeg:150,turbidity:18,rayleigh:4.2},fog:{near:.8,far:5,color:`#aab8a6`},exposure:.88,ambient:{color:`#dde5d8`,intensity:.15}}},canyon:{wall:{color:`#f0b070`,map:`${wM}/stone.png`,normalMap:`${wM}/stone_normal.png`,tile:2.4,roughness:1},floor:{color:`#e3c193`,map:`${wM}/sand.png`,normalMap:`${wM}/sand_normal.png`,tile:3.5,roughness:1},pillar:`#d8a868`,path:`#a98a58`,sun:{color:`#ffb572`,intensity:1.15,height:.35},fill:`#caa37e`,mood:{sky:{elevationDeg:9,azimuthDeg:230,turbidity:9,rayleigh:3.5},fog:{near:.7,far:4.5,color:`#c79c6e`},exposure:.92,ambient:{color:`#ffdcb6`,intensity:.13}}}};function EM(e,t,n){return{color:e.color,roughness:e.roughness,map:e.map,...e.normalMap?{normalMap:e.normalMap}:{},repeat:[Q(t/e.tile),Q(n/e.tile)]}}var DM=10;function OM(e){let{seed:t,width:n=8,depth:r=8,cellSize:i=2,wallHeight:a=2.5,theme:o=`stone`}=e;if(!xM.includes(o))throw new y(`BAD_FORMAT`,`generateMaze theme must be one of [${xM.join(`, `)}], got '${o}'.`,{prop:`theme`,validOptions:[...xM]});let s=TM[o],c=new b(t),l=bM(c,n,r),u=2*n+1,d=2*r+1,f=Q(u*i),p=Q(d*i),m=(e,t)=>[Q((e+.5)*i-f/2),Q((t+.5)*i-p/2)],h=[Zj(`Floor`,[f,SM,p],[0,-.1/2,0],{material:EM(s.floor,f,p),receiveShadow:!0})],g=[],_=0;for(let e=0;e<d;e++){let t=0;for(;t<u;){if(l.cells[e]?.[t]){t++;continue}let n=1;for(;t+n<u&&!l.cells[e]?.[t+n];)n++;g.push({gx:t,gz:e,run:n}),_++;let r=Q(n*i);h.push(Zj(`Wall${_}`,[r,a,i],[Q((t+n/2)*i-f/2),Q(a/2),Q((e+.5)*i-p/2)],{material:EM(s.wall,r,a),castShadow:!0,receiveShadow:!0})),t+=n}}return s.cap&&h.push(...kM(g,i,a,f,p,s.cap)),h.push(...AM(c,l,i,a,m,s)),o===`hedge`?(h.push(...PM(c,g,i,a,m)),h.push(...FM(c,l,i,m,n,r))):o===`canyon`&&h.push(...IM(c,g,i,a,m)),h.push(...MM(l,i,a,m,s)),h.push(...eM(Math.max(f,p)).map((e,t)=>{if(t!==0)return{...e,props:{...e.props,color:s.fill}};let n=e.props?.position;return{...e,props:{...e.props,color:s.sun.color,intensity:s.sun.intensity,position:[n[0]??0,Q((n[1]??0)*s.sun.height),n[2]??0]}}})),{name:`Maze`,type:`Node3D`,children:h}}function kM(e,t,n,r,i,a){return e.map((e,o)=>({name:`Cap${o+1}`,type:`MeshInstance3D`,props:{mesh:`box`,size:[Q(e.run*t+.16),.12,Q(t+.16)],position:[Q((e.gx+e.run/2)*t-r/2),Q(n+.06),Q((e.gz+.5)*t-i/2)],material:{color:a,roughness:1},castShadow:!0,receiveShadow:!0}}))}function AM(e,t,n,r,i,a){let o=[],s=(e,n)=>t.cells[n]?.[e]===!1;for(let e=2;e<t.cells.length-1;e+=2)for(let n=2;n<(t.cells[e]?.length??0)-1;n+=2)s(n,e)&&Number(s(n-1,e))+Number(s(n+1,e))+Number(s(n,e-1))+Number(s(n,e+1))>=3&&o.push([n,e]);let c=Math.min(DM,o.length),l=[],u=new Set,d=Q(n*1.2),f=Q(r*1.12);for(let t=1;t<=c;t++){let n=e.int(0,o.length-1);for(;u.has(n);)n=(n+1)%o.length;u.add(n);let[r,s]=o[n],[c,p]=i(r,s);l.push(jM(`Pillar${t}`,c,p,d,f,a))}return l}function jM(e,t,n,r,i,a){return{name:e,type:`MeshInstance3D`,props:{mesh:`box`,size:[r,i,r],position:[t,Q(i/2),n],material:{...EM(a.wall,r,i),color:a.pillar},castShadow:!0,receiveShadow:!0}}}function MM(e,t,n,r,i){let a=2*e.cols,o=2*e.rows-1,s=Q(t*1.1),c=Q(n*1.25),l=[[0,0],[0,2],[a,o-1],[a,o+1]].map(([e,t],n)=>{let[a,o]=r(e,t);return jM(`Gate${n+1}`,a,o,s,c,i)});for(let[e,n,s]of[[`EntrancePath`,0,1],[`ExitPath`,a,o]]){let[a,o]=r(n,s);l.push({name:e,type:`MeshInstance3D`,props:{mesh:`box`,size:[Q(t*.96),.04,Q(t*.96)],position:[a,.02,o],material:{...EM(i.floor,t,t),color:i.path},receiveShadow:!0}})}return l}var NM=10;function PM(e,t,n,r,i){return[...t].filter(e=>e.run>=2).sort((e,t)=>t.run-e.run||e.gz-t.gz||e.gx-t.gx).slice(0,NM).map((t,a)=>{let[,o]=i(t.gx,t.gz),[s]=i(t.gx,t.gz),[c]=i(t.gx+t.run-1,t.gz);return{name:`HedgeTop${a+1}`,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,area:[Q(t.run*n*.92),Q(n*.7)],density:14,height:.35,sway:.4,colorA:`#2f5e26`,colorB:`#5d8a3c`,seed:e.int(1,1e9),position:[Q((s+c)/2),r,o]}}})}function FM(e,t,n,r,i,a){let o=[];for(let e=0;e<t.cells.length;e++)for(let n=0;n<(t.cells[e]?.length??0);n++)t.cells[e]?.[n]&&o.push([n,e]);let s=Math.min(o.length,Math.max(3,Math.floor(i*a/12))),c=[],l=new Set;for(let t=1;t<=s&&l.size<o.length;t++){let i=e.int(0,o.length-1);for(;l.has(i);)i=(i+1)%o.length;l.add(i);let[a,s]=o[i],[u,d]=r(a,s),f=Q(n*.8);c.push({name:`Grass${t}`,type:`Foliage3D`,props:{kind:`grass`,area:[f,f],density:8,seed:e.int(1,1e9),position:[u,0,d]}})}return c}function IM(e,t,n,r,i){let a=[];if(t.length===0)return a;let o=Math.min(8,t.length);for(let s=1;s<=o;s++){let o=e.pick(t),[c,l]=i(o.gx+e.int(0,o.run-1),o.gz),u=Qj(s,c,l,e,[.3,Q(n*.35)],`#8f7355`),d=u.props?.position;d[1]=Q(d[1]+r),a.push(u)}return a}var LM=`#23222b`,RM=`#5f6672`;function zM(e){let{seed:t,cols:n=10,rows:r=8,cellPx:i=64}=e,a=bM(new b(t),n,r),o=2*n+1,s=2*r+1,c=Q(o*i),l=Q(s*i),u=[{name:`Floor`,type:`ColorRect2D`,props:{size:[c,l],color:LM}}],d=0;for(let e=0;e<s;e++){let t=0;for(;t<o;){if(a.cells[e]?.[t]){t++;continue}let n=1;for(;t+n<o&&!a.cells[e]?.[t+n];)n++;d++;let r=[Q(n*i),i];u.push({name:`Wall${d}`,type:`StaticBody2D`,props:{position:[Q((t+n/2)*i-c/2),Q((e+.5)*i-l/2)],collider:{shape:`rect`,size:r}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:r,color:RM}}]}),t+=n}}return{name:`Maze2D`,type:`Node2D`,children:u}}var BM=16,VM=[`#5b8266`,`#3e6990`,`#a26b38`,`#6d5a96`,`#b0413e`];function HM(e){let{seed:t,count:n=10,width:r=[80,160],gapX:i=[40,120],stepY:a=[-80,40],start:o=[0,300]}=e,s=new b(t),c=[],l=Q(s.range(r[0],r[1])),u=o[0],d=o[1];for(let e=1;e<=n&&(c.push(UM(e,u,d,l,s.pick(VM))),e!==n);e++){let e=Q(s.range(r[0],r[1])),t=Q(s.range(i[0],i[1]));u=Q(u+l/2+t+e/2),d=Q(d+s.range(a[0],a[1])),l=e}return{name:`Platforms`,type:`Node2D`,children:c}}function UM(e,t,n,r,i){return{name:`Platform${e}`,type:`StaticBody2D`,props:{position:[t,n],collider:{shape:`rect`,size:[r,BM]}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:[r,BM],color:i}}]}}var WM=[3,5],GM=3,KM={color:`#ffffff`,roughness:1,emissive:`#ffffff`,emissiveIntensity:.25};function qM(e){let{seed:t,count:n=8,altitude:r=18}=e,[i,a]=tM(e.area,[60,60]),o=new b(t),s=[];for(let e=1;e<=n;e++){let t=o.int(WM[0],WM[1]),n=[];for(let e=1;e<=t;e++){let r=Q(o.range(1,2.2));n.push({name:`Puff${e}`,type:`MeshInstance3D`,props:{mesh:`sphere`,size:[1,1,1],position:[Q((e-(t+1)/2)*o.range(1,1.6)),Q(o.range(-.3,.3)),Q(o.range(-.6,.6))],scale:[Q(r*o.range(1.1,1.6)),Q(r*.55),r],material:KM}})}s.push({name:`Cloud${e}`,type:`Node3D`,props:{position:[Q(o.range(-i/2,i/2)),Q(r+o.range(-3,GM)),Q(o.range(-a/2,a/2))]},children:n})}return{name:`Clouds`,type:`Node3D`,children:s}}var JM=[`island`,`alpine`,`plains`,`desert`,`meadow`,`forest`,`savanna`,`snow`,`wetland`,`volcanic`],YM=128,XM=20,ZM=.8,QM=.12,$M={island:{splat:`island`,maxHeight:4.5,sun:`#fff4d6`,fill:`#b9d4ff`,sky:{elevationDeg:38,azimuthDeg:145,turbidity:2.6,rayleigh:1.1},fog:{near:1,far:4},iblIntensity:.72},alpine:{splat:`alpine`,maxHeight:8,roughness:.65,detail:5,sun:`#f4f7ff`,fill:`#c9d8f2`,sky:{elevationDeg:45,azimuthDeg:35,turbidity:1.4,rayleigh:1.3},fog:{near:1.8,far:6.5},sunIntensity:1.1,exposure:.92,iblIntensity:.72},plains:{splat:`plains`,maxHeight:4,sun:`#fff2cf`,fill:`#bcd3ef`,sky:{elevationDeg:36,azimuthDeg:140,turbidity:2.4,rayleigh:1},fog:{near:.9,far:4},iblIntensity:.58},desert:{splat:`desert`,maxHeight:5,sun:`#ffe3b3`,fill:`#e8c9a6`,sky:{elevationDeg:42,azimuthDeg:160,turbidity:7,rayleigh:.6},fog:{near:.8,far:3.2,color:`#e8d3ae`},sunIntensity:1.35,iblIntensity:.75},meadow:{splat:`grassland`,maxHeight:1.2,sun:`#fff8e2`,fill:`#bfe0c9`,sky:{elevationDeg:55,azimuthDeg:125,turbidity:2.4,rayleigh:.95},fog:{near:1,far:4.4},sunIntensity:2.6,exposure:1.12,iblIntensity:.62},forest:{splat:`forest`,maxHeight:2.5,sun:`#ffdca8`,fill:`#a9c8b4`,sky:{elevationDeg:29,azimuthDeg:120,turbidity:5.5,rayleigh:1},fog:{near:.22,far:1.8,color:`#9fb494`},sunIntensity:2.6,ambient:.26,iblIntensity:.55},savanna:{splat:`savanna`,maxHeight:3,sun:`#ffdca0`,fill:`#e6d2a4`,sky:{elevationDeg:34,azimuthDeg:150,turbidity:5,rayleigh:.7},fog:{near:1,far:4.2,color:`#e3cf9f`},sunIntensity:2,exposure:1.05,iblIntensity:.6},snow:{splat:`snow`,maxHeight:2.2,sun:`#dfe9ff`,fill:`#c2d2f0`,sky:{elevationDeg:22,azimuthDeg:35,turbidity:1.6,rayleigh:1.6},fog:{near:1.2,far:5,color:`#dbe6f5`},sunIntensity:1,exposure:.9,iblIntensity:.72},wetland:{splat:`wetland`,maxHeight:1.4,sun:`#d6ddc8`,fill:`#9fb29a`,sky:{elevationDeg:24,azimuthDeg:115,turbidity:9,rayleigh:1.1},fog:{near:.5,far:2,color:`#92a288`},sunIntensity:1.5,exposure:.94,ambient:.24,iblIntensity:.66},volcanic:{splat:`volcanic`,maxHeight:4,roughness:.7,sun:`#ff8a4a`,fill:`#7a4a3a`,sky:{elevationDeg:14,azimuthDeg:135,turbidity:10,rayleigh:.3},fog:{near:.18,far:1.4,color:`#2a211c`},sunIntensity:1.7,exposure:.86,ambient:.22,iblIntensity:.5}};function eN(e){let{seed:t,theme:n=`island`,size:r=200,water:i=!1}=e,a=$M[n];if(!a)throw new y(`BAD_FORMAT`,`generateTerrain theme must be one of [${JM.join(`, `)}], got '${n}'.`,{prop:`theme`,validOptions:[...JM]});let o=e.maxHeight||a.maxHeight,s=new b(t),c=n===`island`,l=e=>Fx({width:r,depth:r,segsX:YM,segsZ:YM,maxHeight:e,seed:t,...a.roughness===void 0?{}:{roughness:a.roughness},...a.detail===void 0?{}:{detail:a.detail},islandEdge:c}),u=l(o);if(c)for(let e=0;e<3;e++){let e=nN(u)-XM,t=u.maxHeight-u.minHeight,n=u.minHeight+QM*t;if(e+ZM<=n)break;let r=XM-ZM,i=nN(u)-u.minHeight-QM*t;o=Q(o*Math.min(r/i*.95,.9)),u=l(o)}let d=[{name:`Ground`,type:`StaticBody3D`,props:{collider:{shape:`heightfield`}},children:[{name:`Surface`,type:`Terrain3D`,props:{size:[r,r],maxHeight:o,seed:t,theme:a.splat,...a.roughness===void 0?{}:{roughness:a.roughness},...a.detail===void 0?{}:{detail:a.detail}}}]}],f=n===`wetland`;if(c)d.push({name:`Sea`,type:`Water3D`,props:{size:[r*8,r*8],position:[0,tN(u),0],opacity:1}});else if(f){let e=u.maxHeight-u.minHeight||1,t=Q(u.minHeight+.22*e);d.push({name:`Swamp`,type:`Water3D`,props:{size:[r,r],position:[0,t,0],waveHeight:.02,quality:`simple`,color:`#3a4a30`,opacity:.95}})}else if(i){let e=Q(u.minHeight+.1*(u.maxHeight-u.minHeight));d.push({name:`Lake`,type:`Water3D`,props:{size:[r,r],position:[0,e,0],waveHeight:.04}})}return d.push(...vN(n,s,u,r)),c&&d.push(qM({seed:s.int(1,1e9),count:6,area:r,altitude:Math.round(u.maxHeight+12)})),d.push(...eM(r).map((e,t)=>yN(e,t===0?a.sun:a.fill,t===0?a.sunIntensity??1.7:void 0))),{name:`Terrain`,type:`Node3D`,children:d}}function tN(e){let t=nN(e)-XM,n=e.minHeight+QM*(e.maxHeight-e.minHeight);return Q(Math.max(Math.min(t+ZM,n),t+.55))}function nN(e){let t=-1/0,n=e.width/2,r=e.depth/2;for(let i=0;i<=YM;i++){let a=-n+i/YM*e.width,o=-r+i/YM*e.depth;t=Math.max(t,e.baseHeight(a,-r),e.baseHeight(a,r),e.baseHeight(-n,o),e.baseHeight(n,o))}return t}function rN(e,t,n){let r=Math.min(t.width/2-n.margin,n.within??1/0),i=t.maxHeight-t.minHeight||1,a=[];for(let o=0;o<n.count*30&&a.length<n.count;o++){let o=Q(e.range(-r,r)),s=Q(e.range(-r,r));if(n.clearing&&Math.hypot(o,s)<n.clearing||n.within&&Math.hypot(o,s)>n.within)continue;let c=t.heightAt(o,s),l=(c-t.minHeight)/i;l<n.band[0]||l>n.band[1]||t.slopeAt(o,s)>n.maxSlope||a.push({x:o,z:s,y:c})}return a}var iN=[{canopy:`#2f5d44`,trunk:`#6e4a32`},{canopy:`#356a4c`,trunk:`#71503a`},{canopy:`#2c5740`,trunk:`#5f4530`},{canopy:`#3a6b4a`,trunk:`#6a4c34`}],aN=[{canopy:`#4a7c3f`,trunk:`#7a5a3a`},{canopy:`#56883c`,trunk:`#806044`},{canopy:`#7a9d3e`,trunk:`#9a9488`},{canopy:`#86a346`,trunk:`#a39c8e`},{canopy:`#b8862f`,trunk:`#7e5e38`},{canopy:`#a8702c`,trunk:`#74552f`}],oN={canopy:`#9aa052`,trunk:`#8a6a44`},sN={canopy:`#39513f`,trunk:`#5a5650`};function cN(e,t){return e===`conifer`?t.pick(iN):e===`broadleaf`?t.pick(aN):null}function lN(e,t,n,r,i){let a=i?.height??[4.5,7],o=i?.sink??(i?.count===void 0?.05:.3),s={};i?.tier!==void 0&&(s.tier=i.tier),i?.count!==void 0&&i.area!==void 0&&(s.count=i.count,s.area=[i.area,i.area]);let c=cN(r,n),l=i?.palette??c;return l&&(s.canopyColor=l.canopy,s.trunkColor=l.trunk),{name:e,type:`Tree3D`,props:{type:r,seed:n.int(1,1e9),height:Q(n.range(a[0],a[1])),position:[t.x,Q(t.y-o),t.z],...s}}}function uN(e,t,n,r,i,a=0,o){return{name:e,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,area:[r,r],density:i,height:o?.height??.3,...o?.colors?{colorA:o.colors[0],colorB:o.colors[1]}:{},seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z],...a>0?{flowers:a}:{}}}}function dN(e,t,n,r,i){return{name:e,type:`Foliage3D`,props:{kind:`reeds`,style:`simple`,area:[r,r],density:i,height:.9,colorA:`#2f4a26`,colorB:`#5a6f33`,seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z]}}}function fN(e,t,n,r,i){return{name:e,type:`Flowers3D`,props:{density:i,area:[r,r],seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z]}}}function pN(e,t,n,r){return e.map((e,i)=>{let a=Qj(i+1,e.x,e.z,t,n,r?.(t)),o=a.props?.position;return o[1]=Q(o[1]+e.y),a})}function mN(e){let t=Math.round(e.range(104,128)),n=Math.round(t-e.range(10,18)),r=Math.round(t-e.range(20,30)),i=e=>e.toString(16).padStart(2,`0`);return`#${i(n)}${i(t)}${i(r)}`}function hN(e){let t=Math.round(e.range(196,224)),n=Math.min(255,t+Math.round(e.range(4,12))),r=e=>e.toString(16).padStart(2,`0`);return`#${r(t)}${r(t)}${r(n)}`}function gN(e){let t=Math.round(e.range(34,56)),n=Math.min(255,t+Math.round(e.range(2,8))),r=e=>e.toString(16).padStart(2,`0`);return`#${r(n)}${r(t)}${r(t)}`}var _N=[`#6f5b41`,`#7a644a`,`#665439`];function vN(e,t,n,r){let i=[];switch(e){case`island`:{let e=rN(t,n,{count:7,band:[.18,.6],maxSlope:.5,margin:26});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`conifer`)));break}case`alpine`:{let e=rN(t,n,{count:10,band:[.2,.5],maxSlope:.55,margin:6});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`conifer`)));let r=rN(t,n,{count:8,band:[.55,1],maxSlope:.9,margin:6});i.push(...pN(r,t,[.6,1.8]));break}case`plains`:{let e=rN(t,n,{count:8,band:[0,1],maxSlope:.4,margin:6});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`broadleaf`)));let r=rN(t,n,{count:6,band:[0,1],maxSlope:.5,margin:6});i.push(...pN(r,t,[.4,1.2]));break}case`desert`:{let e=rN(t,n,{count:6,band:[0,1],maxSlope:.45,margin:6});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`dead`)));let r=rN(t,n,{count:8,band:[0,1],maxSlope:.6,margin:6});i.push(...pN(r,t,[.5,1.6]));break}case`meadow`:{let e=Q(r*.09),a=rN(t,n,{count:7,band:[0,1],maxSlope:.05,margin:e/2+8});i.push(...a.map((n,r)=>uN(`Carpet${r+1}`,n,t,e,30)));let o=Q(r*.07),s=rN(t,n,{count:3,band:[0,1],maxSlope:.05,margin:o/2+8});i.push(...s.map((e,n)=>fN(`Flowers${n+1}`,e,t,o,`sparse`)));let c=rN(t,n,{count:4,band:[0,1],maxSlope:.1,margin:12});i.push(...c.map((e,n)=>lN(`Grove${n+1}`,e,t,`broadleaf`,{count:3,area:6})));let l=rN(t,n,{count:6,band:[0,1],maxSlope:.2,margin:8});i.push(...pN(l,t,[.3,.9]));break}case`forest`:{let e=Q(r*.12),a=r/2-8,o=et(t.int(1,1e9)),s=(e,t,n)=>{let r=o(e/70,t/70);return r>.12?`conifer`:r<-.12?`broadleaf`:n%2==0?`conifer`:`broadleaf`},c=rN(t,n,{count:40,band:[0,1],maxSlope:.18,margin:8,clearing:e+6}),l=c.map((e,t)=>s(e.x,e.z,t));i.push(...c.map((e,n)=>lN(`Grove${n+1}`,e,t,l[n],{count:12,area:13,height:[5.5,8]}))),c.forEach((e,n)=>{n%3==0&&i.push(lN(`Sapling${n+1}`,e,t,l[n],{count:4,area:19,height:[2.5,3.4],sink:.12}))});let u=rN(t,n,{count:6,band:[0,1],maxSlope:.2,margin:12,clearing:e+4});i.push(...u.map((e,n)=>lN(`Elder${n+1}`,e,t,s(e.x,e.z,n),{tier:`high`,height:[8.4,9.8]})));let d=rN(t,n,{count:3,band:[0,1],maxSlope:.18,margin:10,clearing:e+6});i.push(...d.map((e,n)=>lN(`Accent${n+1}`,e,t,`broadleaf`,{tier:`high`,count:3,area:7,height:[5.6,6.8]})));let f=rN(t,n,{count:10,band:[0,1],maxSlope:.14,margin:9,clearing:e+2});i.push(...f.map((e,n)=>lN(`Bush${n+1}`,e,t,`bush`,{count:4,area:10,height:[2.1,3.1],sink:.12})));let p=0;c.forEach((e,r)=>{if(r%3==2)return;let o=t.range(0,Math.PI*2),s=t.range(2,4.5),c=t.int(1,1e9),l=Q(nM(e.x+Math.cos(o)*s,-a,a)),u=Q(nM(e.z+Math.sin(o)*s,-a,a));n.slopeAt(l,u)>.09||(p++,i.push({name:`Fern${p}`,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,tuftStyle:`fern`,area:[8,8],density:9,height:.4,colorA:`#4a6b34`,colorB:`#82a258`,seed:c,position:[l,Q(n.heightAt(l,u)+.02),u]}}))});let m=Q(r*.08),h=rN(t,n,{count:5,band:[0,1],maxSlope:.06,margin:m/2+8});i.push(...h.map((e,n)=>uN(`Grass${n+1}`,e,t,m,20,0,{height:.24,colors:[`#4f7034`,`#85a154`]})));let g=u.length>0?t.int(3,5):0;for(let e=0;e<g;e++){let r=u[e%u.length],o=t.range(0,Math.PI*2),s=t.range(2.5,4.5),c=Q(nM(r.x+Math.cos(o)*s,-a,a)),l=Q(nM(r.z+Math.sin(o)*s,-a,a));i.push({name:`Log${e+1}`,type:`Tree3D`,props:{type:`dead`,seed:t.int(1,1e9),height:Q(t.range(4.2,5.6)),trunkColor:`#4a4236`,position:[c,Q(n.heightAt(c,l)+.12),l],rotation:[0,t.int(0,359),Q(t.range(81,97))]}})}rN(t,n,{count:5,band:[0,1],maxSlope:.25,margin:9,clearing:e}).forEach((e,n)=>{let r=Q(t.range(.16,.28)),a=Q(t.range(.3,.55));i.push({name:`Stump${n+1}`,type:`MeshInstance3D`,props:{mesh:`cylinder`,size:[r,a,r],position:[e.x,Q(e.y+a/2-.06),e.z],rotation:[0,t.int(0,359),0],material:{color:t.pick(_N),roughness:1},castShadow:!0}})});let _=rN(t,n,{count:8,band:[0,1],maxSlope:.2,margin:8});i.push(...pN(_,t,[.3,1],mN));let v=Q(e*.75),y=rN(t,n,{count:3,band:[0,1],maxSlope:.06,margin:8,within:e-Q(v/Math.SQRT2)});i.push(...y.map((e,n)=>uN(`Clearing${n+1}`,e,t,v,30,0,{colors:[`#5d8438`,`#a8bc60`]})));let b=Q(e*.45),x=rN(t,n,{count:2,band:[0,1],maxSlope:.06,margin:8,within:e-Q(b/Math.SQRT2)});i.push(...x.map((e,n)=>fN(`Flowers${n+1}`,e,t,b,`sparse`)));break}case`savanna`:{let e=rN(t,n,{count:7,band:[0,.85],maxSlope:.35,margin:8});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`broadleaf`,{height:[3.5,5],palette:oN})));let a=Q(r*.09),o=rN(t,n,{count:6,band:[0,1],maxSlope:.05,margin:a/2+8});i.push(...o.map((e,n)=>uN(`Carpet${n+1}`,e,t,a,26,0,{height:.34,colors:[`#9a8f43`,`#c9bd6a`]})));let s=rN(t,n,{count:7,band:[0,1],maxSlope:.5,margin:8});i.push(...pN(s,t,[.4,1.4]));let c=rN(t,n,{count:4,band:[0,1],maxSlope:.2,margin:9});i.push(...c.map((e,n)=>lN(`Scrub${n+1}`,e,t,`bush`,{count:3,area:8,height:[1.4,2.2]})));break}case`snow`:{let e=rN(t,n,{count:8,band:[0,.9],maxSlope:.4,margin:8});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`conifer`,{height:[4,6.5],palette:sN})));let r=rN(t,n,{count:10,band:[0,1],maxSlope:.7,margin:8});i.push(...pN(r,t,[.5,1.8],hN));break}case`wetland`:{let e=Q(r*.08),a=rN(t,n,{count:6,band:[0,.5],maxSlope:.06,margin:e/2+8});i.push(...a.map((n,r)=>dN(`Reeds${r+1}`,n,t,e,4)));let o=Q(r*.08),s=rN(t,n,{count:4,band:[.2,1],maxSlope:.05,margin:o/2+8});i.push(...s.map((e,n)=>uN(`Moss${n+1}`,e,t,o,22,0,{height:.22,colors:[`#3a5a2c`,`#6f8a48`]})));let c=rN(t,n,{count:6,band:[.25,1],maxSlope:.35,margin:9});i.push(...c.map((e,n)=>lN(`Snag${n+1}`,e,t,`dead`,{height:[4,6]})));let l=rN(t,n,{count:6,band:[.2,1],maxSlope:.2,margin:9});i.push(...l.map((e,n)=>lN(`Bush${n+1}`,e,t,`bush`,{count:3,area:7,height:[1.6,2.6]})));let u=rN(t,n,{count:5,band:[.2,1],maxSlope:.3,margin:8});i.push(...pN(u,t,[.3,1],mN));break}case`volcanic`:{let e=rN(t,n,{count:7,band:[0,1],maxSlope:.45,margin:8});i.push(...e.map((e,n)=>lN(`Tree${n+1}`,e,t,`dead`,{height:[4,6.5]})));let r=rN(t,n,{count:12,band:[0,1],maxSlope:.7,margin:8});i.push(...pN(r,t,[.4,1.8],gN)),rN(t,n,{count:3,band:[0,.6],maxSlope:.18,margin:12}).forEach((e,n)=>{t.int(1,1e9),i.push({name:`Smoke${n+1}`,type:`Particles3D`,props:{preset:`smoke`,position:[e.x,Q(e.y+.2),e.z],rate:8,maxParticles:64,colorStart:`#5a5048`,colorEnd:`#2a2422`,sizeStart:18,sizeEnd:44}}),i.push({name:`Embers${n+1}`,type:`Particles3D`,props:{position:[e.x,Q(e.y+.1),e.z],rate:10,maxParticles:48,lifetime:[.8,1.8],speed:[12,34],directionDeg:-90,spreadDeg:40,gravity:[0,-18],sizeStart:4,sizeEnd:1,colorStart:`#ffce6a`,colorEnd:`#d83a14`,blend:`add`}})});break}}return i}function yN(e,t,n){return{...e,props:{...e.props,color:t,...n===void 0?{}:{intensity:n}}}}var bN={arena:{description:`FPS stage: floor, 4 perimeter walls, obstacles, lights — themes: boxes (crates), ruins (broken stone rows), garden (hedges, grass, pool)`,dimension:`3d`,params:{theme:{type:`string`,default:`boxes`,options:[...rM]},width:{type:`number`,default:30,min:4},depth:{type:`number`,default:30,min:4},wallHeight:{type:`number`,default:3,min:.5},obstacles:{type:`number`,default:8,min:0}}},terrain:{description:`Heightfield world: StaticBody3D{heightfield} + Terrain3D + theme dressing (trees, rocks, grass, sea/clouds on island, broad swamp water on wetland, smoke/ember emitters on volcanic; maxHeight 0 = theme default; water adds a lake to non-island themes)`,dimension:`3d`,params:{theme:{type:`string`,default:`island`,options:[...JM]},size:{type:`number`,default:200,min:40,max:400},maxHeight:{type:`number`,default:0,min:0},water:{type:`boolean`,default:!1}}},maze:{description:`Recursive-backtracker 3D maze, west→east — themes: stone, hedge (green + grass), canyon (sandstone + rim rocks)`,dimension:`3d`,params:{theme:{type:`string`,default:`stone`,options:[...xM]},width:{type:`number`,default:8,min:2,max:40},depth:{type:`number`,default:8,min:2,max:40},cellSize:{type:`number`,default:2,min:.5},wallHeight:{type:`number`,default:2.5,min:.5}}},maze2d:{description:`The same maze algorithm as 2D ColorRect2D + StaticBody2D tiles`,dimension:`2d`,params:{cols:{type:`number`,default:10,min:2,max:40},rows:{type:`number`,default:8,min:2,max:40},cellPx:{type:`number`,default:64,min:8}}},dungeon2d:{description:`Roguelike rooms + L-corridors: floor rects, wall bodies (32px tiles)`,dimension:`2d`,params:{rooms:{type:`number`,default:5,min:1,max:20},size:{type:`number`,default:960,min:256}}},platforms2d:{description:`Left-to-right 2D platform course (tune ranges via the library)`,dimension:`2d`,params:{count:{type:`number`,default:10,min:1}}}},xN={arena:cM,terrain:eN,maze:OM,maze2d:zM,dungeon2d:gM,platforms2d:HM};function SN(e,t){let n=xN[e];if(!n){let t=Object.keys(xN);throw new y(`BAD_FORMAT`,`Unknown generator '${e}'. Valid: [${t.join(`, `)}] — the old meadow/forest/island/rocks/clouds generators became themes (e.g. terrain theme: 'meadow', arena theme: 'garden'); scatter is library-only (needs item templates).`,{validOptions:t})}return n(t)}function CN(e){return Object.entries(bN).filter(([,t])=>t.dimension===e).map(([e,t])=>({name:e,meta:t}))}function wN(e,t){if(e.type===`boolean`)return t===!0||t===`true`;if(e.type===`number`){let n=typeof t==`boolean`?NaN:Number(t);return(t===``||!Number.isFinite(n))&&(n=e.default),e.min!==void 0&&(n=Math.max(e.min,n)),e.max!==void 0&&(n=Math.min(e.max,n)),n}let n=String(t);return e.options&&!e.options.includes(n)?e.default:n}function TN(){return Math.floor(Math.random()*1e6)}var EN=[],DN=new Map,ON=null;function kN(e){let t=document.querySelector(`#generate`);t&&(MN(e),t.removeAttribute(`hidden`))}function AN(){document.querySelector(`#generate`)?.setAttribute(`hidden`,``)}function jN(e){let t=document.querySelector(`#generate`);t&&(t.addEventListener(`pointerdown`,e=>{e.target===t&&AN()}),document.querySelector(`#generate-close`)?.addEventListener(`click`,AN),document.querySelector(`#generate-cancel`)?.addEventListener(`click`,AN),document.querySelector(`#generate-insert`)?.addEventListener(`click`,()=>NN(e)))}function MN(e){let t=document.querySelector(`#generate-body`),n=document.querySelector(`#generate-status`);if(!t)return;n&&(n.textContent=``),t.textContent=``;let r=e.working.dimension??`2d`;EN=CN(r);let i=document.createElement(`p`);i.className=`gen-hint`,i.textContent=rj({en:`Deterministic ${r.toUpperCase()} environment generators — the subtree inserts under the selected node (the root when nothing is selected). The same seed always generates the same level.`,ko:`결정적 ${r.toUpperCase()} 환경 생성기 — 생성된 서브트리는 선택한 노드 아래에(선택이 없으면 루트에) 들어갑니다. 같은 시드는 항상 같은 레벨을 만듭니다.`}),t.appendChild(i);let a=PN(rj({en:`generator`,ko:`생성기`})),o=document.createElement(`select`);o.id=`generate-name`;for(let{name:e}of EN){let t=document.createElement(`option`);t.value=e,t.textContent=e,o.appendChild(t)}a.appendChild(o),t.appendChild(a);let s=document.createElement(`p`);s.className=`gen-desc`,t.appendChild(s);let c=document.createElement(`div`);c.id=`generate-params`,t.appendChild(c);let l=PN(`seed`);ON=document.createElement(`input`),ON.type=`number`,ON.step=`1`,ON.value=String(TN());let u=document.createElement(`button`);u.type=`button`,u.className=`ghost`,u.textContent=`↻`,u.title=rj({en:`New random seed`,ko:`새 랜덤 시드`}),u.addEventListener(`click`,()=>{ON&&(ON.value=String(TN()))});let d=document.createElement(`div`);d.className=`gen-seed-row`,d.append(ON,u),l.appendChild(d),t.appendChild(l);let f=()=>{let e=EN.find(e=>e.name===o.value)??EN[0];if(e){s.textContent=e.meta.description,c.textContent=``,DN=new Map;for(let[t,n]of Object.entries(e.meta.params)){let e=PN(t),r;if(n.type===`boolean`)r=document.createElement(`input`),r.type=`checkbox`,r.checked=n.default===!0;else if(n.type===`string`&&n.options){r=document.createElement(`select`);for(let e of n.options){let t=document.createElement(`option`);t.value=e,t.textContent=e,r.appendChild(t)}r.value=String(n.default)}else r=document.createElement(`input`),r.type=n.type===`number`?`number`:`text`,n.type===`number`&&(r.step=`any`,n.min!==void 0&&(r.min=String(n.min)),n.max!==void 0&&(r.max=String(n.max))),r.value=String(n.default),(n.min!==void 0||n.max!==void 0)&&(r.title=`${n.min??``}–${n.max??``}`);DN.set(t,r),e.appendChild(r),c.appendChild(e)}}};o.addEventListener(`change`,f),f()}function NN(e){let t=document.querySelector(`#generate-status`),n=document.querySelector(`#generate-name`),r=EN.find(e=>e.name===n?.value);if(!r||!ON)return;let i={seed:wN({type:`number`,default:TN(),min:0},ON.value)};for(let[e,t]of DN){let n=r.meta.params[e];n&&(i[e]=wN(n,t.type===`checkbox`?t.checked:t.value))}let a;try{a=SN(r.name,i)}catch(e){t&&(t.textContent=e instanceof Error?e.message:String(e));return}let o=e.insertNode(a,e.selection??[]);if(o===null){t&&(t.textContent=rj({en:`Insert failed — see the error banner.`,ko:`삽입 실패 — 에러 배너를 확인하세요.`}));return}e.select(o),ON&&(ON.value=String(TN())),AN()}function PN(e){let t=document.createElement(`label`);t.className=`field`;let n=document.createElement(`span`);return n.textContent=e,t.appendChild(n),t}var FN={groups:{title:{en:`groups — tag nodes for queries`,ko:`groups — 조회용 태그`},body:{en:`Free-form tags. Game code finds nodes with tree-wide queries like getNodesInGroup("coins"), and triggers can filter by group (e.g. only react to "player"). Type a name and press Enter.`,ko:`자유 형식 태그입니다. 게임 코드가 getNodesInGroup("coins")처럼 트리 전체에서 노드를 찾고, 트리거는 그룹으로 거릅니다(예: "player"에만 반응). 이름을 입력하고 Enter를 누르세요.`},example:`triggerEnter → if (other.isInGroup("player")) collect()`},script:{title:{en:`script — attach YOUR game logic`,ko:`script — 게임 로직 연결`},body:{en:`A Behavior is a TypeScript class living in YOUR game code, linked by name. The editor stores the link; the class itself must be registered in the game before loadScene. Props here are passed to the behavior instance.`,ko:`Behavior는 게임 코드에 있는 TypeScript 클래스이며 이름으로 연결됩니다. 에디터는 연결만 저장하고, 클래스 자체는 loadScene 전에 게임에서 등록되어야 합니다. 여기의 props가 비헤이비어 인스턴스로 전달됩니다.`},example:`registerBehavior('CoinCounter', CoinCounter) // in your main.ts`,copy:{label:`copy behavior boilerplate`,text:`import { Behavior, registerBehavior } from 'incanto';
|
|
8318
|
+
}`};var Xk=[`type`,`sunPosition`,`elevationDeg`,`azimuthDeg`,`turbidity`,`rayleigh`],Zk=[`color`,`near`,`far`],Qk=[`coverage`,`density`,`base`,`top`,`color`,`shadeColor`,`speed`,`scale`],$k=[`threshold`,`strength`],eA=[`vignette`,`saturation`,`contrast`],tA=[`mapSize`,`radius`,`static`],nA=[1024,2048],rA=2,iA=1,aA=50,oA=800,sA=`#cfd8e0`,cA=Math.PI/180;function lA(e){return{exposure:pA(e?.exposure),sky:mA(e?.sky),fog:hA(e?.fog,e?.sky!==void 0),clouds:gA(e?.clouds),bloom:_A(e?.bloom),post:vA(e?.post),shadows:yA(e?.shadows)}}function uA(e,t){let n=(90-e)*cA,r=t*cA;return[Math.sin(n)*Math.sin(r),Math.cos(n),Math.sin(n)*Math.cos(r)]}function dA(e){let[t,n,r]=e.sunPosition,i=Math.hypot(t,n,r)||1;return[t/i,n/i,r/i]}function fA(e){let t=[191,213,232],n=[233,228,217],r=[242,201,150],i=SA((e.turbidity-rA)/8),a=dA(e),o=SA((18-Math.asin(xA(a[1],-1,1))/cA)/18)*.8,s=e=>Math.round(CA(CA(t[e],n[e],i),r[e],o));return`#${[s(0),s(1),s(2)].map(e=>e.toString(16).padStart(2,`0`)).join(``)}`}function pA(e){if(e===void 0)return 1;if(typeof e!=`number`||!Number.isFinite(e)||e<=0)throw new y(`BAD_FORMAT`,`environment.exposure must be a finite number > 0 (tone-mapping exposure, default 1), got ${JSON.stringify(e)}.`,{prop:`exposure`});return e}function mA(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.sky must be an object ({ type?: "atmosphere", sunPosition? | elevationDeg?+azimuthDeg?, turbidity?, rayleigh? }), got ${JSON.stringify(e)}.`,{prop:`sky`});let t=e;for(let e of Object.keys(t))if(!Xk.includes(e))throw new y(`BAD_FORMAT`,`environment.sky has unknown key '${e}'. Valid keys: [${Xk.join(`, `)}].`,{prop:`sky`,validOptions:Xk});if(t.type!==void 0&&t.type!==`atmosphere`)throw new y(`BAD_FORMAT`,`environment.sky.type must be 'atmosphere' (the only sky type so far), got ${JSON.stringify(t.type)}.`,{prop:`sky`,validOptions:[`atmosphere`]});let n=t.elevationDeg!==void 0||t.azimuthDeg!==void 0;if(t.sunPosition!==void 0&&n)throw new y(`BAD_FORMAT`,`environment.sky takes sunPosition OR elevationDeg/azimuthDeg, not both.`,{prop:`sky`,validOptions:[`sunPosition`,`elevationDeg+azimuthDeg`]});let r;if(t.sunPosition!==void 0){let e=t.sunPosition;if(!Array.isArray(e)||e.length!==3||!e.every(e=>typeof e==`number`&&Number.isFinite(e))||Math.hypot(e[0],e[1],e[2])===0)throw new y(`BAD_FORMAT`,`environment.sky.sunPosition must be a non-zero [x, y, z] vector, got ${JSON.stringify(e)}.`,{prop:`sky`});r=[e[0],e[1],e[2]]}else{let e=bA(t.elevationDeg,32,`sky.elevationDeg`),n=bA(t.azimuthDeg,135,`sky.azimuthDeg`);if(e<-90||e>90)throw new y(`BAD_FORMAT`,`environment.sky.elevationDeg must be in [-90, 90] (degrees above the horizon), got ${e}.`,{prop:`sky`});r=uA(e,n)}let i=bA(t.turbidity,rA,`sky.turbidity`);if(i<=0)throw new y(`BAD_FORMAT`,`environment.sky.turbidity must be > 0 (atmospheric haze; 2 ≈ clear day), got ${i}.`,{prop:`sky`});let a=bA(t.rayleigh,iA,`sky.rayleigh`);if(a<0)throw new y(`BAD_FORMAT`,`environment.sky.rayleigh must be >= 0 (Rayleigh scattering; 1 ≈ earth-like), got ${a}.`,{prop:`sky`});return{sunPosition:r,turbidity:i,rayleigh:a}}function hA(e,t){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.fog must be an object ({ color?, near?, far? }), got ${JSON.stringify(e)}.`,{prop:`fog`});let n=e;for(let e of Object.keys(n))if(!Zk.includes(e))throw new y(`BAD_FORMAT`,`environment.fog has unknown key '${e}'. Valid keys: [${Zk.join(`, `)}].`,{prop:`fog`,validOptions:Zk});if(n.color!==void 0&&typeof n.color!=`string`)throw new y(`BAD_FORMAT`,`environment.fog.color must be a hex color string, got ${JSON.stringify(n.color)}.`,{prop:`fog`});let r=bA(n.near,aA,`fog.near`),i=bA(n.far,oA,`fog.far`);if(r<0)throw new y(`BAD_FORMAT`,`environment.fog.near must be >= 0 meters, got ${r}.`,{prop:`fog`});if(i<=r)throw new y(`BAD_FORMAT`,`environment.fog.far must be > near (got near ${r}, far ${i}).`,{prop:`fog`});return{color:n.color??(t?``:sA),near:r,far:i}}function gA(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.clouds must be an object ({ coverage?, density?, base?, top?, color?, shadeColor?, speed?, scale? }), got ${JSON.stringify(e)}.`,{prop:`clouds`});let t=e;for(let e of Object.keys(t))if(!Qk.includes(e))throw new y(`BAD_FORMAT`,`environment.clouds has unknown key '${e}'. Valid keys: [${Qk.join(`, `)}].`,{prop:`clouds`,validOptions:Qk});for(let e of[`color`,`shadeColor`])if(t[e]!==void 0&&typeof t[e]!=`string`)throw new y(`BAD_FORMAT`,`environment.clouds.${e} must be a hex color string, got ${JSON.stringify(t[e])}.`,{prop:`clouds`});let n=bA(t.coverage,.5,`clouds.coverage`);if(n<0||n>1)throw new y(`BAD_FORMAT`,`environment.clouds.coverage must be in [0, 1] (how much sky is cloudy), got ${n}.`,{prop:`clouds`});let r=bA(t.density,1,`clouds.density`);if(r<0)throw new y(`BAD_FORMAT`,`environment.clouds.density must be >= 0 (optical thickness), got ${r}.`,{prop:`clouds`});let i=bA(t.base,120,`clouds.base`),a=bA(t.top,320,`clouds.top`);if(a<=i)throw new y(`BAD_FORMAT`,`environment.clouds.top must be > base (got base ${i}, top ${a}).`,{prop:`clouds`});let o=bA(t.speed,1,`clouds.speed`),s=bA(t.scale,240,`clouds.scale`);if(s<=0)throw new y(`BAD_FORMAT`,`environment.clouds.scale must be > 0 (feature size in world units), got ${s}.`,{prop:`clouds`});return{coverage:n,density:r,base:i,top:a,color:t.color??`#ffffff`,shadeColor:t.shadeColor??`#9fb0c8`,speed:o,scale:s}}function _A(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.bloom must be an object ({ threshold?, strength? }), got ${JSON.stringify(e)}.`,{prop:`bloom`});let t=e;for(let e of Object.keys(t))if(!$k.includes(e))throw new y(`BAD_FORMAT`,`environment.bloom has unknown key '${e}'. Valid keys: [${$k.join(`, `)}].`,{prop:`bloom`,validOptions:$k});let n=bA(t.threshold,1,`bloom.threshold`);if(n<0||n>8)throw new y(`BAD_FORMAT`,`environment.bloom.threshold must be in [0, 8] (linear-HDR luminance; 1 = white), got ${n}.`,{prop:`bloom`});let r=bA(t.strength,.8,`bloom.strength`);if(r<0)throw new y(`BAD_FORMAT`,`environment.bloom.strength must be >= 0, got ${r}.`,{prop:`bloom`});return{threshold:n,strength:r}}function vA(e){if(e===void 0)return null;if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.post must be an object ({ vignette?, saturation?, contrast? }), got ${JSON.stringify(e)}.`,{prop:`post`});let t=e;for(let e of Object.keys(t))if(!eA.includes(e))throw new y(`BAD_FORMAT`,`environment.post has unknown key '${e}'. Valid keys: [${eA.join(`, `)}].`,{prop:`post`,validOptions:eA});let n=bA(t.vignette,0,`post.vignette`);if(n<0||n>1)throw new y(`BAD_FORMAT`,`environment.post.vignette must be in [0, 1], got ${n}.`,{prop:`post`});let r=bA(t.saturation,1,`post.saturation`);if(r<0||r>4)throw new y(`BAD_FORMAT`,`environment.post.saturation must be in [0, 4] (1 = neutral), got ${r}.`,{prop:`post`});let i=bA(t.contrast,1,`post.contrast`);if(i<.2||i>3)throw new y(`BAD_FORMAT`,`environment.post.contrast must be in [0.2, 3] (1 = neutral), got ${i}.`,{prop:`post`});return{vignette:n,saturation:r,contrast:i}}function yA(e){if(e===void 0)return null;if(e===!1)return!1;if(e===!0)return{mapSize:2048,radius:1,static:!1};if(typeof e!=`object`||!e||Array.isArray(e))throw new y(`BAD_FORMAT`,`environment.shadows must be true, false or an object ({ mapSize?, radius? }), got ${JSON.stringify(e)}.`,{prop:`shadows`});let t=e;for(let e of Object.keys(t))if(!tA.includes(e))throw new y(`BAD_FORMAT`,`environment.shadows has unknown key '${e}'. Valid keys: [${tA.join(`, `)}].`,{prop:`shadows`,validOptions:tA});let n=t.mapSize===void 0?2048:t.mapSize;if(!nA.includes(n))throw new y(`BAD_FORMAT`,`environment.shadows.mapSize must be one of [${nA.join(`, `)}], got ${JSON.stringify(t.mapSize)}.`,{prop:`shadows`,validOptions:nA.map(String)});let r=bA(t.radius,1,`shadows.radius`);if(r<0)throw new y(`BAD_FORMAT`,`environment.shadows.radius must be >= 0, got ${r}.`,{prop:`shadows`});let i=t.static===void 0?!1:t.static;if(typeof i!=`boolean`)throw new y(`BAD_FORMAT`,`environment.shadows.static must be a boolean, got ${JSON.stringify(t.static)}.`,{prop:`shadows`});return{mapSize:n,radius:r,static:i}}function bA(e,t,n){if(e===void 0)return t;if(typeof e!=`number`||!Number.isFinite(e))throw new y(`BAD_FORMAT`,`environment.${n} must be a finite number, got ${JSON.stringify(e)}.`,{prop:n});return e}function xA(e,t,n){return Math.min(Math.max(e,t),n)}function SA(e){return xA(e,0,1)}function CA(e,t,n){return e+(t-e)*n}var wA=`https://agent8-games.verse8.io/assets/3D/default/textures/hdri`,TA={apartment:`lebombo_1k.hdr`,city:`potsdamer_platz_1k.hdr`,dawn:`kiara_1_dawn_1k.hdr`,forest:`forest_slope_1k.hdr`,lobby:`st_fagans_interior_1k.hdr`,night:`dikhololo_night_1k.hdr`,park:`rooitou_park_1k.hdr`,studio:`studio_small_03_1k.hdr`,sunset:`venice_sunset_1k.hdr`,warehouse:`empty_warehouse_01_1k.hdr`};function EA(e){if(typeof e.hdri==`string`&&e.hdri!==``)return e.hdri;if(typeof e.preset==`string`){let t=TA[e.preset];if(!t)throw Error(`Unknown environment preset '${e.preset}'. Available: ${Object.keys(TA).join(`, `)}.`);return`${wA}/${t}`}return null}var DA=75,OA=class{scene;ambient=new rl(`#ffffff`,0);envKey=null;config=lA(void 0);hdriUrl=null;hdriTexture=null;_sky=null;skyKey=``;skyEnvKey=``;skyEnvTarget=null;fog=new oa(`#ffffff`,1,1e3);underwaterFog=null;underwaterBg=new G;constructor(e){this.scene=e,this.scene.add(this.ambient)}get sunDirection(){return this.config.sky?dA(this.config.sky):null}get clouds(){return this.config.clouds}get bloom(){return this.config.bloom}get post(){return this.config.post}get sceneFog(){return this.scene.fog instanceof oa?this.scene.fog:null}apply(e,t){let n=e===void 0?``:JSON.stringify(e);n!==this.envKey&&(this.envKey=n,this.config=lA(e));let r=this.config,i=e?.ambient;if(this.ambient.color.set(i?.color??`#ffffff`),this.ambient.intensity=i?.intensity??0,t&&(t.toneMappingExposure=r.exposure,t.shadowMap.enabled=r.shadows!==!1,r.shadows!==!1&&r.shadows!==null&&r.shadows.static?t.shadowMap.autoUpdate&&(t.shadowMap.autoUpdate=!1,t.shadowMap.needsUpdate=!0):t.shadowMap.autoUpdate||(t.shadowMap.autoUpdate=!0)),this.applyHdri(e),this.applySky(r.sky,t),this._sky&&(this._sky.visible=!0),this.applyFog(r),this.scene.environment=this.hdriTexture??this.skyEnvTarget?.texture??null,this.scene.environmentIntensity=(this.scene.environment===this.skyEnvTarget?.texture&&this.skyEnvTarget?.55:1)*kA(e?.iblIntensity),e?.skybox===!0&&this.hdriTexture)this.scene.background=this.hdriTexture;else{let t=e?.background;this.scene.background=typeof t==`string`?new G(t):null}}applySunLight(e,t=null){if(!e)return;let n=this.sunDirection;if(t){let r=e.position.length()||100,i,a,o;if(n)[i,a,o]=n;else{i=e.position.x-e.target.position.x,a=e.position.y-e.target.position.y,o=e.position.z-e.target.position.z;let t=Math.hypot(i,a,o)||1;i/=t,a/=t,o/=t}e.target.position.set(t.x,t.y,t.z),e.target.updateMatrixWorld(),e.position.set(t.x+i*r,t.y+a*r,t.z+o*r)}else if(n){let t=e.position.length()||100;e.position.set(n[0],n[1],n[2]).multiplyScalar(t)}let r=this.config.shadows;if(r&&typeof r==`object`){if(!e.castShadow){let t=e.shadow.camera;`left`in t&&t.left===-5&&(t.left=-75,t.right=DA,t.top=DA,t.bottom=-75,t.near=.5,t.far=500,t.updateProjectionMatrix()),e.castShadow=!0}e.shadow.mapSize.x!==r.mapSize&&(e.shadow.mapSize.set(r.mapSize,r.mapSize),e.shadow.map?.dispose(),e.shadow.map=null),e.shadow.radius=r.radius}}applyUnderwater(e){e&&(this.underwaterFog||=new oa(`#000000`,.5,e.visibility),this.underwaterFog.color.set(e.color),this.underwaterFog.near=.5,this.underwaterFog.far=e.visibility,this.scene.fog=this.underwaterFog,this.scene.background=this.underwaterBg.set(e.color),this._sky&&(this._sky.visible=!1))}applyHdri(e){let t=EA(e??{});t!==this.hdriUrl&&(this.hdriUrl=t,this.hdriTexture?.dispose(),this.hdriTexture=null,t&&new Jk().load(t,e=>{if(this.hdriUrl!==t){e.dispose();return}e.mapping=303,this.hdriTexture=e}))}applySky(e,t){let n=e?JSON.stringify(e):``;if(n!==this.skyKey&&(this.skyKey=n,this._sky&&=(this.scene.remove(this._sky),this._sky.material.dispose(),this._sky.geometry.dispose(),null),e)){this._sky=new Yk,this._sky.scale.setScalar(45e4);let t=this._sky.material.uniforms;(t.sunPosition?.value).set(...e.sunPosition),t.turbidity&&(t.turbidity.value=e.turbidity),t.rayleigh&&(t.rayleigh.value=e.rayleigh),this.scene.add(this._sky)}if(e&&t&&this._sky&&this.skyEnvKey!==n){this.skyEnvKey=n,this.skyEnvTarget?.dispose();let e=new ru(t),r=new sa;r.add(this._sky),this.skyEnvTarget=e.fromScene(r),e.dispose(),this.scene.add(this._sky)}!e&&this.skyEnvTarget&&(this.skyEnvTarget.dispose(),this.skyEnvTarget=null,this.skyEnvKey=``)}applyFog(e){if(!e.fog){this.scene.fog=null;return}let t=e.fog.color||(e.sky?fA(e.sky):`#cfd8e0`);this.fog.color.set(t),this.fog.near=e.fog.near,this.fog.far=e.fog.far,this.scene.fog=this.fog}dispose(){this.hdriTexture?.dispose(),this.hdriTexture=null,this.skyEnvTarget?.dispose(),this.skyEnvTarget=null,this._sky&&=(this.scene.remove(this._sky),this._sky.material.dispose(),this._sky.geometry.dispose(),null)}};function kA(e){if(e===void 0)return 1;if(typeof e!=`number`||!Number.isFinite(e)||e<0)throw new y(`BAD_FORMAT`,`environment.iblIntensity must be a finite number >= 0 (multiplies the image-based ambience: sky-derived base 0.55, HDRI base 1; default 1), got ${JSON.stringify(e)}.`,{prop:`iblIntensity`});return e}var AA=new Sa,jA=new H,MA=.4,NA=new Float32Array(72);function PA(e){if(!(e instanceof qp))return null;let t=e._ensureObject3D();if(t.updateWorldMatrix(!0,!0),AA.setFromObject(t),AA.getSize(jA),!Number.isFinite(jA.x)||jA.x===0&&jA.y===0&&jA.z===0){let e=new H().setFromMatrixPosition(t.matrixWorld);AA.min.set(e.x-MA,e.y-MA,e.z-MA),AA.max.set(e.x+MA,e.y+MA,e.z+MA)}else AA.expandByScalar(.02);let{min:n,max:r}=AA,i=0,a=(e,t,n,r,a,o)=>{NA[i++]=e,NA[i++]=t,NA[i++]=n,NA[i++]=r,NA[i++]=a,NA[i++]=o};return a(n.x,n.y,n.z,r.x,n.y,n.z),a(r.x,n.y,n.z,r.x,n.y,r.z),a(r.x,n.y,r.z,n.x,n.y,r.z),a(n.x,n.y,r.z,n.x,n.y,n.z),a(n.x,r.y,n.z,r.x,r.y,n.z),a(r.x,r.y,n.z,r.x,r.y,r.z),a(r.x,r.y,r.z,n.x,r.y,r.z),a(n.x,r.y,r.z,n.x,r.y,n.z),a(n.x,n.y,n.z,n.x,r.y,n.z),a(r.x,n.y,n.z,r.x,r.y,n.z),a(r.x,n.y,r.z,r.x,r.y,r.z),a(n.x,n.y,r.z,n.x,r.y,r.z),NA}function FA(e){return e.spatial===!0&&typeof e._setSpatialPose==`function`}function IA(){let e=new Set,t=[],n=[],r=[];return{visited:e,cameras:t,renderHooks:n,emitters:r,state:{visited:e,cameras:t,renderHooks:n,emitters:r,assets:void 0,sunDirection:null,sunLight:null,alpha:1,ignoreStatic:!1}}}function LA(e,t,n,r,i){let a=i??IA();a.visited.clear(),a.cameras.length=0,a.renderHooks.length=0,a.emitters.length=0;let o=a.state;o.assets=n,o.sunDirection=r?.sunDirection??null,o.ignoreStatic=r?.ignoreStatic===!0,o.sunLight=null,o.alpha=r?.alpha??1,UA(e,t,o),KA(t,a.visited);let s=null;for(let e=0;e<a.cameras.length;e++){let t=a.cameras[e];if(t.current){s=t;break}}s||=a.cameras[0]??null;let c=s?s._ensureObject3D():null;return HA(a.emitters,c),{activeCamera:c,renderHooks:a.renderHooks,sunLight:o.sunLight}}var RA=new H,zA=new H,BA=new H,VA=new H;function HA(e,t){if(e.length===0||!t)return;t.updateWorldMatrix(!0,!1),t.getWorldPosition(zA),t.getWorldDirection(BA),VA.set(0,1,0).applyQuaternion(t.quaternion);let n={position:[zA.x,zA.y,zA.z],forward:[BA.x,BA.y,BA.z],up:[VA.x,VA.y,VA.z]};for(let{node:t,parent:r}of e)r.updateWorldMatrix(!0,!1),r.getWorldPosition(RA),t._setSpatialPose({position:[RA.x,RA.y,RA.z],listener:n})}function UA(e,t,n){let r=t;if(e instanceof qp){let i=e._ensureObject3D();if(e.static&&!n.ignoreStatic&&i.userData.incantoStaticSynced===!0){i.userData.incantoStatic=!0,n.visited.add(i);return}if(i.parent!==t&&t.add(i),e._syncObject3D(n.alpha),n.assets&&e instanceof BE&&e._syncModel(n.assets),typeof e._onRender3D==`function`&&n.renderHooks.push(e),n.sunDirection){let t=e._applySunDirection;typeof t==`function`&&t.call(e,n.sunDirection)}e instanceof TE&&(!n.sunLight||e.intensity>n.sunLight.intensity)&&(n.sunLight=e),n.visited.add(i),e instanceof TC&&n.cameras.push(e),r=i}else FA(e)&&n.emitters.push({node:e,parent:r});for(let t of e.children)UA(t,r,n);if(e instanceof qp){let t=e._ensureObject3D();e.static&&!n.ignoreStatic?(t.userData.incantoStaticSynced=!0,t.userData.incantoStatic=!0,GA(e)):t.userData.incantoStaticSynced===!0&&(t.userData.incantoStaticSynced=!1,t.userData.incantoStatic=!1)}}var WA=new WeakSet;function GA(e){if(WA.has(e))return;WA.add(e);let t=[],n=e=>{(typeof e._onRender3D==`function`||e instanceof TC)&&t.push(`${e.name} (${e.constructor.typeName??`?`})`);for(let t of e.children)n(t)};n(e),t.length>0&&console.warn(`[incanto] static subtree '${e.name}' freezes animated/per-frame nodes: ${t.join(`, `)} — they will stop updating. Unmark static or move them out.`)}function KA(e,t){let n=e.children;for(let r=n.length-1;r>=0;r--){let i=n[r];i.userData.incantoNode&&!t.has(i)?e.remove(i):i.userData.incantoStatic!==!0&&KA(i,t)}}var qA=class{viewOverride=null;overrideCam=new Yc(60,1,.05,5e3);lastCamera=null;lastSize={w:1,h:1};webgl;threeScene=new sa;environment=new OA(this.threeScene);engine;disconnect;canvas;assets;ownsAssets;loadedAssetScenes=new WeakSet;compiledScene=null;syncScratch=IA();ignoreStatic=!1;renderCtx=null;causticsTarget=null;causticsScene=null;causticsUniforms=null;cloudsTarget=null;cloudsHalfTarget=null;cloudsBlurTarget=null;cloudsScene=null;cloudsUniforms=null;cloudsBlurScene=null;cloudsBlurUniforms=null;cloudsCompositeScene=null;cloudsCompositeUniforms=null;bloomTarget=null;bloomBrightTarget=null;bloomBlurTarget=null;bloomBrightScene=null;bloomBrightUniforms=null;bloomBlurScene=null;bloomBlurUniforms=null;bloomCompositeScene=null;bloomCompositeUniforms=null;constructor(e){this.canvas=e.canvas,this.engine=e.engine,this.ownsAssets=!e.assets,this.assets=e.assets??new Mx;let t=lt(e.engine.scene?.environment,{antialias:!0,pixelRatio:Math.min(globalThis.devicePixelRatio??1,2)},globalThis.devicePixelRatio??1,{pixelRatio:e.pixelRatio});this.webgl=new Zf({canvas:e.canvas,antialias:t.antialias}),this.basePixelRatio=t.pixelRatio,this.webgl.setPixelRatio(t.pixelRatio),this.adaptive=e.adaptiveResolution===!1?null:new jk,this.webgl.shadowMap.enabled=!0,this.webgl.shadowMap.type=1,this.webgl.toneMapping=4,this.webgl.toneMappingExposure=1,this.debugLines=new ws(new q,new fs({color:`#00ff6e`,depthTest:!1})),this.debugLines.frustumCulled=!1,this.debugLines.renderOrder=9999,this.debugLines.visible=!1,this.threeScene.add(this.debugLines),this.selectionLines=new ws(new q,new fs({color:`#ffb020`,transparent:!0,depthTest:!1})),this.selectionLines.frustumCulled=!1,this.selectionLines.renderOrder=1e4,this.selectionLines.visible=!1,this.threeScene.add(this.selectionLines),this.disconnect=this.engine.updated.connect(()=>this.render())}basePixelRatio;adaptive;lastFrameAt=0;debugLines;selectionLines;syncSelectionOutline(){let e=this.engine.debugSelection;e&&e.tree!==this.engine.scene?.tree&&(this.engine.debugSelection=null);let t=this.engine.debugSelection,n=t?PA(t):null;if(this.selectionLines.visible=n!==null,n){this.selectionLines.geometry.setAttribute(`position`,new K(n,3));let e=this.selectionLines.geometry.getAttribute(`position`);e.needsUpdate=!0}}syncDebugLines(){let e=null;for(let t of Sh(`3d`))if(e=t.debugLines(),e)break;this.debugLines.visible=e!==null,e&&this.debugLines.geometry.setAttribute(`position`,new K(e,3))}governResolution(){let e=this.adaptive;if(!e)return;let t=globalThis.performance?.now?.()??0,n=this.lastFrameAt;if(this.lastFrameAt=t,n===0)return;let r=t-n;if(r>500){e.reset();return}let i=e.push(r);if(i===null)return;this.webgl.setPixelRatio(this.basePixelRatio*i);let a=this.lastSize;a.w>0&&a.h>0&&this.webgl.setSize(a.w,a.h,!1)}render(){let e=this.engine.scene;if(!e)return;this.governResolution(),this.syncDebugLines(),this.syncSelectionOutline(),e.assets&&!this.loadedAssetScenes.has(e)&&(this.assets.load(e.assets),this.loadedAssetScenes.add(e)),this.environment.apply(e.environment,this.webgl);let{activeCamera:t,renderHooks:n,sunLight:r}=LA(e.root,this.threeScene,this.assets,{sunDirection:this.environment.sunDirection,alpha:this.engine.interpolationAlpha,ignoreStatic:this.ignoreStatic},this.syncScratch),i=t;if(this.viewOverride){let[e,t,n]=this.viewOverride.position,[r,a,o]=this.viewOverride.target;this.overrideCam.position.set(e,t,n),this.overrideCam.lookAt(YA.set(r,a,o)),i=this.overrideCam}if(!i)return;this.lastCamera=i,i.updateWorldMatrix(!0,!1);let a=i.getWorldPosition(ej),o=r?r._ensureObject3D():null,s=!!o&&r.shadowFollowsCamera===!0;this.environment.applySunLight(o,s?a:null),this.compiledScene!==e&&(this.compiledScene=e,this.webgl.compile(this.threeScene,i));let c=this.canvas.clientWidth||this.canvas.width,l=this.canvas.clientHeight||this.canvas.height,u=this.webgl.getSize(JA);(u.x!==c||u.y!==l)&&this.webgl.setSize(c,l,!1),this.lastSize={w:c,h:l};let d=l===0?1:c/l;i.aspect!==d&&(i.aspect=d,i.updateProjectionMatrix()),this.renderCtx||={gl:this.webgl,scene:this.threeScene,camera:i};let f=this.renderCtx;f.camera=i,o?(o.updateWorldMatrix(!0,!1),o.target.updateWorldMatrix(!0,!1),f.sunDir=ZA.setFromMatrixPosition(o.matrixWorld).sub(QA.setFromMatrixPosition(o.target.matrixWorld)).normalize()):f.sunDir=null;for(let e=0;e<n.length;e++)n[e]?._onRender3D(f);let p=null;for(let e=0;e<n.length;e++){let t=n[e].underwaterAt?.(a.x,a.y,a.z);if(t){p=t;break}}this.environment.applyUnderwater(p);let m=this.environment.clouds,h=this.environment.bloom,g=this.environment.post;p?.caustics.enabled?this.renderWithCaustics(i,p):m&&!p?this.renderWithClouds(i,m,o):(h||g)&&!p?this.renderWithBloom(i,h,g):this.webgl.render(this.threeScene,i)}renderWithBloom(e,t,n=null){let r=this.webgl.getDrawingBufferSize(JA),i=Math.max(1,r.x),a=Math.max(1,r.y),o=Math.max(1,Math.ceil(i/2)),s=Math.max(1,Math.ceil(a/2));if(this.bloomTarget&&(this.bloomTarget.width!==i||this.bloomTarget.height!==a)&&(this.bloomTarget.dispose(),this.bloomTarget=null,this.bloomBrightTarget?.dispose(),this.bloomBrightTarget=null,this.bloomBlurTarget?.dispose(),this.bloomBlurTarget=null),this.bloomTarget||(this.bloomTarget=new Si(i,a,{type:Qt}),this.bloomBrightTarget=new Si(o,s,{type:Qt}),this.bloomBlurTarget=new Si(o,s,{type:Qt})),!this.bloomBrightScene){let e=Lk();this.bloomBrightScene=new sa,this.bloomBrightScene.add(e.mesh),this.bloomBrightUniforms=e.uniforms;let t=Rk();this.bloomBlurScene=new sa,this.bloomBlurScene.add(t.mesh),this.bloomBlurUniforms=t.uniforms;let n=zk();this.bloomCompositeScene=new sa,this.bloomCompositeScene.add(n.mesh),this.bloomCompositeUniforms=n.uniforms}let c=this.bloomBrightTarget,l=this.bloomBlurTarget;if(this.webgl.setRenderTarget(this.bloomTarget),this.webgl.render(this.threeScene,e),t){let n=this.bloomBrightUniforms;n.tScene.value=this.bloomTarget.texture,n.uThreshold.value=t.threshold,this.webgl.setRenderTarget(c),this.webgl.render(this.bloomBrightScene,e);let r=this.bloomBlurUniforms;r.tTex.value=c.texture,r.uDir.value.set(1/o,0),this.webgl.setRenderTarget(l),this.webgl.render(this.bloomBlurScene,e),r.tTex.value=l.texture,r.uDir.value.set(0,1/s),this.webgl.setRenderTarget(c),this.webgl.render(this.bloomBlurScene,e)}let u=this.bloomCompositeUniforms;u.tScene.value=this.bloomTarget.texture,u.tBloom.value=t?c.texture:this.bloomTarget.texture,u.uStrength.value=t?t.strength:0,u.uVignette.value=n?.vignette??0,u.uSaturation.value=n?.saturation??1,u.uContrast.value=n?.contrast??1,this.webgl.setRenderTarget(null),this.webgl.render(this.bloomCompositeScene,e)}renderWithClouds(e,t,n){let r=this.webgl.getDrawingBufferSize(JA),i=Math.max(1,r.x),a=Math.max(1,r.y),o=Math.max(1,Math.ceil(i/3)),s=Math.max(1,Math.ceil(a/3));if(this.cloudsTarget&&(this.cloudsTarget.width!==i||this.cloudsTarget.height!==a)&&(this.cloudsTarget.depthTexture?.dispose(),this.cloudsTarget.dispose(),this.cloudsTarget=null,this.cloudsHalfTarget?.dispose(),this.cloudsHalfTarget=null,this.cloudsBlurTarget?.dispose(),this.cloudsBlurTarget=null),!this.cloudsTarget){let e=new Fs(i,a);e.type=Zt,this.cloudsTarget=new Si(i,a,{depthTexture:e,depthBuffer:!0})}if(this.cloudsHalfTarget||(this.cloudsHalfTarget=new Si(o,s,{depthBuffer:!1}),this.cloudsBlurTarget=new Si(o,s,{depthBuffer:!1})),!this.cloudsScene){let{mesh:e,uniforms:t}=Gk();this.cloudsScene=new sa,this.cloudsScene.add(e),this.cloudsUniforms=t}if(!this.cloudsBlurScene){let{mesh:e,uniforms:t}=Wk();this.cloudsBlurScene=new sa,this.cloudsBlurScene.add(e),this.cloudsBlurUniforms=t}if(!this.cloudsCompositeScene){let{mesh:e,uniforms:t}=Kk();this.cloudsCompositeScene=new sa,this.cloudsCompositeScene.add(e),this.cloudsCompositeUniforms=t}this.webgl.setRenderTarget(this.cloudsTarget),this.webgl.render(this.threeScene,e);let c=this.cloudsUniforms;c.tDepth.value=this.cloudsTarget.depthTexture,c.uInvViewProj.value.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse).invert(),e.getWorldPosition(c.uCameraPos.value),c.uTime.value=(globalThis.performance?.now()??0)*.001*t.speed;let l=this.environment.sunDirection??[.4,.8,.3];c.uSunDir.value.set(l[0],l[1],l[2]).normalize(),n&&c.uSunColor.value.copy(n.color),c.uCloudColor.value.set(t.color),c.uShadeColor.value.set(t.shadeColor);let u=this.environment.sceneFog;u?(c.uHorizonColor.value.copy(u.color),c.uFarFade.value=u.far):(c.uHorizonColor.value.set(`#cdd9e6`),c.uFarFade.value=6e3),c.uBase.value=t.base,c.uTop.value=t.top,c.uCoverage.value=t.coverage,c.uDensity.value=t.density,c.uScale.value=t.scale,c.uWind.value.set(1,.35),this.webgl.setRenderTarget(this.cloudsHalfTarget),this.webgl.render(this.cloudsScene,e);let d=this.cloudsBlurUniforms,f=this.cloudsBlurScene;d.tTex.value=this.cloudsHalfTarget.texture,d.uDir.value.set(1/o,0),this.webgl.setRenderTarget(this.cloudsBlurTarget),this.webgl.render(f,e),d.tTex.value=this.cloudsBlurTarget.texture,d.uDir.value.set(0,1/s),this.webgl.setRenderTarget(this.cloudsHalfTarget),this.webgl.render(f,e),this.webgl.setRenderTarget(null);let p=this.cloudsCompositeUniforms;p.tScene.value=this.cloudsTarget.texture,p.tClouds.value=this.cloudsHalfTarget.texture,this.webgl.render(this.cloudsCompositeScene,e)}renderWithCaustics(e,t){let n=this.webgl.getDrawingBufferSize(JA),r=Math.max(1,n.x),i=Math.max(1,n.y);if(this.causticsTarget&&(this.causticsTarget.width!==r||this.causticsTarget.height!==i)&&(this.causticsTarget.depthTexture?.dispose(),this.causticsTarget.dispose(),this.causticsTarget=null),!this.causticsTarget){let e=new Fs(r,i);e.type=Zt,this.causticsTarget=new Si(r,i,{depthTexture:e,depthBuffer:!0})}if(!this.causticsScene){let{mesh:e,uniforms:t}=yp();this.causticsScene=new sa,this.causticsScene.add(e),this.causticsUniforms=t}this.webgl.setRenderTarget(this.causticsTarget),this.webgl.render(this.threeScene,e),this.webgl.setRenderTarget(null);let a=this.causticsUniforms;a.tColor.value=this.causticsTarget.texture,a.tDepth.value=this.causticsTarget.depthTexture,a.uInvViewProj.value.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse).invert(),e.getWorldPosition(a.uCameraPos.value),a.uWaterLevel.value=t.surfaceY,a.uTime.value=(globalThis.performance?.now()??0)*.001*t.caustics.speed,a.uCausticColor.value.set(t.caustics.color),a.uCausticIntensity.value=t.caustics.intensity,a.uCausticScale.value=t.caustics.scale,a.uMaxDist.value=t.visibility;let o=this.environment.sunDirection;o&&a.uSunDirection.value.set(o[0],o[1],o[2]),a.uRayStrength.value=t.rays.enabled?t.rays.strength:0,this.webgl.render(this.causticsScene,e)}screenFromWorld(e,t,n){let r=this.lastCamera;return r?(XA.set(e,t,n).project(r),{x:(XA.x+1)/2*this.lastSize.w,y:(1-XA.y)/2*this.lastSize.h,behind:XA.z>1}):{x:0,y:0,behind:!0}}pick(e,t){let n=this.lastCamera;if(!n)return null;nj.set(e/this.lastSize.w*2-1,-(t/this.lastSize.h*2-1)),tj.setFromCamera(nj,n);let r=tj.intersectObjects(this.threeScene.children,!0);for(let e of r){let t=e.object;for(;t&&!t.userData.incantoNode;)t=t.parent;let n=t?.userData.incantoNode;if(n)return n}return null}stats(){let e=this.webgl.info;return{triangles:e.render.triangles,drawCalls:e.render.calls,geometries:e.memory.geometries,textures:e.memory.textures}}cameraBasis(){let e=this.lastCamera,t=e?e.getWorldQuaternion($A):$A.identity();return{right:new H(1,0,0).applyQuaternion(t),up:new H(0,1,0).applyQuaternion(t),forward:new H(0,0,-1).applyQuaternion(t)}}refreshShadows(){this.webgl.shadowMap.needsUpdate=!0}dispose(){this.disconnect(),this.threeScene.traverse(e=>{let t=e;if(!(!t.isMesh||t.userData?.incantoModelShared))if(t.geometry?.dispose(),Array.isArray(t.material))for(let e of t.material)e.dispose();else t.material?.dispose()}),this.causticsTarget?.depthTexture?.dispose(),this.causticsTarget?.dispose();let e=this.causticsScene?.children[0];e?.geometry?.dispose(),e?.material?.dispose(),this.cloudsTarget?.depthTexture?.dispose(),this.cloudsTarget?.dispose(),this.cloudsHalfTarget?.dispose(),this.cloudsBlurTarget?.dispose(),this.bloomTarget?.dispose(),this.bloomBrightTarget?.dispose(),this.bloomBlurTarget?.dispose();for(let e of[this.cloudsScene,this.cloudsBlurScene,this.cloudsCompositeScene,this.bloomBrightScene,this.bloomBlurScene,this.bloomCompositeScene]){let t=e?.children[0];t?.geometry?.dispose(),t?.material?.dispose()}this.ownsAssets&&this.assets.dispose(),this.environment.dispose(),this.webgl.dispose()}},JA=new B,YA=new H,XA=new H,ZA=new H,QA=new H,$A=new V,ej=new H,tj=new kl,nj=new B,rj=e({DEFAULT_TERRAIN_TEXTURE_BASE:()=>aS,WATER_CUTOUT_MAX:()=>4,WATER_MAX_RIPPLES:()=>8,enablePhysics3D:()=>wS}),ij=new WeakMap,aj=class e{account;roomId;roomState=new t;allUserStates=new t;userJoined=new t;userLeft=new t;globalState=new t;globalMyState=new t;asset=new t;latestUserStates={};latestRoomState={};latestGlobalState={};latestGlobalMyState={};latestAsset={};server;engine;throttleMs;subs=[];messageSignals=new Map;collectionSignals=new Map;latestCollections=new Map;globalMessageSignals=new Map;globalCollectionSignals=new Map;latestGlobalCollections=new Map;scenes=new Map;lastSent=new Map;sendAccumulator=0;detachReplication=null;lastOwner=null;boundScene=null;static get(e){return ij.get(e)??null}static async create(t,n={}){await ij.get(t)?.dispose();let r=n.transport??await uj(n.config);await r.connect();let i=n.room??t.scene?.multiplayer?.room??`auto`,a=new e(t,r,await r.remoteFunction(`joinRoom`,[i===`auto`?void 0:i],{needResponse:!0}),n.throttleMs??50);return ij.set(t,a),a}constructor(e,t,n,r){this.engine=e,this.server=t,this.roomId=n,this.account=t.account,this.throttleMs=Math.max(30,r),this.boundScene=e.scene,this.subs.push(t.subscribeRoomState(n,e=>{this.latestRoomState=e,this.roomState.emit(e)}),t.subscribeRoomAllUserStates(n,e=>{this.latestUserStates=e,this.allUserStates.emit(e)}),t.onRoomUserJoin(n,e=>this.userJoined.emit(e)),t.onRoomUserLeave(n,e=>this.userLeft.emit(e))),t.subscribeGlobalState&&this.subs.push(t.subscribeGlobalState(e=>{this.latestGlobalState=e,this.globalState.emit(e)})),t.subscribeGlobalMyState&&this.subs.push(t.subscribeGlobalMyState(e=>{this.latestGlobalMyState=e,this.globalMyState.emit(e)})),t.subscribeAsset&&this.subs.push(t.subscribeAsset(this.account,e=>{this.latestAsset=e,this.asset.emit(e)})),this.detachReplication=e.fixedUpdated.connect(e=>this.replicate(e))}message(e){let n=this.messageSignals.get(e);return n||(n=new t,this.messageSignals.set(e,n),this.subs.push(this.server.onRoomMessage(this.roomId,e,e=>n?.emit(e)))),n}collection(e){let n=this.collectionSignals.get(e);return n||(n=new t,this.collectionSignals.set(e,n),this.subs.push(this.server.subscribeRoomCollection(this.roomId,e,t=>{this.latestCollections.set(e,t),n?.emit(t)}))),n}latestCollection(e){return this.collection(e),this.latestCollections.get(e)??{}}globalMessage(e){let n=this.globalMessageSignals.get(e);if(!n){n=new t,this.globalMessageSignals.set(e,n);let r=this.server.onGlobalMessage?.(e,e=>n?.emit(e));r&&this.subs.push(r)}return n}globalCollection(e){let n=this.globalCollectionSignals.get(e);if(!n){n=new t,this.globalCollectionSignals.set(e,n);let r=this.server.subscribeGlobalCollection?.(e,t=>{this.latestGlobalCollections.set(e,t),n?.emit(t)});r&&this.subs.push(r)}return n}latestGlobalCollection(e){return this.globalCollection(e),this.latestGlobalCollections.get(e)??{}}setMyState(e){return this.server.remoteFunction(`setMyState`,[this.roomId,e],{throttle:this.throttleMs,throttleKey:`incanto:myState`})}patchRoomState(e){return this.server.remoteFunction(`patchRoomState`,[this.roomId,e])}addEntity(e,t){return this.server.remoteFunction(`addEntity`,[this.roomId,e,t])}updateEntity(e,t,n){return this.server.remoteFunction(`updateEntity`,[this.roomId,e,t,n])}removeEntity(e,t){return this.server.remoteFunction(`removeEntity`,[this.roomId,e,t])}sendEvent(e,t){return this.server.remoteFunction(`sendEvent`,[this.roomId,e,t])}call(e,...t){return this.server.remoteFunction(e,[this.roomId,...t],{needResponse:!0})}registerScene(e,t){this.scenes.set(e,t)}resolveScene(e){let t=this.scenes.get(e);if(!t)throw new y(`UNRESOLVED_INSTANCE`,`No scene registered for '${e}'. Registered: [${[...this.scenes.keys()].join(`, `)}]. Call manager.registerScene('${e}', sceneJson).`);return t}async dispose(){this.detachReplication?.();for(let e of this.subs)e();await this.server.remoteFunction(`leaveRoom`,[this.roomId]),ij.delete(this.engine)}replicate(e){let t=this.engine.scene;if(!t||t!==this.boundScene)return;this.sendAccumulator+=e*1e3;let n=oj(t.root,!0);if(!n)return;n!==this.lastOwner&&(this.lastOwner=n,this.lastSent.clear());let r=n.network,i=Math.max(30,typeof r.throttleMs==`number`?r.throttleMs:this.throttleMs),a=Array.isArray(r.sync)?r.sync:[],o={};for(let e of a){let t=cj(n,e);t!==void 0&&(de(this.lastSent.get(e)??null,t)||(o[e]=j(t)))}if(!(this.sendAccumulator<i)&&Object.keys(o).length!==0){for(let[e,t]of Object.entries(o))this.lastSent.set(e,j(t));this.sendAccumulator=0,this.setMyState({sync:o})}}};function oj(e,t=!1){let n=[];if(sj(e,n),t&&n.length>1)throw new y(`BAD_FORMAT`,`Multiple network owner nodes found (${n.map(e=>e.getPath()).join(`, `)}). Exactly ONE node per player may declare network.mode 'owner' — replicate spawned entities through collections instead.`);return n[0]??null}function sj(e,t){e.network?.mode===`owner`&&t.push(e);for(let n of e.children)sj(n,t)}function cj(e,t){let n=t.lastIndexOf(`.`),r=n===-1?e:e.getNodeOrNull(t.slice(0,n))??void 0,i=n===-1?t:t.slice(n+1);if(r)return r[i]}function lj(e,t,n){for(let[r,i]of Object.entries(t)){let t=r.lastIndexOf(`.`),a=t===-1?e:e.getNodeOrNull(r.slice(0,t)),o=t===-1?r:r.slice(t+1);a&&n(a,o,i)}}async function uj(e){let{createAgent8Server:t}=await Dh(async()=>{let{createAgent8Server:e}=await import(`./agent8-DElIPozC.js`);return{createAgent8Server:e}},[],import.meta.url);return t(e)}var dj=class extends Pe{static typeName=`NetworkSpawner`;static signals=[`spawned`,`despawned`];static props={source:{default:`users`},scene:{default:``},interpolate:{default:!0}};source=`users`;scene=``;interpolate=!0;spawned=new Map;positionTargets=new Map;failedKeys=new Set;update(e){let t=this.tree?.engine;if(!t)return;let n=aj.get(t);if(!n||this.scene===``)return;let r=this.currentEntries(n);for(let[e,t]of Object.entries(r)){let r=this.spawned.get(e);if(!r){if(this.failedKeys.has(e))continue;try{r=St(n.resolveScene(this.scene).root)}catch(t){throw this.failedKeys.add(e),t}r.name=fj(e),this.addChild(r),this.spawned.set(e,r),this.emit(`spawned`,r,e)}let i=t.sync;i&&lj(r,i,(e,t,n)=>this.setProp(e,t,n))}for(let[e,t]of[...this.spawned.entries()])e in r||(this.spawned.delete(e),this.positionTargets.delete(t),this.emit(`despawned`,t,e),t.free());this.interpolate&&this.stepInterpolation(e)}currentEntries(e){if(this.source===`users`){let t={};for(let[n,r]of Object.entries(e.latestUserStates))n!==e.account&&(t[n]=r);return t}return this.source.startsWith(`collection:`)?e.latestCollection(this.source.slice(11)):{}}setProp(e,t,n){if(this.interpolate&&t===`position`&&Array.isArray(n)){this.positionTargets.set(e,n);return}e[t]=n}stepInterpolation(e){let t=Math.min(1,e*8);for(let[e,n]of this.positionTargets){let r=e.position;Array.isArray(r)&&(e.position=r.map((e,r)=>e+((n[r]??e)-e)*t))}}};function fj(e){return e.replace(/[/%]/g,`_`)||`remote`}function pj(){ct(),M(dj)}var mj=80,hj=` `;function gj(e){return`${_j(e,0)}\n`}function _j(e,t){if(typeof e!=`object`||!e)return JSON.stringify(e);let n=vj(e);if(t*2+n.length<=mj)return n;let r=hj.repeat(t+1),i=hj.repeat(t);if(Array.isArray(e))return e.length===0?`[]`:`[\n${e.map(e=>r+_j(e,t+1)).join(`,
|
|
8319
|
+
`)}\n${i}]`;let a=Object.entries(e);return a.length===0?`{}`:`{\n${a.map(([e,n])=>`${r}${JSON.stringify(e)}: ${_j(n,t+1)}`).join(`,
|
|
8320
|
+
`)}\n${i}}`}function vj(e){if(typeof e!=`object`||!e)return JSON.stringify(e);if(Array.isArray(e))return e.length===0?`[]`:`[${e.map(vj).join(`, `)}]`;let t=Object.entries(e);return t.length===0?`{}`:`{ ${t.map(([e,t])=>`${JSON.stringify(e)}: ${vj(t)}`).join(`, `)} }`}async function yj(e){if(!e.ok)throw Error(`HTTP ${e.status} — ${await e.text()}`);return e}async function bj(){return await(await yj(await fetch(`/api/meta`))).json()}async function xj(){return await(await yj(await fetch(`/api/scenes`))).json()}async function Sj(e){return await(await yj(await fetch(`/api/scenes`,{method:`POST`,body:JSON.stringify({path:e})}))).json()}function Cj(e){return e?`/api/scene?file=${encodeURIComponent(e)}`:`/api/scene`}async function wj(e){return await(await yj(await fetch(Cj(e)))).json()}async function Tj(e,t){await yj(await fetch(Cj(t),{method:`PUT`,body:gj(e)}))}var Ej=localStorage.getItem(`incanto-editor-lang`)??`en`,Dj=new Set;function Oj(){return Ej}function kj(e){Ej=e,localStorage.setItem(`incanto-editor-lang`,e);for(let e of Dj)e()}function Aj(e){Dj.add(e)}function jj(e){return e[Ej]}var Mj={node:{paths:[`M5 5h14v14H5z`]},move:{paths:[`M12 3v18M3 12h18`,`M8 7l4-4 4 4M8 17l4 4 4-4M7 8l-4 4 4 4M17 8l4 4-4 4`]},image:{paths:[`M4 5h16v14H4z`,`M4 15l5-5 4 4 3-3 4 4`],circles:[[9,9,1.6]]},film:{paths:[`M4 4h16v16H4z`,`M4 9h16M4 15h16`,`M9 4v16M15 4v16`]},video:{paths:[`M3 7h12v10H3z`,`M15 10l6-3v10l-6-3`]},text:{paths:[`M5 7V5h14v2`,`M12 5v14`,`M9 19h6`]},layers:{paths:[`M12 3 3 8l9 5 9-5-9-5z`,`M3 12l9 5 9-5`,`M3 16l9 5 9-5`]},square:{paths:[`M5 5h14v14H5z`,`M5 12h14`]},ball:{paths:[`M12 8v0`],circles:[[12,12,8],[12,12,1.4]]},person:{paths:[`M5 21v-1a7 7 0 0 1 14 0v1`],circles:[[12,7,4]]},area:{paths:[`M5 5h14v14H5z`],dashed:!0},gamepad:{paths:[`M7 9h-0M6 12h4M8 10v4`,`M4 8h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2z`],circles:[[16,11,1],[18.5,13.5,1]]},clock:{paths:[`M12 7v5l3 2`],circles:[[12,12,9]]},cube:{paths:[`M21 16V8l-9-5-9 5v8l9 5 9-5z`,`M3.3 7.5 12 12.5l8.7-5`,`M12 22V12.5`]},sun:{paths:[`M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9 17 7M7 17l-2.1 2.1`],circles:[[12,12,4]]},bulb:{paths:[`M9 18h6M10 21h4`,`M8 13a6 6 0 1 1 8 0c-1 1-1.5 2-1.5 3h-5c0-1-.5-2-1.5-3z`]},globe:{paths:[`M2 12h20`,`M12 2a15 15 0 0 1 0 20a15 15 0 0 1 0-20z`],circles:[[12,12,10]]},link:{paths:[`M10 14a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1`,`M14 10a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1`]},speaker:{paths:[`M11 5 6 9H3v6h3l5 4V5z`,`M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13`]},swatch:{paths:[`M4 4h16v16H4z`,`M4 4l16 16`]},sparkles:{paths:[`M12 4v5M12 15v5M5 12h5M14 12h5`],circles:[[6,5,1],[18,19,1]]},waves:{paths:[`M2 8c3-3 5 3 8 0s5 3 8 0`,`M2 14c3-3 5 3 8 0s5 3 8 0`,`M2 20c3-3 5 3 8 0s5 3 8 0`]},plant:{paths:[`M12 21v-8`,`M12 13c0-4-3-6-7-6 0 4 3 6 7 6z`,`M12 11c0-4 3-6 7-6 0 4-3 6-7 6z`]},flower:{paths:[`M12 21v-7`],circles:[[12,9,2],[12,4.5,2.2],[16.3,7.5,2.2],[14.7,12.6,2.2],[9.3,12.6,2.2],[7.7,7.5,2.2]]},voxels:{paths:[`M4 14h8v8H4z`,`M12 14h8v8h-8z`,`M8 6h8v8H8z`]}},Nj={Node:`node`,Timer:`clock`,AudioPlayer:`speaker`,ColorRect2D:`swatch`,Particles2D:`sparkles`,Particles3D:`sparkles`,Water3D:`waves`,Foliage3D:`plant`,Flowers3D:`flower`,VoxelGrid3D:`voxels`,ModelInstance3D:`person`,CharacterController3D:`gamepad`,Node2D:`move`,Sprite2D:`image`,AnimatedSprite2D:`film`,Camera2D:`video`,Label:`text`,UILayer:`layers`,StaticBody2D:`square`,RigidBody2D:`ball`,CharacterBody2D:`person`,Area2D:`area`,CharacterController2D:`gamepad`,Node3D:`move`,Billboard3D:`layers`,MeshInstance3D:`cube`,LoftMesh3D:`cube`,Camera3D:`video`,DirectionalLight3D:`sun`,OmniLight3D:`bulb`,StaticBody3D:`square`,RigidBody3D:`ball`,CharacterBody3D:`person`,Area3D:`area`,NetworkSpawner:`globe`};function Pj(e){let t=Mj[Nj[e??``]??(e?`node`:`link`)],n=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);n.setAttribute(`viewBox`,`0 0 24 24`),n.setAttribute(`width`,`13`),n.setAttribute(`height`,`13`),n.setAttribute(`fill`,`none`),n.setAttribute(`stroke`,`currentColor`),n.setAttribute(`stroke-width`,`2`),n.setAttribute(`stroke-linecap`,`round`),n.setAttribute(`stroke-linejoin`,`round`),t.dashed&&n.setAttribute(`stroke-dasharray`,`3 2.4`);for(let e of t.paths){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);t.setAttribute(`d`,e),n.appendChild(t)}for(let[e,r,i]of t.circles??[]){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`circle`);t.setAttribute(`cx`,String(e)),t.setAttribute(`cy`,String(r)),t.setAttribute(`r`,String(i)),n.appendChild(t)}return n}function Fj(){let e=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);e.setAttribute(`viewBox`,`0 0 24 24`),e.setAttribute(`width`,`12`),e.setAttribute(`height`,`12`),e.setAttribute(`fill`,`none`),e.setAttribute(`stroke`,`currentColor`),e.setAttribute(`stroke-width`,`2.4`),e.setAttribute(`aria-hidden`,`true`);let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);return t.setAttribute(`d`,`m6 9 6 6 6-6`),e.appendChild(t),e}var Ij=[{type:`texture`,label:`image (texture)`,metaHints:[`filter`]},{type:`spritesheet`,label:`spritesheet`,metaHints:[`filter`,`frameWidth`,`frameHeight`]},{type:`model`,label:`3D model (GLB/VRM)`,metaHints:[]},{type:`animation`,label:`animation (GLB clips)`,metaHints:[`clip`]}],Lj=new Set,Rj=null,zj=null;function Bj(e,t,n){let r=document.createElement(`input`);r.className=`rename-input`,r.value=e;let i=()=>{let i=r.value.trim().replace(/\//g,``);i&&i!==e?t(i):n()};r.addEventListener(`keydown`,e=>{e.stopPropagation(),e.key===`/`&&e.preventDefault(),e.key===`Enter`&&i(),e.key===`Escape`&&n()});for(let e of[`click`,`pointerdown`,`dblclick`,`mousedown`])r.addEventListener(e,e=>e.stopPropagation());return r.addEventListener(`blur`,i),queueMicrotask(()=>{r.focus(),r.select()}),r}function Vj(e,t){let n={path:``,name:``,folders:new Map,assets:[]},r=e=>{let t=n;if(e===``)return t;for(let n of e.split(`/`)){let e=t.folders.get(n);e||(e={path:t.path?`${t.path}/${n}`:n,name:n,folders:new Map,assets:[]},t.folders.set(n,e)),t=e}return t};for(let t of e){let e=t.lastIndexOf(`/`);r(e===-1?``:t.slice(0,e)).assets.push(t)}for(let e of t)r(e);return n}function Hj(e){let t=e.assets.length;for(let n of e.folders.values())t+=Hj(n);return t}function Uj(e,t){e.textContent=``;let n=t.working.assets??{},r=Object.keys(n);if(r.length===0&&t.pendingGroups.size===0&&!t.addingAsset&&!t.addingGroup){let t=document.createElement(`div`);t.className=`muted-note explorer-empty`,t.textContent=`no assets yet — + adds textures, models, animations`,e.appendChild(t);return}let i=(e,n)=>{e.addEventListener(`dragover`,t=>{t.preventDefault(),t.stopPropagation(),e.classList.add(`drop-target`)}),e.addEventListener(`dragleave`,()=>e.classList.remove(`drop-target`)),e.addEventListener(`drop`,r=>{r.preventDefault(),r.stopPropagation(),e.classList.remove(`drop-target`);let i=r.dataTransfer?.getData(`text/incanto-asset`);i&&t.moveAsset(i,n);let a=r.dataTransfer?.getData(`text/incanto-group`);a&&t.moveGroup(a,n)})};i(e,``);let a=(e,r)=>{let i=n[e],a=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,o=document.createElement(`div`);o.className=`tree-row asset-row${t.selectedAsset===e?` selected`:``}`,o.draggable=!0,o.addEventListener(`dragstart`,t=>{t.dataTransfer?.setData(`text/incanto-asset`,e)});let s=document.createElement(`span`);if(s.className=`tree-icon`,s.appendChild(tM(i.type??``)),s.addEventListener(`click`,e=>{e.stopPropagation(),nM(s,i.type??``)}),Rj===e){let n=e.includes(`/`)?e.slice(0,e.lastIndexOf(`/`)+1):``;o.appendChild(Bj(a,r=>{Rj=null,t.renameAssetKey(e,n+r)},()=>{Rj=null,t.selectAsset(t.selectedAsset)})),o.draggable=!1,o.insertBefore(s,o.firstChild),r.appendChild(o);return}let c=document.createElement(`span`);c.className=`tree-name asset-key`,c.textContent=`$${a}`,c.title=`$${e}`,c.addEventListener(`dblclick`,n=>{n.stopPropagation(),Rj=e,t.selectAsset(e)}),o.append(s,c),o.addEventListener(`click`,()=>t.selectAsset(e)),r.appendChild(o)},o=(e,n)=>{let r=Lj.has(e.path),s=document.createElement(`div`);s.className=`asset-folder${r?` collapsed`:``}${t.selectedGroup===e.path?` selected`:``}`,s.draggable=!0,s.addEventListener(`dragstart`,t=>{t.stopPropagation(),t.dataTransfer?.setData(`text/incanto-group`,e.path)});let c=document.createElement(`span`);c.className=`chev`,c.appendChild(Fj());let l=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);l.setAttribute(`viewBox`,`0 0 24 24`),l.setAttribute(`width`,`12`),l.setAttribute(`height`,`12`),l.setAttribute(`fill`,`none`),l.setAttribute(`stroke`,`currentColor`),l.setAttribute(`stroke-width`,`1.8`),l.setAttribute(`aria-hidden`,`true`);let u=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);if(u.setAttribute(`d`,`M3 6a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`),l.appendChild(u),zj===e.path){let i=e.path.includes(`/`)?e.path.slice(0,e.path.lastIndexOf(`/`)+1):``;if(s.append(c,l,Bj(e.name,n=>{zj=null,t.renameGroup(e.path,i+n)},()=>{zj=null,t.selectGroup(t.selectedGroup)})),s.draggable=!1,n.appendChild(s),!r){let t=document.createElement(`div`);t.className=`tree-children`;for(let n of e.folders.values())o(n,t);for(let n of e.assets)a(n,t);t.children.length>0&&n.appendChild(t)}return}let d=document.createElement(`span`);d.textContent=e.name,d.addEventListener(`dblclick`,n=>{n.stopPropagation(),zj=e.path,t.selectGroup(e.path)});let f=document.createElement(`span`);if(f.className=`count`,f.textContent=`(${Hj(e)})`,s.append(c,l,d,f),s.addEventListener(`click`,()=>{Lj.has(e.path)?Lj.delete(e.path):Lj.add(e.path),t.selectGroup(e.path)}),i(s,e.path),n.appendChild(s),!r){let t=document.createElement(`div`);t.className=`tree-children`;for(let n of e.folders.values())o(n,t);for(let n of e.assets)a(n,t);t.children.length>0&&n.appendChild(t)}},s=Vj(r,t.pendingGroups);for(let t of s.assets)a(t,e);for(let t of s.folders.values())o(t,e)}function Wj(e,t,n){if(t.selection!==null)return!1;if(t.addingGroup){e.appendChild(oM(t.newGroupParent?`NEW GROUP IN ${t.newGroupParent}/`:`NEW GROUP`));let n=document.createElement(`input`);n.placeholder=t.newGroupParent?`heroes`:`characters (or a/b to nest)`,n.className=`mono`,e.appendChild(Xj(`name`,n));let r=document.createElement(`button`);r.type=`button`,r.className=`primary`,r.textContent=`add`;let i=()=>{let e=n.value.trim().replace(/^\/+|\/+$/g,``);e&&(t.cancelAddForms(),t.addGroup(t.newGroupParent?`${t.newGroupParent}/${e}`:e))};r.addEventListener(`click`,i),n.addEventListener(`keydown`,e=>{e.key===`Enter`&&i()});let a=document.createElement(`div`);return a.className=`pop-actions`,a.appendChild(r),e.appendChild(a),setTimeout(()=>n.focus(),0),!0}if(t.addingAsset)return Jj(e,t);if(t.selectedGroup!==null){let r=t.selectedGroup,i=t.groupCount(r);e.appendChild(oM(`GROUP (${i} asset${i===1?``:`s`})`));let a=r.includes(`/`)?r.slice(0,r.lastIndexOf(`/`)+1):``,o=r.includes(`/`)?r.slice(r.lastIndexOf(`/`)+1):r;e.appendChild(Zj(`name`,o,e=>{let n=e.trim().replace(/\/+/g,``);n&&n!==o&&t.renameGroup(r,a+n)}));let s=document.createElement(`button`);return s.type=`button`,s.className=`ghost danger`,s.textContent=`delete group`,s.addEventListener(`click`,()=>{if(i===0){t.deleteGroup(r);return}n(`'${r}/' contains ${i} asset${i===1?``:`s`} — deleting the group deletes them too.`,`delete group & assets`,()=>t.deleteGroup(r))}),e.appendChild(s),!0}let r=t.selectedAsset;if(r===null)return!1;let i=t.working.assets??{};if(!(r in i))return!1;e.appendChild(oM(`ASSET — ${String(i[r].type??`?`)}`)),e.appendChild(rM(r)),e.appendChild(iM(t,r)),e.appendChild(Gj(t,i,r));let a=document.createElement(`button`);return a.type=`button`,a.className=`ghost danger`,a.textContent=`delete asset`,a.addEventListener(`click`,()=>{t.selectAsset(null),t.mutate(()=>{delete i[r],Object.keys(i).length===0&&delete t.working.assets})}),e.appendChild(a),!0}function Gj(e,t,n){let r=t[n],i=document.createElement(`div`);i.className=`asset-editor`;let a=n.includes(`/`)?n.slice(n.lastIndexOf(`/`)+1):n,o=n.includes(`/`)?n.slice(0,n.lastIndexOf(`/`)+1):``,s=Zj(`name`,a,t=>{let r=t.trim().replace(/^\$/,``).replace(/\//g,``);r&&r!==a&&e.renameAssetKey(n,o+r)});aM(s.querySelector(`input`)),i.appendChild(s),i.appendChild(Zj(`url`,String(r.url??``),t=>{e.mutate(()=>{r.url=t.trim()})}));let c=document.createElement(`div`);c.className=`muted-note`,c.textContent=`meta (key · value)`,i.appendChild(c);for(let[t,n]of Object.entries(r))t===`type`||t===`url`||i.appendChild(Kj(e,r,t,n));return i.appendChild(qj(e,r)),i}function Kj(e,t,n,r){let i=document.createElement(`div`);i.className=`meta-row`;let a=document.createElement(`input`);a.value=n,a.className=`mono`;let o=document.createElement(`input`);o.value=typeof r==`string`?r:JSON.stringify(r),o.className=`mono`;let s=()=>{let r=a.value.trim();e.mutate(()=>{delete t[n],r&&(t[r]=Qj(o.value))})};a.addEventListener(`change`,s),o.addEventListener(`change`,s);let c=document.createElement(`button`);return c.type=`button`,c.className=`linklike danger-link`,c.textContent=`✕`,c.addEventListener(`click`,()=>{e.mutate(()=>{delete t[n]})}),i.append(a,o,c),i}function qj(e,t){let n=document.createElement(`div`);n.className=`meta-row`;let r=document.createElement(`input`);r.placeholder=`filter…`,r.className=`mono`;let i=document.createElement(`input`);i.placeholder=`nearest`,i.className=`mono`;let a=()=>{let n=r.value.trim();!n||i.value.trim()===``||e.mutate(()=>{t[n]=Qj(i.value)})};return r.addEventListener(`change`,a),i.addEventListener(`change`,a),n.append(r,i,document.createElement(`span`)),n}function Jj(e,t){return e.appendChild(oM(`NEW ASSET`)),e.appendChild(Yj(t)),!0}function Yj(e){let t=document.createElement(`div`);t.className=`asset-editor`;let n=document.createElement(`select`);for(let e of Ij){let t=document.createElement(`option`);t.value=e.type,t.textContent=e.label,n.appendChild(t)}t.appendChild(Xj(`type`,n));let r=document.createElement(`input`);r.placeholder=`(optional) characters`,r.className=`mono`,r.value=e.newAssetGroup;let i=`asset-groups-list`;r.setAttribute(`list`,i);let a=document.createElement(`datalist`);a.id=i;let o=new Set;for(let t of Object.keys(e.working.assets??{})){let e=t.lastIndexOf(`/`);e!==-1&&o.add(t.slice(0,e))}for(let t of e.pendingGroups)o.add(t);for(let e of o){let t=document.createElement(`option`);t.value=e,a.appendChild(t)}t.appendChild(Xj(`group`,r)),t.appendChild(a);let s=document.createElement(`input`);s.placeholder=`coin`,s.className=`mono`,aM(s),t.appendChild(Xj(`key`,s));let c=document.createElement(`input`);c.placeholder=`/textures/coin.png · https://… · data:…`,c.className=`mono`,t.appendChild(Xj(`url`,c));let l=document.createElement(`textarea`);l.rows=2,l.placeholder=`or paste a JSON object: { "type": "model", "url": "/m.glb" }`,t.appendChild(l);let u=document.createElement(`button`);u.type=`button`,u.className=`primary`,u.textContent=`add`,u.addEventListener(`click`,()=>{let t=s.value.trim().replace(/^\$/,``);if(!t)return;let i=r.value.trim().replace(/\/+$/,``),a=i?`${i}/${t}`:t,o=null,u=l.value.trim();if(u)try{o=JSON.parse(u)}catch{l.classList.add(`invalid`);return}else c.value.trim()&&(o={type:n.value,url:c.value.trim()});o&&(e.cancelAddForms(),e.selectedAsset=a,e.mutate(()=>{e.working.assets||(e.working.assets={});let t=e.working.assets;t[a]=o}))});let d=document.createElement(`div`);return d.className=`pop-actions`,d.appendChild(u),t.appendChild(d),t}function Xj(e,t){let n=document.createElement(`label`);n.className=`field`;let r=document.createElement(`span`);return r.textContent=e,n.append(r,t),n}function Zj(e,t,n){let r=document.createElement(`input`);return r.value=t,r.className=`mono`,r.addEventListener(`change`,()=>n(r.value)),Xj(e,r)}function Qj(e){let t=e.trim();if(t===`true`)return!0;if(t===`false`)return!1;if(t!==``&&Number.isFinite(Number(t)))return Number(t);if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return e}return e}var $j={texture:`M3 5h18v14H3z M3 15l5-5 4 4 3-3 6 6 M8.5 9.5h.01`,spritesheet:`M3 4h18v16H3z M9 4v16 M15 4v16 M3 12h18`,model:`M12 2l9 5v10l-9 5-9-5V7z M12 12l9-5 M12 12L3 7 M12 12v10`,animation:`M12 2a10 10 0 1 0 10 10 M22 12l-3-3m3 3l3-3 M12 7v5l3 3`},eM={texture:{en:`image (texture) — Sprite2D.texture references it as "$key".`,ko:`이미지(텍스처) — Sprite2D.texture에서 "$키"로 참조합니다.`},spritesheet:{en:`spritesheet — AnimatedSprite2D slices it into named frame animations.`,ko:`스프라이트시트 — AnimatedSprite2D가 이름 붙은 프레임 애니메이션으로 자릅니다.`},model:{en:`3D model (GLB/glTF/VRM) — ModelInstance3D.model references it as "$key".`,ko:`3D 모델(GLB/glTF/VRM) — ModelInstance3D.model에서 "$키"로 참조합니다.`},animation:{en:`animation clips (GLB, in memory — drawn nowhere) — any model can play them; mixamo retargets onto VRM.`,ko:`애니메이션 클립(GLB, 메모리 전용 — 그려지지 않음) — 어떤 모델이든 재생 가능, mixamo는 VRM에 자동 리타게팅.`}};function tM(e){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);t.setAttribute(`viewBox`,`0 0 24 24`),t.setAttribute(`width`,`13`),t.setAttribute(`height`,`13`),t.setAttribute(`fill`,`none`),t.setAttribute(`stroke`,`currentColor`),t.setAttribute(`stroke-width`,`1.8`),t.setAttribute(`aria-hidden`,`true`);let n=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);return n.setAttribute(`d`,$j[e]??`M4 4h16v16H4z`),t.appendChild(n),t.classList.add(`asset-icon-${e}`),t}function nM(e,t){document.querySelector(`.balloon`)?.remove();let n=eM[t];if(!n)return;let r=document.createElement(`div`);r.className=`balloon floating`;let i=document.createElement(`div`);i.className=`balloon-title`,i.textContent=t;let a=document.createElement(`span`);a.textContent=jj(n),r.append(i,a),document.body.appendChild(r);let o=e.getBoundingClientRect();r.style.left=`${o.right+8}px`,r.style.top=`${Math.max(8,o.top-8)}px`;let s=()=>{r.remove(),document.removeEventListener(`pointerdown`,s,!0)};setTimeout(()=>document.addEventListener(`pointerdown`,s,!0),0)}function rM(e){let t=document.createElement(`div`);t.className=`field uid-line`;let n=document.createElement(`span`);n.textContent=`key`;let r=document.createElement(`div`);r.className=`uid-value`;let i=document.createElement(`code`);i.textContent=`$${e}`;let a=document.createElement(`button`);return a.type=`button`,a.className=`uid-copy`,a.title=`Copy key`,a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,a.addEventListener(`click`,()=>{navigator.clipboard?.writeText(`$${e}`),a.classList.add(`copied`),setTimeout(()=>a.classList.remove(`copied`),600)}),r.append(i,a),t.append(n,r),t}function iM(e,t){let n=t.includes(`/`)?t.slice(0,t.lastIndexOf(`/`)):``,r=document.createElement(`select`),i=new Set([``]);for(let t of Object.keys(e.working.assets??{})){let e=t.split(`/`);for(let t=1;t<e.length;t++)i.add(e.slice(0,t).join(`/`))}for(let t of e.pendingGroups)i.add(t);for(let e of[...i].sort()){let t=document.createElement(`option`);t.value=e,t.textContent=e===``?`(root)`:`${e}/`,e===n&&(t.selected=!0),r.appendChild(t)}r.addEventListener(`change`,()=>{e.moveAsset(t,r.value)});let a=document.createElement(`label`);a.className=`field`;let o=document.createElement(`span`);return o.textContent=`group`,a.append(o,r),a}function aM(e){e&&(e.addEventListener(`keydown`,e=>{e.key===`/`&&e.preventDefault()}),e.addEventListener(`input`,()=>{e.value.includes(`/`)&&(e.value=e.value.replace(/\//g,``))}))}function oM(e){let t=document.createElement(`div`);t.className=`section-title`,t.textContent=e;let n=document.createElement(`span`);return n.className=`rule`,t.appendChild(n),t}var sM=window.parent!==window,cM=new URLSearchParams(window.location.search).get(`parentOrigin`),lM=!1;function uM(e){if(sM){if(!cM){lM||(lM=!0,console.warn(`incanto-editor: embedded without ?parentOrigin=<origin> — postMessage disabled`));return}window.parent.postMessage(e,cM)}}var dM={ready(e,t,n){uM({type:`incanto-editor:ready`,input:e,output:t,version:n})},open(e,t){uM({type:`incanto-editor:open`,input:e,output:t})},change(e){uM({type:`incanto-editor:change`,dirty:e})},save(e,t,n){uM({type:`incanto-editor:save`,input:e,output:t,data:n})},error(e){uM({type:`incanto-editor:error`,message:e})}},fM=[[`Core`,e=>!e.endsWith(`2D`)&&!e.endsWith(`3D`)&&e!==`Label`&&e!==`UILayer`&&e!==`NetworkSpawner`],[`2D`,e=>e.endsWith(`2D`)&&!/Body|Area|Controller/.test(e)||e===`Label`||e===`UILayer`],[`2D Physics`,e=>e.endsWith(`2D`)&&/Body|Area|Controller/.test(e)],[`3D`,e=>e.endsWith(`3D`)&&!/Body|Area|Controller/.test(e)],[`3D Physics`,e=>e.endsWith(`3D`)&&/Body|Area|Controller/.test(e)],[`Network`,e=>e===`NetworkSpawner`]],pM=[...fM,[`Other`,e=>fM.every(([,t])=>!t(e))]],mM={title:{en:`How Incanto scenes work`,ko:`Incanto 씬은 어떻게 동작하나`},sections:[{heading:{en:`Everything is a node in a tree`,ko:`모든 것은 트리 위의 노드`},text:{en:`A scene is ONE tree of typed nodes (Godot-style). Each node has a name (unique among its siblings), a type that defines its props and behavior, optional children, and an optional scene-wide-unique uid. The whole structure lives in a *.scene.json file — there is no hidden state: what you see in this editor IS the file.`,ko:`씬은 타입을 가진 노드들의 단일 트리입니다(Godot 방식). 각 노드는 이름(형제 간 유일), props와 동작을 결정하는 타입, 선택적 자식들, 그리고 선택적인 씬 전역 유일 uid를 가집니다. 전체 구조가 *.scene.json 파일 하나에 들어있고 숨겨진 상태는 없습니다 — 이 에디터에서 보는 것이 곧 파일 그 자체입니다.`}},{heading:{en:`Props are delta-only`,ko:`Props는 변경분만 기록`},text:{en:`Every prop has a default defined by the engine. The JSON only stores values that DIFFER from the default — so files stay small and diffs stay meaningful. This editor follows the same rule: set a value back to its default and it disappears from the file.`,ko:`모든 prop에는 엔진이 정의한 기본값이 있습니다. JSON에는 기본값과 다른 값만 기록되어 파일이 작고 diff가 의미를 가집니다. 이 에디터도 같은 규칙을 따릅니다 — 값을 기본값으로 되돌리면 파일에서 사라집니다.`}},{heading:{en:`Addressing: paths, names, uid, groups`,ko:`노드 찾기: 경로·이름·uid·그룹`},text:{en:`Code reaches nodes four ways: a path like "Player/Skin" (relative) or "%Unique" (marked-unique name), getNodesByName("Enemy") which returns a LIST (names repeat across the tree), getNodeByUid("n_x1y2") which returns exactly one node and survives moves/renames, and groups — free tags for queries like "every coin".`,ko:`코드는 네 가지 방법으로 노드에 접근합니다: "Player/Skin" 같은 경로(상대) 또는 "%Unique"(유일 표시 이름), 트리 전체에서 같은 이름을 모두 찾는 getNodesByName("Enemy") — 이름은 중복될 수 있어 리스트가 돌아옵니다 —, 정확히 한 노드를 돌려주고 이동/개명에도 살아남는 getNodeByUid("n_x1y2"), 그리고 "모든 코인"처럼 묶어 조회하는 자유 태그 groups.`}},{heading:{en:`Signals connect, behaviors act`,ko:`시그널로 잇고 비헤이비어로 움직인다`},text:{en:`Nodes emit signals (an Area2D fires triggerEnter, a Timer fires timeout). The scene's "connections" wire a signal to a handler — declaratively, in JSON. Game logic itself is a Behavior: a TypeScript class in YOUR game, attached by name via "script". The editor shows and edits these links but the code lives in the game.`,ko:`노드는 시그널을 발산합니다(Area2D의 triggerEnter, Timer의 timeout). 씬의 "connections"가 시그널을 핸들러에 선언적으로(JSON으로) 연결합니다. 게임 로직 자체는 Behavior — 게임 쪽 TypeScript 클래스이며 "script"에 이름으로 연결됩니다. 에디터는 이 연결을 보여주고 편집하지만 코드는 게임에 있습니다.`}},{heading:{en:`Assets are declared, then referenced`,ko:`에셋은 선언하고 $키로 참조`},text:{en:`The scene header declares assets (textures, spritesheets, 3D models, animation clips) under a key; nodes reference them as "$key". Animations are data too: an {type:"animation"} asset loads GLB clips into memory and any ModelInstance3D can play them — Mixamo clips retarget onto VRM avatars automatically.`,ko:`씬 헤더에서 에셋(텍스처·스프라이트시트·3D 모델·애니메이션 클립)을 키로 선언하고, 노드는 "$key"로 참조합니다. 애니메이션도 데이터입니다 — {type:"animation"} 에셋이 GLB 클립을 메모리에 올리고 어떤 ModelInstance3D든 재생할 수 있으며, Mixamo 클립은 VRM 아바타에 자동 리타게팅됩니다.`}}]},Z=(e,t,...n)=>({type:e,summary:t,body:n}),hM=[{id:`core`,label:{en:`Core`,ko:`Core`},intro:{en:`Dimension-free building blocks: plain containers and the game clock. They render nothing themselves.`,ko:`차원과 무관한 기본 블록 — 순수 컨테이너와 게임 시계입니다. 스스로는 아무것도 그리지 않습니다.`},nodes:[Z(`Node`,{en:`A plain container with no transform.`,ko:`변환 없이 자식을 묶는 순수 컨테이너.`},{en:`Use it to group related nodes (all coins, all UI) without affecting their positions. Lifecycle, signals, groups, script — everything works; it just has no visual or spatial meaning of its own.`,ko:`위치에 영향을 주지 않으면서 관련 노드(코인 전부, UI 전부)를 묶을 때 씁니다. 라이프사이클·시그널·그룹·스크립트가 모두 동작하며, 시각적·공간적 의미만 없습니다.`}),Z(`Timer`,{en:"A serializable countdown that emits `timeout`.",ko:"`timeout` 시그널을 쏘는 직렬화 가능한 카운트다운."},{en:`Set waitTime (seconds), optionally autostart or oneShot, and connect its timeout signal to any handler. Because it is a node, the whole timing setup lives in the scene file — agents can read and tune it.`,ko:`waitTime(초)을 정하고 autostart·oneShot을 선택한 뒤 timeout 시그널을 핸들러에 연결하세요. 노드이기 때문에 타이밍 설정 전체가 씬 파일에 남아 에이전트가 읽고 조정할 수 있습니다.`}),Z(`HudLayer`,{en:`Screen-space HUD overlay above the canvas — parent for UiText/UiBar/UiBanner.`,ko:`캔버스 위 화면 고정 HUD 오버레이 — UiText/UiBar/UiBanner의 부모.`},{en:`A DOM overlay (position:fixed) that never blocks pointer input. Put UI widgets as children; each picks one of 9 anchors (topLeft…bottomRight). Works identically over 2D and 3D renderers; in headless/tests it is a silent no-op. zIndex lifts it above the canvas.`,ko:`포인터 입력을 가로막지 않는 DOM 오버레이(position:fixed)입니다. UI 위젯을 자식으로 두면 각자 9개 앵커(topLeft…bottomRight) 중 하나에 붙습니다. 2D·3D 렌더러 어디서나 동일하게 동작하고, 헤드리스/테스트에서는 조용히 no-op입니다. zIndex로 캔버스 위에 올립니다.`}),Z(`UiText`,{en:`A HUD text line — score, timers, hints.`,ko:`HUD 텍스트 한 줄 — 점수, 타이머, 힌트.`},{en:`Child of HudLayer. Set text/size/color in JSON; update from behaviors: (getNode('%Score') as UiText).text = String(score). shadow adds a soft outline for readability over any scene.`,ko:`HudLayer의 자식. text/size/color를 JSON으로 정하고, 비헤이비어에서 (getNode('%Score') as UiText).text = String(score) 로 갱신하세요. shadow는 어떤 화면 위에서도 읽히도록 부드러운 그림자를 더합니다.`}),Z(`UiBar`,{en:`A labeled progress bar — health, stamina, reload, boss HP.`,ko:`라벨 달린 진행 바 — 체력, 스태미나, 재장전, 보스 HP.`},{en:`Child of HudLayer. Drive value/max from behaviors; the fill animates and turns lowColor under lowThreshold (default 30%). width/height/color/background style it; label prefixes a small caption.`,ko:`HudLayer의 자식. 비헤이비어에서 value/max를 갱신하면 채움이 애니메이션되고 lowThreshold(기본 30%) 아래로 떨어지면 lowColor로 바뀝니다. width/height/color/background로 스타일, label로 작은 캡션을 붙입니다.`}),Z(`UiBanner`,{en:`Center-screen announcements with fade and a queue — "WAVE 2", "YOU DIED".`,ko:`페이드·큐가 있는 중앙 공지 — "WAVE 2", "YOU DIED".`},{en:`Child of HudLayer. Call show('WAVE 2', { color, seconds }) from behaviors; messages queue and fade in/out. seconds 0 = sticky until the next show(). clear() drops everything. Emits bannerShown(text).`,ko:`HudLayer의 자식. 비헤이비어에서 show('WAVE 2', { color, seconds })를 호출하면 메시지가 큐에 쌓여 페이드 인/아웃됩니다. seconds 0이면 다음 show()까지 고정, clear()로 전부 제거. bannerShown(text) 시그널을 냅니다.`}),Z(`UiButton`,{en:`A clickable HUD button — menus, START screens, dialog choices.`,ko:`클릭 가능한 HUD 버튼 — 메뉴, 시작 화면, 대화 선택지.`},{en:`Child of HudLayer. Set text/size/color/background; disabled greys it out. Emits the 'pressed' signal (behaviors: node.on('pressed', ...)); press() triggers it programmatically (gamepad menus, tests).`,ko:`HudLayer의 자식. text/size/color/background를 설정하고 disabled로 비활성화합니다. 'pressed' 시그널을 내며(비헤이비어에서 node.on('pressed', ...)), press()로 코드에서도 누를 수 있습니다(게임패드 메뉴, 테스트).`}),Z(`UiDialogue`,{en:`A typewriter dialogue box with a queue and choice buttons — the RPG conversation layer.`,ko:`타자기 효과·큐·선택지 버튼을 갖춘 대화창 — RPG 대화 레이어.`},{en:`Child of HudLayer (anchor bottom by default). say(speaker, text, choices?) queues lines; clicking (or advance()) reveals then advances; choice lines wait for choose(i). Signals: lineShown(text), choiceMade(index), dialogueFinished. charsPerSecond 0 = instant. Check .active to pause player input during conversations.`,ko:`HudLayer의 자식(기본 anchor bottom). say(화자, 텍스트, 선택지?)로 줄을 큐에 넣고, 클릭(또는 advance())이 전체 공개→다음 줄로 진행하며, 선택지 줄은 choose(i)를 기다립니다. 시그널: lineShown(text), choiceMade(index), dialogueFinished. charsPerSecond 0이면 즉시 표시. 대화 중 플레이어 입력을 멈추려면 .active를 확인하세요.`}),Z(`AudioPlayer`,{en:`Plays a sound: zero-asset procedural SFX, BGM loops, or one-shot effects.`,ko:`소리 재생 — 무에셋 절차적 효과음, 배경음 루프, 단발 효과음.`},{en:`Set preset (coin/jump/hurt/explosion/…) for an instant zero-asset SFX (pitch/seed vary it), or leave it "custom" and set src (URL or "$assetKey"). volume 0..1; bus routes through engine.audio (sfx|music) for global volume/mute; loop for music; autoplay starts on ready (browsers may hold it until the first user gesture). Call play()/stop() from game code. Dimension-free — 2D and 3D alike.`,ko:`preset(coin/jump/hurt/explosion/…)을 설정하면 즉시 무에셋 효과음이 납니다(pitch·seed로 변형). 아니면 "custom"으로 두고 src(URL 또는 "$에셋키")를 쓰세요. volume은 0..1, bus는 engine.audio(sfx|music)를 통해 전역 볼륨/음소거에 연결, 음악은 loop, autoplay는 준비되면 재생합니다(브라우저가 첫 입력까지 보류 가능). 게임 코드에서 play()/stop()을 부르세요. 2D·3D 어디서나 동작합니다.`})]},{id:`2d`,label:{en:`2D`,ko:`2D`},intro:{en:`The 2D world is y-down pixels: 1 unit = 1 px, (0,0) top-left, rotation in clockwise degrees. Rendering needs a current Camera2D.`,ko:`2D 세계는 y-아래 픽셀 좌표입니다: 1유닛=1px, (0,0)은 좌상단, 회전은 시계방향 도(degree). 렌더링에는 current 카메라(Camera2D)가 필요합니다.`},nodes:[Z(`Node2D`,{en:`The 2D transform container (position/rotation/scale).`,ko:`2D 변환 컨테이너(position/rotation/scale).`},{en:`Children inherit its transform — move the parent, everything follows. renderOrder orders drawing; visible hides the subtree.`,ko:`자식은 변환을 상속합니다 — 부모를 움직이면 전부 따라옵니다. renderOrder로 그리기 순서를, visible로 서브트리 표시를 제어합니다.`}),Z(`Sprite2D`,{en:`A textured quad.`,ko:`텍스처 사각형(스프라이트).`},{en:`texture is "$assetKey" from the scene assets. anchor [0.5,0.5] centers; flipX/flipY mirror; tint multiplies color; opacity fades. Size comes from the texture × scale.`,ko:`texture는 씬 에셋의 "$키"입니다. anchor [0.5,0.5]면 중앙 기준, flipX/flipY로 반전, tint로 색 곱, opacity로 투명도. 크기는 텍스처 × scale로 정해집니다.`}),Z(`ColorRect2D`,{en:`A flat colored rectangle — no texture needed.`,ko:`단색 사각형 — 텍스처 불필요.`},{en:`size [w,h] px, color, opacity, anchor. Backgrounds, platforms, walls, UI panels, generated-level tiles (maze2d/dungeon2d emit these) — blocky art without any asset.`,ko:`size [w,h] px, color, opacity, anchor. 배경·플랫폼·벽·UI 패널·생성 레벨 타일(maze2d/dungeon2d가 이걸 만듭니다) — 에셋 없이 만드는 블록 그래픽입니다.`}),Z(`TileMap2D`,{en:`A whole tile level as ONE node — grid render + merged static colliders.`,ko:`타일 레벨 전체를 노드 하나로 — 그리드 렌더 + 병합된 정적 콜라이더.`},{en:`Author cells as rows of characters: "." / space = empty, digits 0-9 = atlas tile index, other chars map through legend ({"G": 12}). texture is a "$atlas" asset read left-to-right top-to-bottom in tileSize squares (columns: 0 derives from the texture width). Tile indices listed in solid become static colliders, greedy-merged into a few rectangles. Cell (0,0) hangs its top-left on the node origin.`,ko:`cells를 문자 행으로 작성합니다: "."/공백 = 빈 칸, 숫자 0-9 = 아틀라스 타일 번호, 그 외 문자는 legend({"G": 12})로 매핑. texture는 tileSize 정사각형을 좌→우, 상→하로 읽는 "$아틀라스" 에셋입니다(columns: 0이면 텍스처 폭에서 유도). solid에 나열된 타일 번호는 정적 콜라이더가 되며 소수의 직사각형으로 탐욕 병합됩니다. (0,0) 칸의 좌상단이 노드 원점에 걸립니다.`}),Z(`AnimatedSprite2D`,{en:`Spritesheet animation player.`,ko:`스프라이트시트 애니메이션 플레이어.`},{en:`Point sheet at a "$sheet" asset, define animations as named frame ranges with fps/loop in JSON, set autoplay. Emits animationFinished(name) for one-shot chains.`,ko:`sheet에 "$시트" 에셋을 연결하고, JSON에 fps/loop를 가진 이름별 프레임 구간으로 animations를 정의한 뒤 autoplay를 지정하세요. 단발 애니메이션 연결을 위해 animationFinished(name)를 발산합니다.`}),Z(`Camera2D`,{en:`The 2D view: follow, zoom, limits.`,ko:`2D 시점 — 추적·줌·경계.`},{en:`position is the view CENTER. follow tracks a node path with smoothing (0..1, higher = snappier). limits [minX,minY,maxX,maxY] clamps the view inside a world region. current: true makes it THE camera.`,ko:`position은 화면의 중심입니다. follow가 노드 경로를 smoothing(0..1, 높을수록 빠릿)으로 추적합니다. limits [minX,minY,maxX,maxY]가 시점을 월드 영역 안에 가둡니다. current: true인 카메라가 실제 시점이 됩니다.`}),Z(`Particles2D`,{en:`A 2D particle emitter (fire, sparks, smoke…).`,ko:`2D 파티클 이미터(불·스파크·연기…).`},{en:`Start from a preset (fire/smoke/sparks/…) then override any prop: rate, lifetime/speed ranges, direction + spread, gravity, size/color/alpha start→end, additive blend. burst > 0 with emitting: false makes a one-shot that emits finished. Animates LIVE in this editor.`,ko:`preset(fire/smoke/sparks/…)에서 시작해 어떤 prop이든 덮어쓰세요: rate, lifetime/speed 구간, direction+spread, gravity, size/color/alpha 시작→끝, additive blend. emitting: false에 burst > 0이면 단발 발사 후 finished를 발산합니다. 이 에디터에서 라이브로 움직입니다.`}),Z(`Label`,{en:`Text rendered to a quad.`,ko:`텍스트를 그리는 노드.`},{en:`text/fontSize/color/font/align — rendered via CanvasTexture, so any system font string works. Inside a UILayer it pins to the screen (HUD).`,ko:`text/fontSize/color/font/align — CanvasTexture로 그려져 시스템 폰트 문자열을 그대로 쓸 수 있습니다. UILayer 아래에 두면 화면에 고정됩니다(HUD).`}),Z(`UILayer`,{en:`A screen-space subtree (HUD).`,ko:`화면 고정 서브트리(HUD).`},{en:`Everything under it ignores the camera: positions are screen pixels from the top-left. Score counters, prompts, menus go here.`,ko:`이 아래의 모든 것은 카메라를 무시합니다 — 좌상단 기준 화면 픽셀 좌표입니다. 점수, 안내 문구, 메뉴를 여기에 둡니다.`})]},{id:`2d-physics`,label:{en:`2D Physics`,ko:`2D 물리`},intro:{en:`Rapier-backed. Colliders are PROPS ({shape, …}) — the green dashed wireframes in this editor. Physics runs when the game calls enablePhysics2D (and in play mode). Gravity lives on the scene row.`,ko:`Rapier 기반입니다. 콜라이더는 prop({shape, …})이며 에디터의 초록 점선이 그것입니다. 물리는 게임이 enablePhysics2D를 부를 때(그리고 플레이 모드에서) 돌고, 중력은 씬 행에 있습니다.`},nodes:[Z(`StaticBody2D`,{en:`Immovable collision: ground, walls, platforms.`,ko:`움직이지 않는 충돌체 — 바닥·벽·플랫폼.`},{en:`Other bodies collide with it; it never moves. Cheapest body type — use it for all level geometry.`,ko:`다른 바디가 부딪히지만 자신은 절대 움직이지 않습니다. 가장 저렴한 바디 — 레벨 지형 전부에 쓰세요.`}),Z(`RigidBody2D`,{en:`Fully simulated: falls, bounces, pushes.`,ko:`완전 시뮬레이션 — 떨어지고 튕기고 밀립니다.`},{en:`Gravity and collisions drive it. Set linearVelocity to launch. For player characters prefer CharacterBody2D (direct control).`,ko:`중력과 충돌이 움직임을 결정합니다. linearVelocity로 발사하세요. 플레이어 캐릭터에는 직접 제어가 가능한 CharacterBody2D를 권합니다.`}),Z(`CharacterBody2D`,{en:`Kinematic character: you set velocity, it slides.`,ko:`키네마틱 캐릭터 — 속도를 주면 미끄러지듯 이동.`},{en:`moveAndSlide() resolves collisions without physics pushing back; isOnFloor() gates jumps. Sensors (Area2D) do not block it but still fire triggers.`,ko:`moveAndSlide()가 밀려나지 않으면서 충돌을 처리하고 isOnFloor()로 점프를 판정합니다. 센서(Area2D)는 길을 막지 않으면서 트리거를 발사합니다.`}),Z(`Area2D`,{en:`A sensor: overlap triggers, no collision response.`,ko:`센서 — 겹침 감지만, 충돌 반응 없음.`},{en:`Fires triggerEnter(other)/triggerExit(other). Coins, checkpoints, damage zones. Filter with other.isInGroup("player").`,ko:`triggerEnter(other)/triggerExit(other)를 발산합니다. 코인·체크포인트·데미지 존에 쓰고, other.isInGroup("player")로 거릅니다.`}),Z(`CharacterController2D`,{en:`Zero-code platformer/top-down movement.`,ko:`코드 없는 플랫포머/탑다운 이동.`},{en:`Put it UNDER a CharacterBody2D. mode "platformer" (gravity + jump via jumpAction) or "topDown" (free 2-axis). Reads the scene input map actions (moveAction/jumpAction). maxSpeed/jumpHeight are intent-level numbers.`,ko:`CharacterBody2D의 자식으로 두세요. mode는 "platformer"(중력+jumpAction 점프) 또는 "topDown"(자유 2축)이며 씬 입력 맵의 액션(moveAction/jumpAction)을 읽습니다. maxSpeed/jumpHeight는 의도 그대로의 숫자입니다.`}),Z(`Joint2D`,{en:`A physics joint linking its parent body to a target body — weld, hinge, rope, spring.`,ko:`부모 바디와 대상 바디를 잇는 물리 조인트 — 용접, 힌지, 로프, 스프링.`},{en:`Child of body A (a physics body); "target" is a node path to body B. type: fixed (rigid weld) / revolute (pin at the anchors) / rope (caps anchor distance at length px; 0 = measured at creation) / spring (pulls toward length with stiffness/damping). anchor/targetAnchor are LOCAL px offsets.`,ko:`바디 A(물리 바디)의 자식으로 두고 "target"에 바디 B의 노드 경로를 줍니다. type: fixed(강체 용접) / revolute(앵커 핀 힌지) / rope(앵커 간 거리를 length px로 제한, 0이면 생성 시 실측) / spring(stiffness/damping으로 length를 향해 당김). anchor/targetAnchor는 로컬 px 오프셋.`})]},{id:`3d`,label:{en:`3D`,ko:`3D`},intro:{en:`Meters, y-up, rotations in degrees. Standard materials need LIGHT — add a DirectionalLight3D or scene ambient, or you get silhouettes.`,ko:`미터 단위, y-위, 회전은 도(degree)입니다. 표준 머티리얼은 빛이 필요합니다 — DirectionalLight3D나 씬 ambient가 없으면 실루엣만 보입니다.`},nodes:[Z(`Node3D`,{en:`The 3D transform container.`,ko:`3D 변환 컨테이너.`},{en:`position [x,y,z] in meters, rotation [x,y,z] in degrees, scale per axis. Children inherit.`,ko:`position [x,y,z] 미터, rotation [x,y,z] 도, scale은 축별. 자식이 상속합니다.`}),Z(`MeshInstance3D`,{en:`A primitive mesh + material.`,ko:`프리미티브 메시 + 머티리얼.`},{en:`mesh: box/sphere/plane/cylinder…, size per primitive, material {color, roughness, metalness, emissive, emissiveIntensity, wireframe, map, normalMap, repeat} (this editor gives it swatches, sliders, texture-URL fields, and a repeat [u,v] tiling vector). map/normalMap are texture URLs; repeat only takes effect with a map. castShadow/receiveShadow per node.`,ko:`mesh: box/sphere/plane/cylinder…, 프리미티브별 size, material {color, roughness, metalness, emissive, emissiveIntensity, wireframe, map, normalMap, repeat}(에디터가 스와치·슬라이더·텍스처 URL 입력·repeat [u,v] 타일링 벡터 제공). map/normalMap은 텍스처 URL, repeat는 map이 있을 때만 적용. 그림자는 castShadow/receiveShadow.`}),Z(`LoftMesh3D`,{en:`A smooth swept hull (loft).`,ko:`부드러운 스윕 선체(로프트).`},{en:`sections: ≥2 cross-section stations {z, width, height, y, corner 0..1} interpolated into ONE smooth curved surface — vehicle bodies, glass canopies, boat hulls. slices/smooth control tessellation. Same material as MeshInstance3D minus textures (no UVs); pair clearcoat paint or high-envMapIntensity glass with the smooth normals for the automotive look.`,ko:`sections: 단면 스테이션 {z, width, height, y, corner 0..1} 2개 이상을 보간해 하나의 매끈한 곡면을 만듭니다 — 차체, 유리 캐노피, 선체. slices/smooth로 테셀레이션 조절. material은 MeshInstance3D와 동일하되 텍스처 제외(UV 없음). clearcoat 도장이나 높은 envMapIntensity 유리를 곡면 법선과 조합하면 자동차 룩이 납니다.`}),Z(`ModelInstance3D`,{en:`A GLB/glTF/VRM model file.`,ko:`GLB/glTF/VRM 모델 파일.`},{en:'model: "$assetKey" or URL. targetHeight scales the model to stand N units tall (run `npx incanto-model file.glb` to read its real size first). animation plays an embedded clip name OR an "$animation" asset — Mixamo clips retarget onto VRM humanoids automatically. One node per VRM asset (the avatar runtime mounts live).',ko:'model은 "$에셋키" 또는 URL입니다. targetHeight가 모델을 N유닛 높이로 맞춥니다(먼저 `npx incanto-model 파일.glb`로 실제 크기를 확인하세요). animation은 내장 클립 이름 또는 "$애니메이션" 에셋을 재생하며, Mixamo 클립은 VRM 휴머노이드에 자동 리타게팅됩니다. VRM 에셋은 노드 하나만 쓸 수 있습니다(아바타 런타임이 라이브로 마운트됨).'}),Z(`Sprite3D`,{en:`A 2D image as a camera-facing billboard (the 2.5D look).`,ko:`카메라를 향하는 2D 빌보드 스프라이트(2.5D 룩).`},{en:`A textured quad that turns to face the camera inside the 3D world (Octopath / Don't Starve / MapleStory-in-3D). texture is an image URL; size is [w,h] in METERS. billboard: "y" stays upright with a screen-aligned yaw — off-center sprites never roll (characters/props), "full" faces it completely (items/FX), "none" is fixed to the node rotation. anchor [0.5,0] plants the feet on the ground. pixelArt nearest-filters for crisp pixels; alphaTest is a hard cutout that depth-sorts against 3D geometry (a tree occludes it); flipX mirrors left/right; tint/opacity recolor.`,ko:`3D 월드 안에서 카메라를 향해 도는 텍스처 쿼드(Octopath/Don't Starve, 3D 속 메이플스토리 룩). texture는 이미지 URL, size는 [너비,높이] 미터. billboard: "y"는 세로로 선 채 카메라 방향과 정렬된 yaw — 화면 가장자리에서도 기울지 않음(캐릭터/사물), "full"은 완전히 향함(아이템/FX), "none"은 노드 회전에 고정. anchor [0.5,0]은 발을 바닥에 둡니다. pixelArt는 nearest 필터로 픽셀을 또렷하게, alphaTest는 3D 지형과 깊이정렬되는 하드 컷아웃(나무가 가림), flipX는 좌우 반전, tint/opacity로 색·투명도.`}),Z(`AnimatedSprite3D`,{en:`A billboard sprite that plays spritesheet animations.`,ko:`스프라이트시트 애니를 재생하는 빌보드 스프라이트.`},{en:`Everything Sprite3D does, plus frame animation. sheet is a spritesheet image URL whose cells are frameWidth×frameHeight; animations maps a name to {frames, fps, loop} where frames is an inclusive [start,end] range or an explicit list; autoplay starts one on load. Game code calls play("walk") / stop(); a non-looping clip clamps on its last frame and emits animationFinished(name) — chain attack→idle from it.`,ko:`Sprite3D의 모든 기능 + 프레임 애니. sheet는 frameWidth×frameHeight 칸을 가진 스프라이트시트 URL, animations는 이름→{frames, fps, loop}(frames는 포함 [시작,끝] 범위 또는 명시 목록), autoplay는 로드 시 하나를 시작. 게임 코드에서 play("walk")/stop() 호출, 비반복 클립은 마지막 프레임에 머물며 animationFinished(name)를 emit(attack→idle 연결).`}),Z(`Billboard3D`,{en:`A group that turns toward the camera — children follow.`,ko:`카메라를 향해 도는 그룹 — 자식들이 함께 회전.`},{en:`A transform container that orients itself toward the camera every frame; children inherit the rotation, so hang world-space UI under it — HP bars, markers, floating icons (text is a canvas-rendered texture on a child Sprite3D). mode: "screen" (default) copies the camera orientation so a child rectangle stays an upright rectangle anywhere on screen (a yaw-only look-at visibly tilts off-center shapes under a pitched camera); "y" stays upright with a screen-aligned yaw (no off-center roll); "none" turns billboarding off. While billboarding, the node's own rotation prop (and the rotate gizmo) is overwritten every frame — switch to "none" to pose children, then switch back. Unlike Sprite3D (a textured quad that spins only its own image), Billboard3D rotates the whole group.`,ko:`매 프레임 카메라를 향해 자신을 회전시키는 변환 컨테이너로, 자식이 회전을 상속합니다 — HP바·마커·아이콘 같은 월드 UI를 자식으로 붙이세요(텍스트는 캔버스로 그린 텍스처를 자식 Sprite3D에). mode: "screen"(기본)은 카메라 자세를 그대로 복사해 자식 직사각형이 화면 어디서든 똑바른 직사각형으로 보입니다(yaw만 도는 look-at은 기울어진 카메라에서 중앙 밖 도형이 눈에 띄게 비스듬해짐); "y"는 세로로 선 채 카메라로 yaw만; "none"은 빌보드 끔. 빌보드 중에는 노드 자신의 rotation(회전 기즈모 포함)이 매 프레임 덮어써집니다 — 자식을 배치할 땐 "none"으로 바꿨다가 되돌리세요. 자기 그림만 도는 Sprite3D(텍스처 쿼드)와 달리 그룹 전체가 회전합니다.`}),Z(`Camera3D`,{en:`The 3D view.`,ko:`3D 시점.`},{en:`Perspective camera; fov in degrees; current: true selects it. Use the editor's "game cam" (0) to preview exactly what it renders.`,ko:`원근 카메라이며 fov는 도 단위, current: true가 실제 시점이 됩니다. 에디터의 "game cam"(0)으로 정확한 렌더 결과를 미리 보세요.`}),Z(`DirectionalLight3D`,{en:`Sun-like light from a direction.`,ko:`태양광 — 방향에서 평행하게.`},{en:`Position sets the direction toward the origin. intensity/color; pair with scene ambient for soft fill.`,ko:`위치가 원점을 향한 방향을 정합니다. intensity/color를 조절하고 부드러운 채움광은 씬 ambient와 함께 쓰세요.`}),Z(`OmniLight3D`,{en:`A point light radiating everywhere.`,ko:`점광 — 사방으로 퍼지는 빛.`},{en:`Lamps, torches, glows. range limits reach; intensity/color shape the falloff.`,ko:`램프·횃불·발광체. range로 도달 거리를, intensity/color로 감쇠를 만듭니다.`}),Z(`Particles3D`,{en:`A 3D particle emitter (fire, magic, weather…).`,ko:`3D 파티클 이미터(불·마법·날씨…).`},{en:`The same preset + override model as Particles2D, in meters with [x,y,z] gravity. Camera-facing billboard quads, instanced — hundreds are cheap. Animates LIVE in this editor.`,ko:`Particles2D와 같은 preset+덮어쓰기 모델을 미터 단위와 [x,y,z] 중력으로. 카메라를 향하는 빌보드 쿼드를 인스턴싱해 수백 개도 가볍습니다. 이 에디터에서 라이브로 움직입니다.`}),Z(`Terrain3D`,{en:`Procedural heightfield terrain with biome texture splatting.`,ko:`바이옴 텍스처 스플래팅이 적용된 절차적 하이트필드 지형.`},{en:`Seeded simplex hills displaced once on the CPU; theme (island/alpine/plains/desert/custom) picks the 4 blended biome textures by height and slope. heightAt(x,z) answers the surface height anywhere. For physics, parent it under a StaticBody3D with collider {shape:'heightfield'}.`,ko:`시드 기반 심플렉스 언덕을 CPU에서 한 번 변위합니다. theme(island/alpine/plains/desert/custom)이 높이·경사로 블렌딩되는 바이옴 텍스처 4장을 고릅니다. heightAt(x,z)로 어디서든 지표 높이를 얻고, 물리는 StaticBody3D 아래에 두고 collider {shape:'heightfield'}를 쓰세요.`}),Z(`Water3D`,{en:`A shader-water surface with splash signals.`,ko:`스플래시 신호를 내는 셰이더 물 표면.`},{en:`size [w,d] meters on XZ. quality 'fancy' (default) = FBM wave shader with a trough/surface/peak ramp (colors), CubeCamera reflections (reflection/reflectionInterval) and opt-in shoreline foam; 'simple' = the cheap sine material (color). Bodies crossing the surface emit entered/exited(body) and raise ripples (interaction). Volumetric gameplay still wants an Area3D. Waves animate LIVE in this editor.`,ko:`XZ 평면에 size [w,d] 미터. quality 'fancy'(기본)는 FBM 파도 셰이더 — trough/surface/peak 램프(colors), CubeCamera 반사(reflection/reflectionInterval), 옵트인 해안 거품(foam). 'simple'은 저사양용 사인파 머티리얼(color). 바디가 수면을 지나면 entered/exited(body) 신호와 물결이 일어납니다(interaction). 부피 기반 게임플레이엔 여전히 Area3D를 쓰세요. 이 에디터에서 파도가 라이브로 움직입니다.`}),Z(`River3D`,{en:`Running water derived from a path and the ground under it.`,ko:`경로와 그 아래 지형에서 유도되는 흐르는 물.`},{en:`Author a centerline path [[x,z],…] plus width/widths (a profile source→mouth) and depth; the node samples the Terrain3D underneath and derives the rest. It CARVES ITS OWN BED by default (carve): a trench per reach that heightAt, the collider, the splat and draped vegetation all see, with a floor that only ever falls, so a path over a rise digs through instead of burying the water. Its surface is then FITTED to that ground — never higher than the lowest rim holding it, ending where the ground comes up to meet it (asymmetric on a sloping reach), lying down as a film where a bank has fallen away, so a river can never hang in the air. Plus a current that speeds up where the channel pinches or tips (flowSpeed is the mean) and whitewater from grade, bank shear and thinning column. Boulders in the channel are answered without wiring: the node finds MeshInstance3D/InstancedMesh3D footprints standing in the water column and the current piles a white cushion on the upstream face, tears a wake downstream and bends its sheen around them. A trench thinner than a terrain cell cannot survive the grid: a 2.4 m creek on a 260 m map wants Terrain3D resolution 256. flowForce drags bodies downstream (drag, never thrust) and sampleAt(x,z) answers where a world point sits in the channel. No extra render passes — a map can carry a dozen.`,ko:`중심선 path [[x,z],…]와 width/widths(상류→하류 프로파일), depth만 주면 나머지는 아래 Terrain3D를 샘플링해 유도합니다. 기본적으로 강이 자기 바닥을 직접 팝니다(carve) — 구간마다 하나씩 도랑을 내고, heightAt·콜라이더·스플랫·식생 드레이프가 모두 그 지형을 봅니다. 파낸 바닥은 계속 내려가기만 하므로 경로가 언덕을 넘어도 물이 묻히지 않고 뚫고 흐릅니다. 그리고 수면은 그 지형에 맞춰집니다 — 자기를 담는 가장 낮은 둑보다 높아질 수 없고, 지면이 올라오는 지점에서 끝나며(비스듬한 구간에서는 좌우 폭이 다릅니다), 둑이 아예 없는 쪽에서는 경사면에 얇은 막처럼 누워버립니다. 그래서 강이 공중에 뜨는 일이 없습니다. 여기에 폭이 좁아지거나 경사가 급해지면 빨라지는 유속(flowSpeed는 평균)과 경사·둑 전단·얕아지는 수심에서 나오는 흰 물살이 더해집니다. 수로에 놓인 바위도 배선 없이 반응합니다 — MeshInstance3D/InstancedMesh3D 중 실제로 물기둥과 겹치는 것을 찾아, 상류면에 흰 물이 쌓이고 하류로 후류가 찢어지며 수면 광택이 바위를 돌아 휩니다. 지형 셀보다 얇은 도랑은 그리드에서 살아남지 못합니다 — 260 m 맵의 2.4 m 개울이라면 Terrain3D resolution 256이 필요합니다. flowForce가 바디를 하류로 끌고(밀지 않고 끌어당김), sampleAt(x,z)로 월드 좌표가 수로 어디에 있는지 알 수 있습니다. 추가 렌더 패스가 없어 한 맵에 여러 개를 둘 수 있습니다.`}),Z(`WaterCutout3D`,{en:`Marks its parent as something that holds the water back — a dry hull, a diving bell, a well.`,ko:`부모 오브젝트가 물을 막는다고 표시 — 마른 선실, 잠수종, 우물.`},{en:`Water is ONE surface and knows nothing about interiors, so an open hull floating on it fills with sea every time a crest clears its floor — freeboard alone can never promise otherwise. This node names the geometry that keeps the water out: it MUST be a CHILD of that thing (a hull, a bell, a dock's well, a cave mouth), and the water re-draws the part of it inside the box into its depth pre-pass, then hides behind it exactly as it hides behind any solid object. Nothing is ever cut OUT of the water, so a hole in open sea is impossible: overshoot the box and more of that hull holds water back, undershoot and water stands in the bow. size is the box extent in meters; enabled toggles it live (a scuttled hull starts letting the sea in). Four per water surface; needs quality fancy.`,ko:`물은 하나의 표면이라 '안쪽'이라는 개념이 없습니다. 그래서 뚜껑 없는 배를 띄우면 파도 마루가 바닥을 넘을 때마다 배 안에 바다가 차 보이고, 건현(freeboard)만으로는 절대 막을 수 없습니다. 이 노드는 '물을 막는 지오메트리'를 지정합니다. 반드시 그 물체(선체·잠수종·부두 우물·동굴 입구)의 자식이어야 하며, 물이 상자 안쪽의 그 지오메트리를 자기 깊이 프리패스에 다시 그린 뒤 평범한 불투명 물체 뒤에 숨듯 그 뒤로 숨습니다. 물에서 무언가를 '도려내지' 않으므로 열린 바다에 구멍이 나는 일은 원리적으로 불가능합니다 — 상자가 크면 그 배가 물을 더 많이 막을 뿐이고, 작으면 뱃머리에 물이 남습니다. size는 미터 단위 상자 크기, enabled는 런타임 토글(침수 시작 연출). 수면 하나당 4개, quality fancy 필요.`}),Z(`Foliage3D`,{en:`An instanced grass/flower carpet that sways.`,ko:`바람에 흔들리는 인스턴스 풀밭/꽃밭.`},{en:`kind grass/flowers/reeds scattered over area [w,d] at density (capped by maxInstances — instanced, tens of thousands of blades cheap). Grass defaults to style 'mesh': every instance is a REAL tapered blade curved by a bezier vertex shader — Voronoi-clump hue/lean, groundColor soil roots (match the terrain), sunDirection tip sheen, 2-octave rolling wind, fadeStart/fadeEnd camera LOD, and (interaction) blade-bending around moving bodies. style 'blades' keeps the 8-SDF-blades-per-quad ported shader, 'simple' the legacy quads. colorA/colorB tint bottom→top, sway sets the wind, seed makes the scatter reproducible.`,ko:`kind grass/flowers/reeds를 area [w,d]에 density로 흩뿌립니다(maxInstances 상한 — 인스턴싱이라 수만 가닥도 가벼움). grass는 기본 style 'mesh': 인스턴스 하나하나가 베지어 버텍스 셰이더로 휘어지는 진짜 잎 메시 — 보로노이 클럼프 색/기울기, groundColor 흙빛 뿌리(지형 색에 맞추세요), sunDirection 잎끝 광택, 2옥타브 굽이치는 바람, fadeStart/fadeEnd 카메라 LOD, (interaction) 움직이는 바디 주변 풀 눕힘까지. style 'blades'는 쿼드당 8가닥 SDF 셰이더, 'simple'은 기존 쿼드 룩. colorA/colorB가 아래→위 색, sway가 바람 세기, seed가 배치를 재현 가능하게 합니다.`}),Z(`Flowers3D`,{en:`Instanced flower PLANTS — stems, leaves, multi-petal heads.`,ko:`인스턴스 꽃밭 — 줄기·잎·여러 장 꽃잎의 진짜 꽃 식물.`},{en:`Real procedural flower plants (curved stem, 2-3 leaves, a 5-8 petal head around a contrasting center disc, 1-3 blooms per plant) scattered over area [w,d]. density is the vibe dial: 'lush' / 'sparse' (default) / 'none', or a number in plants/m². varieties picks a subset of daisy/cosmos/bellflower ([] = all three); palette sets the head colors ([] = white/yellow/violet). clustering 0-1 gathers plants into Voronoi patches that bloom one species + color together; sway bobs the heads in a gentle wind; seed makes the field reproducible. ≤3 varieties → ≤6 draw calls.`,ko:`진짜 프로시저럴 꽃 식물(휘어진 줄기, 잎 2-3장, 대비되는 중심 원반을 두른 꽃잎 5-8장 머리, 포기당 꽃 1-3송이)을 area [w,d]에 흩뿌립니다. density가 바이브 다이얼: 'lush'(풍성하게) / 'sparse'(듬성듬성, 기본) / 'none'(없게) 또는 m²당 개수. varieties는 daisy/cosmos/bellflower 부분집합([] = 셋 다), palette는 꽃 색([] = 흰/노랑/보라). clustering 0-1이 보로노이 패치로 모아 한 패치가 같은 종·같은 색으로 피고, sway가 바람에 머리를 끄덕이며, seed로 배치가 재현됩니다. 품종 ≤3 → 드로우 콜 ≤6.`}),Z(`Tree3D`,{en:`Procedural ez-tree groves — branchy trunks, textured leaves.`,ko:`프로시저럴 ez-tree 나무 — 가지 달린 줄기와 텍스처 잎까지.`},{en:`type conifer/broadleaf/dead picks the recipe family; tier is the cost dial: simple = primitive low-poly, medium = light forest presets (≤3k tris/tree), high = full ez-tree presets (8–20k, hero trees). count > 1 scatters a forest patch over area [w,d] — up to 3 seed variants, each branches + leaves InstancedMesh (≤6 draw calls); count × tris/tree is budget-checked at load. seed makes every branch and leaf reproducible; height jitters ±20% per instance; leaves sway in a simplex wind.`,ko:`type conifer/broadleaf/dead가 수종을, tier가 비용을 정합니다: simple = 기존 로우폴리, medium = 가벼운 forest 프리셋(나무당 ≤3k tris), high = 풀 ez-tree 프리셋(8–20k, 주인공 나무). count > 1이면 area [w,d]에 숲 패치를 흩뿌립니다 — 시드 변형 최대 3종, 변형마다 가지+잎 InstancedMesh(드로우 콜 ≤6), count × tris는 로드 시 예산 검사. seed로 가지와 잎이 전부 재현되고 height는 인스턴스마다 ±20% 지터링, 잎은 심플렉스 바람에 흔들립니다.`}),Z(`VoxelGrid3D`,{en:`A Minecraft-style block grid in ONE node.`,ko:`마인크래프트식 블록 그리드 — 노드 하나로.`},{en:`voxels is a list of [x,y,z,palette] integer cells (terrain/island generators emit these). Greedy-meshed and instanced — large worlds stay one draw batch. Game code edits blocks via setBlock/getBlock; emits blocksChanged.`,ko:`voxels는 [x,y,z,팔레트] 정수 셀 목록입니다(terrain/island 생성기가 만들어 냅니다). 그리디 메싱+인스턴싱으로 큰 월드도 드로우 배치 하나를 유지합니다. 게임 코드는 setBlock/getBlock으로 수정하고 blocksChanged가 발산됩니다.`})]},{id:`3d-physics`,label:{en:`3D Physics`,ko:`3D 물리`},intro:{en:`Same model as 2D, in meters with y-up gravity ([0,-9.81,0] default). Colliders: box {size}, sphere {radius}, capsule {radius,height}.`,ko:`2D와 같은 모델을 미터·y-위 중력([0,-9.81,0] 기본)으로. 콜라이더는 box {size}, sphere {radius}, capsule {radius,height}.`},nodes:[Z(`StaticBody3D`,{en:`Immovable 3D collision.`,ko:`움직이지 않는 3D 충돌체.`},{en:`Floors, walls, level geometry.`,ko:`바닥·벽·레벨 지형.`}),Z(`RigidBody3D`,{en:`Simulated 3D body.`,ko:`시뮬레이션되는 3D 바디.`},{en:`Crates, balls, debris — gravity and impacts drive it.`,ko:`상자·공·파편 — 중력과 충격이 움직입니다.`}),Z(`CharacterBody3D`,{en:`Kinematic 3D character.`,ko:`키네마틱 3D 캐릭터.`},{en:`moveAndSlide with up = +y; isOnFloor for jumps.`,ko:`+y를 위로 moveAndSlide, 점프 판정은 isOnFloor.`}),Z(`Area3D`,{en:`3D overlap sensor.`,ko:`3D 겹침 센서.`},{en:`triggerEnter/Exit — pickups, zones, goals.`,ko:`triggerEnter/Exit — 아이템·존·골인 지점.`}),Z(`CharacterController3D`,{en:`Zero-code 3D movement + camera rig.`,ko:`코드 없는 3D 이동 + 카메라 리그.`},{en:`Put it UNDER a CharacterBody3D. view: thirdPerson (orbit + zoom), firstPerson (eyeHeight, mouseLook), sideView or flightView. Reads moveAction/jumpAction/sprintAction from the scene input map; skinPath turns the visual child to face travel. Intent-level numbers: maxSpeed, jumpVelocity, camDistance.`,ko:`CharacterBody3D의 자식으로 두세요. view는 thirdPerson(궤도+줌), firstPerson(eyeHeight, mouseLook), sideView, flightView 중 하나입니다. 씬 입력 맵의 moveAction/jumpAction/sprintAction을 읽고 skinPath의 비주얼 자식을 진행 방향으로 돌립니다. maxSpeed·jumpVelocity·camDistance 같은 의도 수준의 숫자만 만집니다.`}),Z(`BoneLookAt3D`,{en:`Look-at IK for one bone — the head turns toward a target on top of the animation.`,ko:`본 하나의 룩앳 IK — 애니메이션 위에서 머리가 대상을 향해 돌아갑니다.`},{en:`"target" = ModelInstance3D path, "bone" = bone name (default Head), "lookAt" = the node to watch (e.g. "%Player"). Blends in/out smoothly and DISENGAGES beyond maxAngleDeg (no owl necks); weight sets how far it commits. forwardAxis names the bone's facing axis (mixamo heads: +z). Purely visual — headless no-op.`,ko:`"target"에 ModelInstance3D 경로, "bone"에 본 이름(기본 Head), "lookAt"에 바라볼 노드(예: "%Player")를 줍니다. 부드럽게 페이드 인/아웃하고 maxAngleDeg 밖에서는 해제됩니다(목이 돌아가지 않음). weight로 몰입도를 조절하고 forwardAxis는 본의 정면 축입니다(mixamo 머리: +z). 순수 시각 기능 — 헤드리스에서는 no-op.`}),Z(`InstancedMesh3D`,{en:`Hundreds of copies of one mesh in ONE draw call — rocks, posts, crates.`,ko:`메시 하나의 수백 개 복사본을 드로우콜 1개로 — 바위, 말뚝, 상자.`},{en:`Same mesh/size/material surface as MeshInstance3D; "transforms" places the copies — each row [x, y, z, yawDeg?, scale?]. Replace the whole array to update (mutations are not watched). The scattering workhorse for open worlds.`,ko:`MeshInstance3D와 같은 mesh/size/material 표면에 "transforms"로 복사본을 배치합니다 — 각 행은 [x, y, z, yawDeg?, scale?]. 갱신은 배열 전체 교체로 하세요(내부 변경은 감지되지 않음). 오픈월드 스캐터링의 주력입니다.`}),Z(`BoneAttachment3D`,{en:`Rides a skeleton bone of an animated model — swords in hands, hats on heads.`,ko:`애니메이션 모델의 스켈레톤 본을 따라다님 — 손에 쥔 검, 머리 위 모자.`},{en:`"target" is a node path to the ModelInstance3D, "bone" the bone name ("RightHand" also matches the Mixamo spellings). Children inherit the live animated transform; this node's own position/rotation become a bone-space offset. Purely visual — headless it stays where its props put it, so keep gameplay checks range-based.`,ko:`"target"에 ModelInstance3D 노드 경로, "bone"에 본 이름을 줍니다("RightHand"는 Mixamo 표기도 자동 매칭). 자식들이 살아있는 애니메이션 트랜스폼을 물려받고, 이 노드의 position/rotation은 본 기준 오프셋이 됩니다. 순수 시각 기능 — 헤드리스에서는 prop 위치에 머무니 게임 판정은 거리 기반으로 유지하세요.`}),Z(`Trail3D`,{en:`A fading world-space ribbon behind the parent — wingtip trails, sword arcs, tyre streaks.`,ko:`부모 뒤로 남는 페이드아웃 월드 리본 — 날개끝 궤적, 검격 궤적, 타이어 자국.`},{en:"Child of the moving node. Records the world position over `seconds` and renders a camera-facing strip that tapers and fades to the tail. width (m), color, opacity, additive for glowing energy trails, minDistance filters jitter. emitting: false stops laying new ribbon while the old tail fades out.",ko:`움직이는 노드의 자식으로 두세요. seconds 동안의 월드 위치를 기록해 꼬리로 갈수록 가늘어지고 투명해지는 카메라 지향 스트립을 그립니다. width(m), color, opacity, 빛나는 에너지 궤적에는 additive, minDistance로 떨림을 걸러냅니다. emitting: false면 새 리본만 멈추고 기존 꼬리는 자연스럽게 사라집니다.`}),Z(`Joint3D`,{en:`A physics joint linking its parent body to a target body — weld, ball joint, rope, spring.`,ko:`부모 바디와 대상 바디를 잇는 물리 조인트 — 용접, 볼 조인트, 로프, 스프링.`},{en:`Child of body A; "target" is a node path to body B. type: fixed (rigid weld) / spherical (ball joint at the anchors) / rope (caps anchor distance at length m; 0 = measured at creation) / spring (pulls toward length with stiffness/damping). anchor/targetAnchor are LOCAL meter offsets.`,ko:`바디 A의 자식으로 두고 "target"에 바디 B의 노드 경로를 줍니다. type: fixed(강체 용접) / spherical(앵커 볼 조인트) / rope(앵커 간 거리를 length m로 제한, 0이면 생성 시 실측) / spring(stiffness/damping으로 length를 향해 당김). anchor/targetAnchor는 로컬 미터 오프셋.`})]},{id:`network`,label:{en:`Network`,ko:`네트워크`},intro:{en:`Multiplayer is transport-agnostic: the engine speaks one NetworkTransport interface (built-in offline Loopback + an @agent8/gameserver adapter). The scene declares replication; one owner node per player broadcasts its sync keys.`,ko:`멀티플레이어는 트랜스포트 불가지론입니다 — 엔진은 NetworkTransport 인터페이스 하나만 사용합니다(내장 오프라인 Loopback + @agent8/gameserver 어댑터). 복제는 씬이 선언하며, 플레이어당 하나의 owner 노드가 sync 키를 송출합니다.`},nodes:[Z(`NetworkSpawner`,{en:`Spawns a registered scene per remote player/entity.`,ko:`원격 플레이어/엔티티마다 등록된 씬을 생성.`},{en:`source "users" mirrors every OTHER account in the room (self skipped); "collection:<id>" mirrors a room collection. Replicated sync patches apply to each instance; position interpolates. Emits spawned/despawned.`,ko:`source "users"는 방의 다른 모든 계정을 미러링하고(자신 제외) "collection:<id>"는 방 컬렉션을 미러링합니다. 복제 sync 패치가 인스턴스에 적용되고 position은 보간됩니다. spawned/despawned를 발산합니다.`})]}],gM=`overview`,_M=null;function vM(){document.querySelector(`#docs`)?.removeAttribute(`hidden`),xM()}function yM(){document.querySelector(`#docs`)?.setAttribute(`hidden`,``)}function bM(){let e=document.querySelector(`#docs`);e&&(e.addEventListener(`pointerdown`,t=>{t.target===e&&yM()}),document.querySelector(`#docs-close`)?.addEventListener(`click`,yM))}function xM(){let e=document.querySelector(`#docs-tabs`),t=document.querySelector(`#docs-body`);if(!e||!t)return;e.textContent=``;let n=(t,n)=>{let r=document.createElement(`button`);r.type=`button`,r.className=`docs-tab${gM===t?` active`:``}`,r.textContent=n,r.addEventListener(`click`,()=>{gM=t,_M=null,xM()}),e.appendChild(r)};n(`overview`,jj({en:`Overview`,ko:`개요`}));for(let e of hM)n(e.id,jj(e.label));if(t.textContent=``,gM===`overview`){SM(t);return}let r=hM.find(e=>e.id===gM);r&&CM(t,r)}function SM(e){let t=document.createElement(`h2`);t.textContent=jj(mM.title),e.appendChild(t);for(let t of mM.sections){let n=document.createElement(`h3`);n.textContent=jj(t.heading);let r=document.createElement(`p`);r.textContent=jj(t.text),e.append(n,r)}}function CM(e,t){let n=document.createElement(`p`);n.className=`docs-intro`,n.textContent=jj(t.intro),e.appendChild(n);for(let n of t.nodes){let t=document.createElement(`div`);t.className=`docs-node${_M===n.type?` open`:``}`;let r=document.createElement(`button`);r.type=`button`,r.className=`docs-node-head`;let i=document.createElement(`span`);i.className=`tree-icon`,i.appendChild(Pj(n.type));let a=document.createElement(`strong`);a.textContent=n.type;let o=document.createElement(`span`);if(o.className=`docs-summary`,o.textContent=jj(n.summary),r.append(i,a,o),r.addEventListener(`click`,()=>{_M=_M===n.type?null:n.type,xM()}),t.appendChild(r),_M===n.type){let e=document.createElement(`div`);e.className=`docs-detail`;for(let t of n.body){let n=document.createElement(`p`);n.textContent=jj(t),e.appendChild(n)}e.appendChild(wM(n.type)),t.appendChild(e)}e.appendChild(t)}}function wM(e){let t=document.createElement(`table`);t.className=`docs-props`;let n=document.createElement(`tr`);for(let e of[jj({en:`prop`,ko:`prop`}),jj({en:`default`,ko:`기본값`})]){let t=document.createElement(`th`);t.textContent=e,n.appendChild(t)}t.appendChild(n);try{let n=ge(e);for(let[e,r]of Object.entries(n)){let n=document.createElement(`tr`),i=document.createElement(`td`);i.className=`mono`,i.textContent=e;let a=document.createElement(`td`);a.className=`mono`,a.textContent=JSON.stringify(r.default),n.append(i,a),t.appendChild(n)}}catch{}return t}function Q(e){return Math.round(e*100)/100}function TM(e,t,n,r,i){return{name:e,type:`StaticBody3D`,props:{collider:{shape:`box`,size:t},position:n,...i?{rotation:i}:{}},children:[{name:`Skin`,type:`MeshInstance3D`,props:{mesh:`box`,size:t,...r}}]}}function EM(e,t,n,r,i,a){let o=Q(r.range(i[0],i[1])),s=Q(r.range(.5,.7));return{name:`Rock${e}`,type:`MeshInstance3D`,props:{mesh:`sphere`,size:[1,1,1],position:[t,Q(o*s*.6),n],rotation:[0,r.int(0,359),0],scale:[o,Q(o*s),Q(o*r.range(.8,1.1))],material:{color:a??DM(r),roughness:1},castShadow:!0}}}function DM(e){let t=Math.round(e.range(110,160)).toString(16).padStart(2,`0`);return`#${t}${t}${t}`}function OM(e){return[{name:`Sun`,type:`DirectionalLight3D`,props:{position:[Q(e*.8),Q(e*1.5),Q(e*.6)],intensity:1,castShadow:!0,shadowArea:Q(e*1.2)}},{name:`FillLight`,type:`DirectionalLight3D`,props:{position:[Q(-e*.8),Q(e*.8),Q(-e*.6)],intensity:.4,color:`#b9d4ff`}}]}function kM(e,t){return e===void 0?t:typeof e==`number`?[e,e]:e}function AM(e,t,n){return Math.min(Math.max(e,t),n)}var jM=[`boxes`,`ruins`,`garden`],MM=.5,NM=.1,PM=2,FM={boxes:{floor:`#3f3f3f`,wall:`#55504a`,obstacles:[`#b0413e`,`#5b8266`,`#3e6990`,`#a26b38`,`#6d5a96`,`#878787`]},ruins:{floor:`#7d766b`,wall:`#8a8378`,obstacles:[`#8a8378`,`#979085`,`#a39a8d`,`#7b746a`]},garden:{floor:`#4d7c3a`,wall:`#2f6b2f`,obstacles:[`#2f6b2f`,`#3a7a38`,`#356e33`]}};function IM(e){let{seed:t,width:n=30,depth:r=30,wallHeight:i=3,obstacles:a=8,theme:o=`boxes`}=e;if(!jM.includes(o))throw new y(`BAD_FORMAT`,`generateArena theme must be one of [${jM.join(`, `)}], got '${o}'.`,{prop:`theme`,validOptions:[...jM]});let s=FM[o],c=new b(t),l=[TM(`Floor`,[n,NM,r],[0,-.1/2,0],{material:{color:s.floor,roughness:1},receiveShadow:!0})],u=i/2,d=[n+MM*2,i,MM],f=[MM,i,r],p={material:{color:s.wall,roughness:.9},receiveShadow:!0};l.push(TM(`Wall1`,d,[0,u,-(r+MM)/2],p),TM(`Wall2`,d,[0,u,(r+MM)/2],p),TM(`Wall3`,f,[-(n+MM)/2,u,0],p),TM(`Wall4`,f,[(n+MM)/2,u,0],p)),o===`ruins`?l.push(...RM(c,s,n,r,i,a)):l.push(...LM(c,s,n,r,i,a,o)),o===`garden`&&l.push(...zM(c,n,r));let m=Math.max(n,r);return l.push({name:`Sun`,type:`DirectionalLight3D`,props:{position:[Q(m*.8),Q(m*1.5),Q(m*.6)],intensity:1,castShadow:!0,shadowArea:Q(m*1.2)}},{name:`FillLight`,type:`DirectionalLight3D`,props:{position:[Q(-m*.8),Q(m*.8),Q(-m*.6)],intensity:.4,color:`#b9d4ff`}},{name:`Lamp`,type:`OmniLight3D`,props:{position:[0,Q(i+2),0],intensity:.5,color:`#fff3d6`,range:Q(m)}}),{name:`Arena`,type:`Node3D`,children:l}}function LM(e,t,n,r,i,a,o){let s=[],c=o===`garden`?Math.min(n,r)*.16:0;for(let o=1;o<=a;o++){let a=[Q(e.range(.8,2.6)),Q(e.range(.8,Math.max(1.2,i*.8))),Q(e.range(.8,2.6))],l=Q(e.range(-(n/2-PM),n/2-PM)),u=Q(e.range(-(r/2-PM),r/2-PM));if(c>0&&Math.hypot(l,u)<c+1.5){let t=Math.max(Math.hypot(l,u),.001);l=Q(l/t*(c+1.5+e.range(0,2))),u=Q(u/t*(c+1.5+e.range(0,2)))}let d=e.int(0,359);s.push(TM(`Obstacle${o}`,a,[l,Q(a[1]/2),u],{material:{color:e.pick(t.obstacles),roughness:.8},castShadow:!0},[0,d,0]))}return s}function RM(e,t,n,r,i,a){let o=[];if(a<=0)return o;let s=Math.max(1,Math.round(Math.sqrt(a/2))),c=Math.ceil(a/s),l=n-PM*2,u=r-PM*2,d=0;for(let n=0;n<s&&d<a;n++){let r=Q(s===1?0:-u/2+n/(s-1)*u);for(let n=0;n<c&&d<a;n++){d++;let a=Q((c===1?0:-l/2+n/(c-1)*l)+e.range(-.4,.4)),s=Q(e.next()>.35?e.range(i*.7,i*1.2):e.range(.4,.9)),u=Q(e.range(.8,1.2));o.push(TM(`Obstacle${d}`,[u,s,u],[a,Q(s/2),Q(r+e.range(-.4,.4))],{material:{color:e.pick(t.obstacles),roughness:.95},castShadow:!0},[0,e.int(-8,8),0]))}}return o}function zM(e,t,n){let r=[],i=Math.min(t,n)*.16,a=r=>{let a=Math.min(t,n)/2-r/2-1,o=Q(e.range(-a,a)),s=Q(e.range(-a,a)),c=Math.max(Math.hypot(o,s),.001);return c<i+r/2&&(o=Q(o/c*(i+r/2+.5)),s=Q(s/c*(i+r/2+.5))),[o,s]};for(let i=1;i<=3;i++){let o=Q(Math.min(t,n)*e.range(.18,.26)),[s,c]=a(o);r.push({name:`Grass${i}`,type:`Foliage3D`,props:{kind:`grass`,area:[o,o],density:10,seed:e.int(1,1e9),position:[s,0,c]}})}for(let i=1;i<=2;i++){let o=Q(Math.min(t,n)*e.range(.12,.18)),[s,c]=a(o);r.push({name:`FlowerBed${i}`,type:`Flowers3D`,props:{density:`lush`,clustering:.3,area:[o,o],seed:e.int(1,1e9),position:[s,0,c]}})}return r.push({name:`Pool`,type:`Water3D`,props:{size:[Q(i*2),Q(i*2)],position:[0,.3,0],waveHeight:.04}}),r}var BM=32,VM=[4,8],HM=`#332f3a`,UM=`#6b6357`;function WM(e){let{seed:t,rooms:n=5}=e,[r,i]=kM(e.size,[960,720]),a=Math.max(8,Math.floor(r/BM)),o=Math.max(8,Math.floor(i/BM)),s=new b(t),c=[];for(let e=0;e<n*12&&c.length<n;e++){let e=s.int(VM[0],VM[1]),t=s.int(VM[0],VM[1]),n={x:s.int(1,Math.max(1,a-e-1)),y:s.int(1,Math.max(1,o-t-1)),w:e,h:t};c.some(e=>GM(e,n,1))||c.push(n)}let l=new Set,u=e=>{for(let t=e.y;t<e.y+e.h;t++)for(let n=e.x;n<e.x+e.w;n++)l.add(`${n},${t}`)};for(let e of c)u(e);let d=[];for(let e=1;e<c.length;e++){let[t,n]=KM(c[e-1]),[r,i]=KM(c[e]),a={x:Math.min(t,r),y:n,w:Math.abs(t-r)+1,h:1},o={x:r,y:Math.min(n,i),w:1,h:Math.abs(n-i)+1};for(let[t,n]of[[`H`,a],[`V`,o]])u(n),(n.w>1||n.h>1)&&d.push({name:`Corridor${e}${t}`,rect:n})}let f=new Set;for(let e of l){let[t,n]=e.split(`,`).map(Number);for(let e=-1;e<=1;e++)for(let r=-1;r<=1;r++){let i=`${t+r},${n+e}`;l.has(i)||f.add(i)}}let p=-(a*BM)/2,m=-(o*BM)/2,h=(e,t,n)=>({name:e,type:`ColorRect2D`,props:{position:[p+(t.x+t.w/2)*BM,m+(t.y+t.h/2)*BM],size:[t.w*BM,t.h*BM],color:n}}),g=c.map((e,t)=>h(`Room${t+1}`,e,HM));for(let e of d)g.push(h(e.name,e.rect,HM));let _=0;for(let e=-1;e<=o;e++){let t=-1;for(;t<=a;){if(!f.has(`${t},${e}`)){t++;continue}let n=1;for(;t+n<=a&&f.has(`${t+n},${e}`);)n++;_++;let r=[n*BM,BM];g.push({name:`Wall${_}`,type:`StaticBody2D`,props:{position:[p+(t+n/2)*BM,m+(e+.5)*BM],collider:{shape:`rect`,size:r}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:r,color:UM}}]}),t+=n}}return{name:`Dungeon`,type:`Node2D`,children:g}}function GM(e,t,n){return e.x-n<t.x+t.w&&e.x+e.w+n>t.x&&e.y-n<t.y+t.h&&e.y+e.h+n>t.y}function KM(e){return[Math.floor(e.x+e.w/2),Math.floor(e.y+e.h/2)]}var qM=[[0,-1],[1,0],[0,1],[-1,0]];function JM(e,t,n){let r=2*t+1,i=2*n+1,a=Array.from({length:i},()=>Array(r).fill(!1)),o=(e,t)=>{a[t][e]=!0};o(1,1);let s=new Set([`0,0`]),c=[[0,0]];for(;c.length>0;){let[r,i]=c[c.length-1],a=[];for(let[e,o]of qM){let c=r+e,l=i+o;c>=0&&c<t&&l>=0&&l<n&&!s.has(`${c},${l}`)&&a.push([c,l])}if(a.length===0){c.pop();continue}let[l,u]=e.pick(a);s.add(`${l},${u}`),o(2*l+1,2*u+1),o(r+l+1,i+u+1),c.push([l,u])}return o(0,1),o(2*t,2*n-1),{cols:t,rows:n,cells:a}}var YM=[`stone`,`hedge`,`canyon`],XM=.1,ZM=`https://agent8-games.verse8.io/assets/3D/default/textures/wall`,QM=`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,$M={stone:{wall:{color:`#e8e2d8`,map:`${ZM}/blocks.png`,normalMap:`${ZM}/blocks_normal.png`,tile:2,roughness:.95},floor:{color:`#99938a`,map:`${QM}/stone.png`,normalMap:`${QM}/stone_normal.png`,tile:3,roughness:1},cap:`#6b5848`,pillar:`#cfc8bb`,path:`#665f55`,sun:{color:`#c9d6ea`,intensity:.75,height:.5},fill:`#9fb4cc`,mood:{sky:{elevationDeg:10,azimuthDeg:150,turbidity:16,rayleigh:3.2},fog:{near:.5,far:3.5,color:`#86909c`},exposure:.82,ambient:{color:`#c9d4e2`,intensity:.12}}},hedge:{wall:{color:`#55a83e`,map:`${QM}/grass.png`,normalMap:`${QM}/grass_normal.png`,tile:1.4,roughness:1},floor:{color:`#86b06d`,map:`${QM}/grass.png`,normalMap:`${QM}/grass_normal.png`,tile:3,roughness:1},pillar:`#3d7531`,path:`#7d6845`,sun:{color:`#e9eee6`,intensity:.7,height:1},fill:`#b9c8b4`,mood:{sky:{elevationDeg:35,azimuthDeg:150,turbidity:18,rayleigh:4.2},fog:{near:.8,far:5,color:`#aab8a6`},exposure:.88,ambient:{color:`#dde5d8`,intensity:.15}}},canyon:{wall:{color:`#f0b070`,map:`${QM}/stone.png`,normalMap:`${QM}/stone_normal.png`,tile:2.4,roughness:1},floor:{color:`#e3c193`,map:`${QM}/sand.png`,normalMap:`${QM}/sand_normal.png`,tile:3.5,roughness:1},pillar:`#d8a868`,path:`#a98a58`,sun:{color:`#ffb572`,intensity:1.15,height:.35},fill:`#caa37e`,mood:{sky:{elevationDeg:9,azimuthDeg:230,turbidity:9,rayleigh:3.5},fog:{near:.7,far:4.5,color:`#c79c6e`},exposure:.92,ambient:{color:`#ffdcb6`,intensity:.13}}}};function eN(e,t,n){return{color:e.color,roughness:e.roughness,map:e.map,...e.normalMap?{normalMap:e.normalMap}:{},repeat:[Q(t/e.tile),Q(n/e.tile)]}}var tN=10;function nN(e){let{seed:t,width:n=8,depth:r=8,cellSize:i=2,wallHeight:a=2.5,theme:o=`stone`}=e;if(!YM.includes(o))throw new y(`BAD_FORMAT`,`generateMaze theme must be one of [${YM.join(`, `)}], got '${o}'.`,{prop:`theme`,validOptions:[...YM]});let s=$M[o],c=new b(t),l=JM(c,n,r),u=2*n+1,d=2*r+1,f=Q(u*i),p=Q(d*i),m=(e,t)=>[Q((e+.5)*i-f/2),Q((t+.5)*i-p/2)],h=[TM(`Floor`,[f,XM,p],[0,-.1/2,0],{material:eN(s.floor,f,p),receiveShadow:!0})],g=[],_=0;for(let e=0;e<d;e++){let t=0;for(;t<u;){if(l.cells[e]?.[t]){t++;continue}let n=1;for(;t+n<u&&!l.cells[e]?.[t+n];)n++;g.push({gx:t,gz:e,run:n}),_++;let r=Q(n*i);h.push(TM(`Wall${_}`,[r,a,i],[Q((t+n/2)*i-f/2),Q(a/2),Q((e+.5)*i-p/2)],{material:eN(s.wall,r,a),castShadow:!0,receiveShadow:!0})),t+=n}}return s.cap&&h.push(...rN(g,i,a,f,p,s.cap)),h.push(...iN(c,l,i,a,m,s)),o===`hedge`?(h.push(...cN(c,g,i,a,m)),h.push(...lN(c,l,i,m,n,r))):o===`canyon`&&h.push(...uN(c,g,i,a,m)),h.push(...oN(l,i,a,m,s)),h.push(...OM(Math.max(f,p)).map((e,t)=>{if(t!==0)return{...e,props:{...e.props,color:s.fill}};let n=e.props?.position;return{...e,props:{...e.props,color:s.sun.color,intensity:s.sun.intensity,position:[n[0]??0,Q((n[1]??0)*s.sun.height),n[2]??0]}}})),{name:`Maze`,type:`Node3D`,children:h}}function rN(e,t,n,r,i,a){return e.map((e,o)=>({name:`Cap${o+1}`,type:`MeshInstance3D`,props:{mesh:`box`,size:[Q(e.run*t+.16),.12,Q(t+.16)],position:[Q((e.gx+e.run/2)*t-r/2),Q(n+.06),Q((e.gz+.5)*t-i/2)],material:{color:a,roughness:1},castShadow:!0,receiveShadow:!0}}))}function iN(e,t,n,r,i,a){let o=[],s=(e,n)=>t.cells[n]?.[e]===!1;for(let e=2;e<t.cells.length-1;e+=2)for(let n=2;n<(t.cells[e]?.length??0)-1;n+=2)s(n,e)&&Number(s(n-1,e))+Number(s(n+1,e))+Number(s(n,e-1))+Number(s(n,e+1))>=3&&o.push([n,e]);let c=Math.min(tN,o.length),l=[],u=new Set,d=Q(n*1.2),f=Q(r*1.12);for(let t=1;t<=c;t++){let n=e.int(0,o.length-1);for(;u.has(n);)n=(n+1)%o.length;u.add(n);let[r,s]=o[n],[c,p]=i(r,s);l.push(aN(`Pillar${t}`,c,p,d,f,a))}return l}function aN(e,t,n,r,i,a){return{name:e,type:`MeshInstance3D`,props:{mesh:`box`,size:[r,i,r],position:[t,Q(i/2),n],material:{...eN(a.wall,r,i),color:a.pillar},castShadow:!0,receiveShadow:!0}}}function oN(e,t,n,r,i){let a=2*e.cols,o=2*e.rows-1,s=Q(t*1.1),c=Q(n*1.25),l=[[0,0],[0,2],[a,o-1],[a,o+1]].map(([e,t],n)=>{let[a,o]=r(e,t);return aN(`Gate${n+1}`,a,o,s,c,i)});for(let[e,n,s]of[[`EntrancePath`,0,1],[`ExitPath`,a,o]]){let[a,o]=r(n,s);l.push({name:e,type:`MeshInstance3D`,props:{mesh:`box`,size:[Q(t*.96),.04,Q(t*.96)],position:[a,.02,o],material:{...eN(i.floor,t,t),color:i.path},receiveShadow:!0}})}return l}var sN=10;function cN(e,t,n,r,i){return[...t].filter(e=>e.run>=2).sort((e,t)=>t.run-e.run||e.gz-t.gz||e.gx-t.gx).slice(0,sN).map((t,a)=>{let[,o]=i(t.gx,t.gz),[s]=i(t.gx,t.gz),[c]=i(t.gx+t.run-1,t.gz);return{name:`HedgeTop${a+1}`,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,area:[Q(t.run*n*.92),Q(n*.7)],density:14,height:.35,sway:.4,colorA:`#2f5e26`,colorB:`#5d8a3c`,seed:e.int(1,1e9),position:[Q((s+c)/2),r,o]}}})}function lN(e,t,n,r,i,a){let o=[];for(let e=0;e<t.cells.length;e++)for(let n=0;n<(t.cells[e]?.length??0);n++)t.cells[e]?.[n]&&o.push([n,e]);let s=Math.min(o.length,Math.max(3,Math.floor(i*a/12))),c=[],l=new Set;for(let t=1;t<=s&&l.size<o.length;t++){let i=e.int(0,o.length-1);for(;l.has(i);)i=(i+1)%o.length;l.add(i);let[a,s]=o[i],[u,d]=r(a,s),f=Q(n*.8);c.push({name:`Grass${t}`,type:`Foliage3D`,props:{kind:`grass`,area:[f,f],density:8,seed:e.int(1,1e9),position:[u,0,d]}})}return c}function uN(e,t,n,r,i){let a=[];if(t.length===0)return a;let o=Math.min(8,t.length);for(let s=1;s<=o;s++){let o=e.pick(t),[c,l]=i(o.gx+e.int(0,o.run-1),o.gz),u=EM(s,c,l,e,[.3,Q(n*.35)],`#8f7355`),d=u.props?.position;d[1]=Q(d[1]+r),a.push(u)}return a}var dN=`#23222b`,fN=`#5f6672`;function pN(e){let{seed:t,cols:n=10,rows:r=8,cellPx:i=64}=e,a=JM(new b(t),n,r),o=2*n+1,s=2*r+1,c=Q(o*i),l=Q(s*i),u=[{name:`Floor`,type:`ColorRect2D`,props:{size:[c,l],color:dN}}],d=0;for(let e=0;e<s;e++){let t=0;for(;t<o;){if(a.cells[e]?.[t]){t++;continue}let n=1;for(;t+n<o&&!a.cells[e]?.[t+n];)n++;d++;let r=[Q(n*i),i];u.push({name:`Wall${d}`,type:`StaticBody2D`,props:{position:[Q((t+n/2)*i-c/2),Q((e+.5)*i-l/2)],collider:{shape:`rect`,size:r}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:r,color:fN}}]}),t+=n}}return{name:`Maze2D`,type:`Node2D`,children:u}}var mN=16,hN=[`#5b8266`,`#3e6990`,`#a26b38`,`#6d5a96`,`#b0413e`];function gN(e){let{seed:t,count:n=10,width:r=[80,160],gapX:i=[40,120],stepY:a=[-80,40],start:o=[0,300]}=e,s=new b(t),c=[],l=Q(s.range(r[0],r[1])),u=o[0],d=o[1];for(let e=1;e<=n&&(c.push(_N(e,u,d,l,s.pick(hN))),e!==n);e++){let e=Q(s.range(r[0],r[1])),t=Q(s.range(i[0],i[1]));u=Q(u+l/2+t+e/2),d=Q(d+s.range(a[0],a[1])),l=e}return{name:`Platforms`,type:`Node2D`,children:c}}function _N(e,t,n,r,i){return{name:`Platform${e}`,type:`StaticBody2D`,props:{position:[t,n],collider:{shape:`rect`,size:[r,mN]}},children:[{name:`Skin`,type:`ColorRect2D`,props:{size:[r,mN],color:i}}]}}var vN=[3,5],yN=3,bN={color:`#ffffff`,roughness:1,emissive:`#ffffff`,emissiveIntensity:.25};function xN(e){let{seed:t,count:n=8,altitude:r=18}=e,[i,a]=kM(e.area,[60,60]),o=new b(t),s=[];for(let e=1;e<=n;e++){let t=o.int(vN[0],vN[1]),n=[];for(let e=1;e<=t;e++){let r=Q(o.range(1,2.2));n.push({name:`Puff${e}`,type:`MeshInstance3D`,props:{mesh:`sphere`,size:[1,1,1],position:[Q((e-(t+1)/2)*o.range(1,1.6)),Q(o.range(-.3,.3)),Q(o.range(-.6,.6))],scale:[Q(r*o.range(1.1,1.6)),Q(r*.55),r],material:bN}})}s.push({name:`Cloud${e}`,type:`Node3D`,props:{position:[Q(o.range(-i/2,i/2)),Q(r+o.range(-3,yN)),Q(o.range(-a/2,a/2))]},children:n})}return{name:`Clouds`,type:`Node3D`,children:s}}var SN=[`island`,`alpine`,`plains`,`desert`,`meadow`,`forest`,`savanna`,`snow`,`wetland`,`volcanic`],CN=128,wN=20,TN=.8,EN=.12,DN={island:{splat:`island`,maxHeight:4.5,sun:`#fff4d6`,fill:`#b9d4ff`,sky:{elevationDeg:38,azimuthDeg:145,turbidity:2.6,rayleigh:1.1},fog:{near:1,far:4},iblIntensity:.72},alpine:{splat:`alpine`,maxHeight:8,roughness:.65,detail:5,sun:`#f4f7ff`,fill:`#c9d8f2`,sky:{elevationDeg:45,azimuthDeg:35,turbidity:1.4,rayleigh:1.3},fog:{near:1.8,far:6.5},sunIntensity:1.1,exposure:.92,iblIntensity:.72},plains:{splat:`plains`,maxHeight:4,sun:`#fff2cf`,fill:`#bcd3ef`,sky:{elevationDeg:36,azimuthDeg:140,turbidity:2.4,rayleigh:1},fog:{near:.9,far:4},iblIntensity:.58},desert:{splat:`desert`,maxHeight:5,sun:`#ffe3b3`,fill:`#e8c9a6`,sky:{elevationDeg:42,azimuthDeg:160,turbidity:7,rayleigh:.6},fog:{near:.8,far:3.2,color:`#e8d3ae`},sunIntensity:1.35,iblIntensity:.75},meadow:{splat:`grassland`,maxHeight:1.2,sun:`#fff8e2`,fill:`#bfe0c9`,sky:{elevationDeg:55,azimuthDeg:125,turbidity:2.4,rayleigh:.95},fog:{near:1,far:4.4},sunIntensity:2.6,exposure:1.12,iblIntensity:.62},forest:{splat:`forest`,maxHeight:2.5,sun:`#ffdca8`,fill:`#a9c8b4`,sky:{elevationDeg:29,azimuthDeg:120,turbidity:5.5,rayleigh:1},fog:{near:.22,far:1.8,color:`#9fb494`},sunIntensity:2.6,ambient:.26,iblIntensity:.55},savanna:{splat:`savanna`,maxHeight:3,sun:`#ffdca0`,fill:`#e6d2a4`,sky:{elevationDeg:34,azimuthDeg:150,turbidity:5,rayleigh:.7},fog:{near:1,far:4.2,color:`#e3cf9f`},sunIntensity:2,exposure:1.05,iblIntensity:.6},snow:{splat:`snow`,maxHeight:2.2,sun:`#dfe9ff`,fill:`#c2d2f0`,sky:{elevationDeg:22,azimuthDeg:35,turbidity:1.6,rayleigh:1.6},fog:{near:1.2,far:5,color:`#dbe6f5`},sunIntensity:1,exposure:.9,iblIntensity:.72},wetland:{splat:`wetland`,maxHeight:1.4,sun:`#d6ddc8`,fill:`#9fb29a`,sky:{elevationDeg:24,azimuthDeg:115,turbidity:9,rayleigh:1.1},fog:{near:.5,far:2,color:`#92a288`},sunIntensity:1.5,exposure:.94,ambient:.24,iblIntensity:.66},volcanic:{splat:`volcanic`,maxHeight:4,roughness:.7,sun:`#ff8a4a`,fill:`#7a4a3a`,sky:{elevationDeg:14,azimuthDeg:135,turbidity:10,rayleigh:.3},fog:{near:.18,far:1.4,color:`#2a211c`},sunIntensity:1.7,exposure:.86,ambient:.22,iblIntensity:.5}};function ON(e){let{seed:t,theme:n=`island`,size:r=200,water:i=!1}=e,a=DN[n];if(!a)throw new y(`BAD_FORMAT`,`generateTerrain theme must be one of [${SN.join(`, `)}], got '${n}'.`,{prop:`theme`,validOptions:[...SN]});let o=Math.max(2,Math.round(e.resolution??CN)),s=e.maxHeight||a.maxHeight,c=new b(t),l=n===`island`,u=e=>Gx({width:r,depth:r,segsX:o,segsZ:o,maxHeight:e,seed:t,...a.roughness===void 0?{}:{roughness:a.roughness},...a.detail===void 0?{}:{detail:a.detail},islandEdge:l}),d=u(s);if(l)for(let e=0;e<3;e++){let e=AN(d)-wN,t=d.maxHeight-d.minHeight,n=d.minHeight+EN*t;if(e+TN<=n)break;let r=wN-TN,i=AN(d)-d.minHeight-EN*t;s=Q(s*Math.min(r/i*.95,.9)),d=u(s)}let f=[{name:`Ground`,type:`StaticBody3D`,props:{collider:{shape:`heightfield`}},children:[{name:`Surface`,type:`Terrain3D`,props:{size:[r,r],maxHeight:s,seed:t,theme:a.splat,...a.roughness===void 0?{}:{roughness:a.roughness},...a.detail===void 0?{}:{detail:a.detail},...o===CN?{}:{resolution:o}}}]}],p=n===`wetland`;if(l)f.push({name:`Sea`,type:`Water3D`,props:{size:[r*8,r*8],position:[0,kN(d),0],opacity:1}});else if(p){let e=d.maxHeight-d.minHeight||1,t=Q(d.minHeight+.22*e);f.push({name:`Swamp`,type:`Water3D`,props:{size:[r,r],position:[0,t,0],waveHeight:.02,quality:`simple`,color:`#3a4a30`,opacity:.95}})}else if(i){let e=Q(d.minHeight+.1*(d.maxHeight-d.minHeight));f.push({name:`Lake`,type:`Water3D`,props:{size:[r,r],position:[0,e,0],waveHeight:.04}})}return f.push(...KN(n,c,d,r)),l&&f.push(xN({seed:c.int(1,1e9),count:6,area:r,altitude:Math.round(d.maxHeight+12)})),f.push(...OM(r).map((e,t)=>qN(e,t===0?a.sun:a.fill,t===0?a.sunIntensity??1.7:void 0))),{name:`Terrain`,type:`Node3D`,children:f}}function kN(e){let t=AN(e)-wN,n=e.minHeight+EN*(e.maxHeight-e.minHeight);return Q(Math.max(Math.min(t+TN,n),t+.55))}function AN(e){let t=-1/0,n=e.width/2,r=e.depth/2,i=e.segsX;for(let a=0;a<=i;a++){let o=-n+a/i*e.width,s=-r+a/i*e.depth;t=Math.max(t,e.baseHeight(o,-r),e.baseHeight(o,r),e.baseHeight(-n,s),e.baseHeight(n,s))}return t}function jN(e,t,n){let r=Math.min(t.width/2-n.margin,n.within??1/0),i=t.maxHeight-t.minHeight||1,a=[];for(let o=0;o<n.count*30&&a.length<n.count;o++){let o=Q(e.range(-r,r)),s=Q(e.range(-r,r));if(n.clearing&&Math.hypot(o,s)<n.clearing||n.within&&Math.hypot(o,s)>n.within)continue;let c=t.heightAt(o,s),l=(c-t.minHeight)/i;l<n.band[0]||l>n.band[1]||t.slopeAt(o,s)>n.maxSlope||a.push({x:o,z:s,y:c})}return a}var MN=[{canopy:`#2f5d44`,trunk:`#6e4a32`},{canopy:`#356a4c`,trunk:`#71503a`},{canopy:`#2c5740`,trunk:`#5f4530`},{canopy:`#3a6b4a`,trunk:`#6a4c34`}],NN=[{canopy:`#4a7c3f`,trunk:`#7a5a3a`},{canopy:`#56883c`,trunk:`#806044`},{canopy:`#7a9d3e`,trunk:`#9a9488`},{canopy:`#86a346`,trunk:`#a39c8e`},{canopy:`#b8862f`,trunk:`#7e5e38`},{canopy:`#a8702c`,trunk:`#74552f`}],PN={canopy:`#9aa052`,trunk:`#8a6a44`},FN={canopy:`#39513f`,trunk:`#5a5650`};function IN(e,t){return e===`conifer`?t.pick(MN):e===`broadleaf`?t.pick(NN):null}function LN(e,t,n,r,i){let a=i?.height??[4.5,7],o=i?.sink??(i?.count===void 0?.05:.3),s={};i?.tier!==void 0&&(s.tier=i.tier),i?.count!==void 0&&i.area!==void 0&&(s.count=i.count,s.area=[i.area,i.area]);let c=IN(r,n),l=i?.palette??c;return l&&(s.canopyColor=l.canopy,s.trunkColor=l.trunk),{name:e,type:`Tree3D`,props:{type:r,seed:n.int(1,1e9),height:Q(n.range(a[0],a[1])),position:[t.x,Q(t.y-o),t.z],...s}}}function RN(e,t,n,r,i,a=0,o){return{name:e,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,area:[r,r],density:i,height:o?.height??.3,...o?.colors?{colorA:o.colors[0],colorB:o.colors[1]}:{},seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z],...a>0?{flowers:a}:{}}}}function zN(e,t,n,r,i){return{name:e,type:`Foliage3D`,props:{kind:`reeds`,style:`simple`,area:[r,r],density:i,height:.9,colorA:`#2f4a26`,colorB:`#5a6f33`,seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z]}}}function BN(e,t,n,r,i){return{name:e,type:`Flowers3D`,props:{density:i,area:[r,r],seed:n.int(1,1e9),position:[t.x,Q(t.y+.02),t.z]}}}function VN(e,t,n,r){return e.map((e,i)=>{let a=EM(i+1,e.x,e.z,t,n,r?.(t)),o=a.props?.position;return o[1]=Q(o[1]+e.y),a})}function HN(e){let t=Math.round(e.range(104,128)),n=Math.round(t-e.range(10,18)),r=Math.round(t-e.range(20,30)),i=e=>e.toString(16).padStart(2,`0`);return`#${i(n)}${i(t)}${i(r)}`}function UN(e){let t=Math.round(e.range(196,224)),n=Math.min(255,t+Math.round(e.range(4,12))),r=e=>e.toString(16).padStart(2,`0`);return`#${r(t)}${r(t)}${r(n)}`}function WN(e){let t=Math.round(e.range(34,56)),n=Math.min(255,t+Math.round(e.range(2,8))),r=e=>e.toString(16).padStart(2,`0`);return`#${r(n)}${r(t)}${r(t)}`}var GN=[`#6f5b41`,`#7a644a`,`#665439`];function KN(e,t,n,r){let i=[];switch(e){case`island`:{let e=jN(t,n,{count:7,band:[.18,.6],maxSlope:.5,margin:26});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`conifer`)));break}case`alpine`:{let e=jN(t,n,{count:10,band:[.2,.5],maxSlope:.55,margin:6});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`conifer`)));let r=jN(t,n,{count:8,band:[.55,1],maxSlope:.9,margin:6});i.push(...VN(r,t,[.6,1.8]));break}case`plains`:{let e=jN(t,n,{count:8,band:[0,1],maxSlope:.4,margin:6});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`broadleaf`)));let r=jN(t,n,{count:6,band:[0,1],maxSlope:.5,margin:6});i.push(...VN(r,t,[.4,1.2]));break}case`desert`:{let e=jN(t,n,{count:6,band:[0,1],maxSlope:.45,margin:6});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`dead`)));let r=jN(t,n,{count:8,band:[0,1],maxSlope:.6,margin:6});i.push(...VN(r,t,[.5,1.6]));break}case`meadow`:{let e=Q(r*.09),a=jN(t,n,{count:7,band:[0,1],maxSlope:.05,margin:e/2+8});i.push(...a.map((n,r)=>RN(`Carpet${r+1}`,n,t,e,30)));let o=Q(r*.07),s=jN(t,n,{count:3,band:[0,1],maxSlope:.05,margin:o/2+8});i.push(...s.map((e,n)=>BN(`Flowers${n+1}`,e,t,o,`sparse`)));let c=jN(t,n,{count:4,band:[0,1],maxSlope:.1,margin:12});i.push(...c.map((e,n)=>LN(`Grove${n+1}`,e,t,`broadleaf`,{count:3,area:6})));let l=jN(t,n,{count:6,band:[0,1],maxSlope:.2,margin:8});i.push(...VN(l,t,[.3,.9]));break}case`forest`:{let e=Q(r*.12),a=r/2-8,o=et(t.int(1,1e9)),s=(e,t,n)=>{let r=o(e/70,t/70);return r>.12?`conifer`:r<-.12?`broadleaf`:n%2==0?`conifer`:`broadleaf`},c=jN(t,n,{count:40,band:[0,1],maxSlope:.18,margin:8,clearing:e+6}),l=c.map((e,t)=>s(e.x,e.z,t));i.push(...c.map((e,n)=>LN(`Grove${n+1}`,e,t,l[n],{count:12,area:13,height:[5.5,8]}))),c.forEach((e,n)=>{n%3==0&&i.push(LN(`Sapling${n+1}`,e,t,l[n],{count:4,area:19,height:[2.5,3.4],sink:.12}))});let u=jN(t,n,{count:6,band:[0,1],maxSlope:.2,margin:12,clearing:e+4});i.push(...u.map((e,n)=>LN(`Elder${n+1}`,e,t,s(e.x,e.z,n),{tier:`high`,height:[8.4,9.8]})));let d=jN(t,n,{count:3,band:[0,1],maxSlope:.18,margin:10,clearing:e+6});i.push(...d.map((e,n)=>LN(`Accent${n+1}`,e,t,`broadleaf`,{tier:`high`,count:3,area:7,height:[5.6,6.8]})));let f=jN(t,n,{count:10,band:[0,1],maxSlope:.14,margin:9,clearing:e+2});i.push(...f.map((e,n)=>LN(`Bush${n+1}`,e,t,`bush`,{count:4,area:10,height:[2.1,3.1],sink:.12})));let p=0;c.forEach((e,r)=>{if(r%3==2)return;let o=t.range(0,Math.PI*2),s=t.range(2,4.5),c=t.int(1,1e9),l=Q(AM(e.x+Math.cos(o)*s,-a,a)),u=Q(AM(e.z+Math.sin(o)*s,-a,a));n.slopeAt(l,u)>.09||(p++,i.push({name:`Fern${p}`,type:`Foliage3D`,props:{kind:`grass`,style:`tufts`,tuftStyle:`fern`,area:[8,8],density:9,height:.4,colorA:`#4a6b34`,colorB:`#82a258`,seed:c,position:[l,Q(n.heightAt(l,u)+.02),u]}}))});let m=Q(r*.08),h=jN(t,n,{count:5,band:[0,1],maxSlope:.06,margin:m/2+8});i.push(...h.map((e,n)=>RN(`Grass${n+1}`,e,t,m,20,0,{height:.24,colors:[`#4f7034`,`#85a154`]})));let g=u.length>0?t.int(3,5):0;for(let e=0;e<g;e++){let r=u[e%u.length],o=t.range(0,Math.PI*2),s=t.range(2.5,4.5),c=Q(AM(r.x+Math.cos(o)*s,-a,a)),l=Q(AM(r.z+Math.sin(o)*s,-a,a));i.push({name:`Log${e+1}`,type:`Tree3D`,props:{type:`dead`,seed:t.int(1,1e9),height:Q(t.range(4.2,5.6)),trunkColor:`#4a4236`,position:[c,Q(n.heightAt(c,l)+.12),l],rotation:[0,t.int(0,359),Q(t.range(81,97))]}})}jN(t,n,{count:5,band:[0,1],maxSlope:.25,margin:9,clearing:e}).forEach((e,n)=>{let r=Q(t.range(.16,.28)),a=Q(t.range(.3,.55));i.push({name:`Stump${n+1}`,type:`MeshInstance3D`,props:{mesh:`cylinder`,size:[r,a,r],position:[e.x,Q(e.y+a/2-.06),e.z],rotation:[0,t.int(0,359),0],material:{color:t.pick(GN),roughness:1},castShadow:!0}})});let _=jN(t,n,{count:8,band:[0,1],maxSlope:.2,margin:8});i.push(...VN(_,t,[.3,1],HN));let v=Q(e*.75),y=jN(t,n,{count:3,band:[0,1],maxSlope:.06,margin:8,within:e-Q(v/Math.SQRT2)});i.push(...y.map((e,n)=>RN(`Clearing${n+1}`,e,t,v,30,0,{colors:[`#5d8438`,`#a8bc60`]})));let b=Q(e*.45),x=jN(t,n,{count:2,band:[0,1],maxSlope:.06,margin:8,within:e-Q(b/Math.SQRT2)});i.push(...x.map((e,n)=>BN(`Flowers${n+1}`,e,t,b,`sparse`)));break}case`savanna`:{let e=jN(t,n,{count:7,band:[0,.85],maxSlope:.35,margin:8});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`broadleaf`,{height:[3.5,5],palette:PN})));let a=Q(r*.09),o=jN(t,n,{count:6,band:[0,1],maxSlope:.05,margin:a/2+8});i.push(...o.map((e,n)=>RN(`Carpet${n+1}`,e,t,a,26,0,{height:.34,colors:[`#9a8f43`,`#c9bd6a`]})));let s=jN(t,n,{count:7,band:[0,1],maxSlope:.5,margin:8});i.push(...VN(s,t,[.4,1.4]));let c=jN(t,n,{count:4,band:[0,1],maxSlope:.2,margin:9});i.push(...c.map((e,n)=>LN(`Scrub${n+1}`,e,t,`bush`,{count:3,area:8,height:[1.4,2.2]})));break}case`snow`:{let e=jN(t,n,{count:8,band:[0,.9],maxSlope:.4,margin:8});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`conifer`,{height:[4,6.5],palette:FN})));let r=jN(t,n,{count:10,band:[0,1],maxSlope:.7,margin:8});i.push(...VN(r,t,[.5,1.8],UN));break}case`wetland`:{let e=Q(r*.08),a=jN(t,n,{count:6,band:[0,.5],maxSlope:.06,margin:e/2+8});i.push(...a.map((n,r)=>zN(`Reeds${r+1}`,n,t,e,4)));let o=Q(r*.08),s=jN(t,n,{count:4,band:[.2,1],maxSlope:.05,margin:o/2+8});i.push(...s.map((e,n)=>RN(`Moss${n+1}`,e,t,o,22,0,{height:.22,colors:[`#3a5a2c`,`#6f8a48`]})));let c=jN(t,n,{count:6,band:[.25,1],maxSlope:.35,margin:9});i.push(...c.map((e,n)=>LN(`Snag${n+1}`,e,t,`dead`,{height:[4,6]})));let l=jN(t,n,{count:6,band:[.2,1],maxSlope:.2,margin:9});i.push(...l.map((e,n)=>LN(`Bush${n+1}`,e,t,`bush`,{count:3,area:7,height:[1.6,2.6]})));let u=jN(t,n,{count:5,band:[.2,1],maxSlope:.3,margin:8});i.push(...VN(u,t,[.3,1],HN));break}case`volcanic`:{let e=jN(t,n,{count:7,band:[0,1],maxSlope:.45,margin:8});i.push(...e.map((e,n)=>LN(`Tree${n+1}`,e,t,`dead`,{height:[4,6.5]})));let r=jN(t,n,{count:12,band:[0,1],maxSlope:.7,margin:8});i.push(...VN(r,t,[.4,1.8],WN)),jN(t,n,{count:3,band:[0,.6],maxSlope:.18,margin:12}).forEach((e,n)=>{t.int(1,1e9),i.push({name:`Smoke${n+1}`,type:`Particles3D`,props:{preset:`smoke`,position:[e.x,Q(e.y+.2),e.z],rate:8,maxParticles:64,colorStart:`#5a5048`,colorEnd:`#2a2422`,sizeStart:18,sizeEnd:44}}),i.push({name:`Embers${n+1}`,type:`Particles3D`,props:{position:[e.x,Q(e.y+.1),e.z],rate:10,maxParticles:48,lifetime:[.8,1.8],speed:[12,34],directionDeg:-90,spreadDeg:40,gravity:[0,-18],sizeStart:4,sizeEnd:1,colorStart:`#ffce6a`,colorEnd:`#d83a14`,blend:`add`}})});break}}return i}function qN(e,t,n){return{...e,props:{...e.props,color:t,...n===void 0?{}:{intensity:n}}}}var JN={arena:{description:`FPS stage: floor, 4 perimeter walls, obstacles, lights — themes: boxes (crates), ruins (broken stone rows), garden (hedges, grass, pool)`,dimension:`3d`,params:{theme:{type:`string`,default:`boxes`,options:[...jM]},width:{type:`number`,default:30,min:4},depth:{type:`number`,default:30,min:4},wallHeight:{type:`number`,default:3,min:.5},obstacles:{type:`number`,default:8,min:0}}},terrain:{description:`Heightfield world: StaticBody3D{heightfield} + Terrain3D + theme dressing (trees, rocks, grass, sea/clouds on island, broad swamp water on wetland, smoke/ember emitters on volcanic; maxHeight 0 = theme default; water adds a lake to non-island themes)`,dimension:`3d`,params:{theme:{type:`string`,default:`island`,options:[...SN]},size:{type:`number`,default:200,min:40,max:400},maxHeight:{type:`number`,default:0,min:0},water:{type:`boolean`,default:!1}}},maze:{description:`Recursive-backtracker 3D maze, west→east — themes: stone, hedge (green + grass), canyon (sandstone + rim rocks)`,dimension:`3d`,params:{theme:{type:`string`,default:`stone`,options:[...YM]},width:{type:`number`,default:8,min:2,max:40},depth:{type:`number`,default:8,min:2,max:40},cellSize:{type:`number`,default:2,min:.5},wallHeight:{type:`number`,default:2.5,min:.5}}},maze2d:{description:`The same maze algorithm as 2D ColorRect2D + StaticBody2D tiles`,dimension:`2d`,params:{cols:{type:`number`,default:10,min:2,max:40},rows:{type:`number`,default:8,min:2,max:40},cellPx:{type:`number`,default:64,min:8}}},dungeon2d:{description:`Roguelike rooms + L-corridors: floor rects, wall bodies (32px tiles)`,dimension:`2d`,params:{rooms:{type:`number`,default:5,min:1,max:20},size:{type:`number`,default:960,min:256}}},platforms2d:{description:`Left-to-right 2D platform course (tune ranges via the library)`,dimension:`2d`,params:{count:{type:`number`,default:10,min:1}}}},YN={arena:IM,terrain:ON,maze:nN,maze2d:pN,dungeon2d:WM,platforms2d:gN};function XN(e,t){let n=YN[e];if(!n){let t=Object.keys(YN);throw new y(`BAD_FORMAT`,`Unknown generator '${e}'. Valid: [${t.join(`, `)}] — the old meadow/forest/island/rocks/clouds generators became themes (e.g. terrain theme: 'meadow', arena theme: 'garden'); scatter is library-only (needs item templates).`,{validOptions:t})}return n(t)}function ZN(e){return Object.entries(JN).filter(([,t])=>t.dimension===e).map(([e,t])=>({name:e,meta:t}))}function QN(e,t){if(e.type===`boolean`)return t===!0||t===`true`;if(e.type===`number`){let n=typeof t==`boolean`?NaN:Number(t);return(t===``||!Number.isFinite(n))&&(n=e.default),e.min!==void 0&&(n=Math.max(e.min,n)),e.max!==void 0&&(n=Math.min(e.max,n)),n}let n=String(t);return e.options&&!e.options.includes(n)?e.default:n}function $N(){return Math.floor(Math.random()*1e6)}var eP=[],tP=new Map,nP=null;function rP(e){let t=document.querySelector(`#generate`);t&&(oP(e),t.removeAttribute(`hidden`))}function iP(){document.querySelector(`#generate`)?.setAttribute(`hidden`,``)}function aP(e){let t=document.querySelector(`#generate`);t&&(t.addEventListener(`pointerdown`,e=>{e.target===t&&iP()}),document.querySelector(`#generate-close`)?.addEventListener(`click`,iP),document.querySelector(`#generate-cancel`)?.addEventListener(`click`,iP),document.querySelector(`#generate-insert`)?.addEventListener(`click`,()=>sP(e)))}function oP(e){let t=document.querySelector(`#generate-body`),n=document.querySelector(`#generate-status`);if(!t)return;n&&(n.textContent=``),t.textContent=``;let r=e.working.dimension??`2d`;eP=ZN(r);let i=document.createElement(`p`);i.className=`gen-hint`,i.textContent=jj({en:`Deterministic ${r.toUpperCase()} environment generators — the subtree inserts under the selected node (the root when nothing is selected). The same seed always generates the same level.`,ko:`결정적 ${r.toUpperCase()} 환경 생성기 — 생성된 서브트리는 선택한 노드 아래에(선택이 없으면 루트에) 들어갑니다. 같은 시드는 항상 같은 레벨을 만듭니다.`}),t.appendChild(i);let a=cP(jj({en:`generator`,ko:`생성기`})),o=document.createElement(`select`);o.id=`generate-name`;for(let{name:e}of eP){let t=document.createElement(`option`);t.value=e,t.textContent=e,o.appendChild(t)}a.appendChild(o),t.appendChild(a);let s=document.createElement(`p`);s.className=`gen-desc`,t.appendChild(s);let c=document.createElement(`div`);c.id=`generate-params`,t.appendChild(c);let l=cP(`seed`);nP=document.createElement(`input`),nP.type=`number`,nP.step=`1`,nP.value=String($N());let u=document.createElement(`button`);u.type=`button`,u.className=`ghost`,u.textContent=`↻`,u.title=jj({en:`New random seed`,ko:`새 랜덤 시드`}),u.addEventListener(`click`,()=>{nP&&(nP.value=String($N()))});let d=document.createElement(`div`);d.className=`gen-seed-row`,d.append(nP,u),l.appendChild(d),t.appendChild(l);let f=()=>{let e=eP.find(e=>e.name===o.value)??eP[0];if(e){s.textContent=e.meta.description,c.textContent=``,tP=new Map;for(let[t,n]of Object.entries(e.meta.params)){let e=cP(t),r;if(n.type===`boolean`)r=document.createElement(`input`),r.type=`checkbox`,r.checked=n.default===!0;else if(n.type===`string`&&n.options){r=document.createElement(`select`);for(let e of n.options){let t=document.createElement(`option`);t.value=e,t.textContent=e,r.appendChild(t)}r.value=String(n.default)}else r=document.createElement(`input`),r.type=n.type===`number`?`number`:`text`,n.type===`number`&&(r.step=`any`,n.min!==void 0&&(r.min=String(n.min)),n.max!==void 0&&(r.max=String(n.max))),r.value=String(n.default),(n.min!==void 0||n.max!==void 0)&&(r.title=`${n.min??``}–${n.max??``}`);tP.set(t,r),e.appendChild(r),c.appendChild(e)}}};o.addEventListener(`change`,f),f()}function sP(e){let t=document.querySelector(`#generate-status`),n=document.querySelector(`#generate-name`),r=eP.find(e=>e.name===n?.value);if(!r||!nP)return;let i={seed:QN({type:`number`,default:$N(),min:0},nP.value)};for(let[e,t]of tP){let n=r.meta.params[e];n&&(i[e]=QN(n,t.type===`checkbox`?t.checked:t.value))}let a;try{a=XN(r.name,i)}catch(e){t&&(t.textContent=e instanceof Error?e.message:String(e));return}let o=e.insertNode(a,e.selection??[]);if(o===null){t&&(t.textContent=jj({en:`Insert failed — see the error banner.`,ko:`삽입 실패 — 에러 배너를 확인하세요.`}));return}e.select(o),nP&&(nP.value=String($N())),iP()}function cP(e){let t=document.createElement(`label`);t.className=`field`;let n=document.createElement(`span`);return n.textContent=e,t.appendChild(n),t}var lP={groups:{title:{en:`groups — tag nodes for queries`,ko:`groups — 조회용 태그`},body:{en:`Free-form tags. Game code finds nodes with tree-wide queries like getNodesInGroup("coins"), and triggers can filter by group (e.g. only react to "player"). Type a name and press Enter.`,ko:`자유 형식 태그입니다. 게임 코드가 getNodesInGroup("coins")처럼 트리 전체에서 노드를 찾고, 트리거는 그룹으로 거릅니다(예: "player"에만 반응). 이름을 입력하고 Enter를 누르세요.`},example:`triggerEnter → if (other.isInGroup("player")) collect()`},script:{title:{en:`script — attach YOUR game logic`,ko:`script — 게임 로직 연결`},body:{en:`A Behavior is a TypeScript class living in YOUR game code, linked by name. The editor stores the link; the class itself must be registered in the game before loadScene. Props here are passed to the behavior instance.`,ko:`Behavior는 게임 코드에 있는 TypeScript 클래스이며 이름으로 연결됩니다. 에디터는 연결만 저장하고, 클래스 자체는 loadScene 전에 게임에서 등록되어야 합니다. 여기의 props가 비헤이비어 인스턴스로 전달됩니다.`},example:`registerBehavior('CoinCounter', CoinCounter) // in your main.ts`,copy:{label:`copy behavior boilerplate`,text:`import { Behavior, registerBehavior } from 'incanto';
|
|
8225
8321
|
|
|
8226
8322
|
export class MyBehavior extends Behavior {
|
|
8227
8323
|
static props = { speed: { default: 100 } };
|
|
@@ -8231,4 +8327,4 @@ export class MyBehavior extends Behavior {
|
|
|
8231
8327
|
update(dt: number): void {}
|
|
8232
8328
|
}
|
|
8233
8329
|
registerBehavior('MyBehavior', MyBehavior); // before loadScene()
|
|
8234
|
-
`}},network:{title:{en:`network — replicate to other players`,ko:`network — 다른 플레이어에게 복제`},body:{en:`mode "owner" means THIS player owns the node and broadcasts the listed sync keys to everyone in the room (one owner node per player — usually your player character). Other players see it via a NetworkSpawner. Keys are relative to this node: "position", or "Skin.animation" for a child prop.`,ko:`mode "owner"는 이 플레이어가 노드를 소유하고 sync 키 목록을 방의 모두에게 송출한다는 뜻입니다(플레이어당 owner 노드 하나 — 보통 내 캐릭터). 다른 플레이어는 NetworkSpawner로 봅니다. 키는 이 노드 기준 상대 표기입니다: "position", 자식 prop은 "Skin.animation".`},example:`{ "mode": "owner", "sync": ["position"], "throttleMs": 50 }`},collider:{title:{en:`collider — the physics shape`,ko:`collider — 물리 모양`},body:{en:`Shapes: rect (size [w,h]), circle (radius), capsule (radius + height — good for characters). offset shifts the shape from the node position. The green dashed outline in the viewport shows exactly where it is.`,ko:`모양: rect(size [w,h]), circle(radius), capsule(radius+height — 캐릭터에 적합). offset이 노드 위치에서 모양을 이동시킵니다. 뷰포트의 초록 점선이 정확한 위치를 보여줍니다.`},example:`{ "shape": "capsule", "radius": 12, "height": 16 }`},physics:{title:{en:`physics — scene gravity`,ko:`physics — 씬 중력`},body:{en:`World gravity in px/s² (y-down: positive y pulls DOWN). [0, 1400] feels platformer-y; [0, 0] for top-down. Takes effect when the game calls enablePhysics2D — and in the editor’s play mode.`,ko:`월드 중력, px/s² 단위(y-아래: 양수 y가 아래로 당김). [0, 1400]이면 플랫포머 느낌, 탑다운은 [0, 0]. 게임이 enablePhysics2D를 부를 때 — 그리고 에디터 플레이 모드에서 — 적용됩니다.`},example:`"physics": { "gravity": [0, 1400] }`}},IN=null;function LN(e){document.addEventListener(`click`,t=>{let n=t.target,r=n.closest(`[data-help]`);if(!r){e.contains(n)||(e.hidden=!0);return}let i=FN[r.dataset.help??``];if(!i)return;if(!e.hidden&&IN===r){e.hidden=!0;return}IN=r,e.textContent=``;let a=document.createElement(`h4`);a.textContent=rj(i.title);let o=document.createElement(`div`);if(o.textContent=rj(i.body),e.append(a,o),i.example){let t=document.createElement(`pre`);t.textContent=i.example,e.appendChild(t)}if(i.copy){let t=document.createElement(`div`);t.className=`pop-actions`;let n=document.createElement(`button`);n.type=`button`,n.className=`linklike`,n.textContent=`⧉ ${i.copy.label}`,n.addEventListener(`click`,()=>{navigator.clipboard.writeText(i.copy?.text??``),n.textContent=`✓ copied`}),t.appendChild(n),e.appendChild(t)}e.hidden=!1;let s=r.getBoundingClientRect();e.style.left=`${Math.max(8,Math.min(innerWidth-300-8,s.left-300+20))}px`,e.style.top=`${Math.min(innerHeight-60,s.bottom+8)}px`})}function RN(e){let t=document.createElement(`button`);return t.type=`button`,t.className=`help-btn`,t.dataset.help=e,t.textContent=`?`,t.title=`What is this?`,t}var zN=JSON.parse('[{"name":"2dbasic","file":"characters/2dbasic.png","url":"incanto/assets/characters/2dbasic.png","kind":"character","bytes":30499,"description":"2dbasic sprite sheet image.anything,base character. (frame size 192x192)","animation":"characters/2dbasic.json","frameWidth":111,"frameHeight":83},{"name":"attacked","file":"audio/attacked.mp3","url":"incanto/assets/audio/attacked.mp3","kind":"audio","bytes":8757,"description":"Short hurt / took-damage SFX for the player or an enemy."},{"name":"bark_birch_color","file":"vegetation/bark/birch_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_color_1k.jpg","kind":"foliage","bytes":194186,"description":"Birch bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_birch_normal","file":"vegetation/bark/birch_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_normal_1k.jpg","kind":"foliage","bytes":378046,"description":"Birch bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_birch_roughness","file":"vegetation/bark/birch_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_roughness_1k.jpg","kind":"foliage","bytes":127387,"description":"Birch bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_color","file":"vegetation/bark/oak_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_color_1k.jpg","kind":"foliage","bytes":297877,"description":"Oak bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_normal","file":"vegetation/bark/oak_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_normal_1k.jpg","kind":"foliage","bytes":67610,"description":"Oak bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_roughness","file":"vegetation/bark/oak_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_roughness_1k.jpg","kind":"foliage","bytes":16648,"description":"Oak bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_color","file":"vegetation/bark/pine_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_color_1k.jpg","kind":"foliage","bytes":196361,"description":"Pine bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_normal","file":"vegetation/bark/pine_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_normal_1k.jpg","kind":"foliage","bytes":58237,"description":"Pine bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_roughness","file":"vegetation/bark/pine_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_roughness_1k.jpg","kind":"foliage","bytes":36136,"description":"Pine bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"box","file":"items/box.png","url":"incanto/assets/items/box.png","kind":"item","bytes":10861,"description":"Item box sprite for Dungeons and Dungeoners. Container sprite that holds random items or rewards when opened by player."},{"name":"buff_potion","file":"items/buff_potion.png","url":"incanto/assets/items/buff_potion.png","kind":"item","bytes":3809,"description":"Buff potion item sprite for Dungeons and Dungeoners. Consumable item that grants temporary stat boosts or positive effects to player character."},{"name":"coin","file":"items/coin.png","url":"incanto/assets/items/coin.png","kind":"item","bytes":1689,"description":"Gold coin collectible sprite for Dungeons and Dungeoners. Currency item with metallic sheen, used as in-game money or collectible reward."},{"name":"explosion","file":"audio/explosion.mp3","url":"incanto/assets/audio/explosion.mp3","kind":"audio","bytes":40124,"description":"Impactful explosion / large destructive hit SFX. Pair with the Particles2D \\"explosion\\" preset."},{"name":"floor00","file":"tiles/floor00.jpg","url":"incanto/assets/tiles/floor00.jpg","kind":"tile","bytes":28736,"description":"Basic floor tile texture for Dungeons and Dungeoners project, suitable for dungeon ground surfaces."},{"name":"gem","file":"items/gem.png","url":"incanto/assets/items/gem.png","kind":"item","bytes":8762,"description":"Gem collectible sprite for Dungeons and Dungeoners. Valuable gemstone item used as currency, crafting material, or quest objective."},{"name":"ghost","file":"characters/ghost.png","url":"incanto/assets/characters/ghost.png","kind":"character","bytes":22933,"description":"Ghost character with translucent appearance sprite sheet image (frame size 112x128)","animation":"characters/ghost.json","frameWidth":112,"frameHeight":128},{"name":"goblin","file":"characters/goblin.png","url":"incanto/assets/characters/goblin.png","kind":"character","bytes":57994,"description":"Medieval goblin with torch sprite sheet image (frame size 192x192)","animation":"characters/goblin.json","frameWidth":192,"frameHeight":192},{"name":"gold","file":"items/gold.png","url":"incanto/assets/items/gold.png","kind":"item","bytes":22313,"description":"Gold item sprite for Dungeons and Dungeoners. Gold pile or gold bar sprite representing valuable currency or treasure reward."},{"name":"gold-loot","file":"audio/gold_loot.mp3","url":"incanto/assets/audio/gold_loot.mp3","kind":"audio","bytes":7506,"description":"Metallic coin / gold pickup jingle — collecting currency."},{"name":"ground_dirt","file":"vegetation/ground/dirt_color.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/dirt_color.jpg","kind":"foliage","bytes":231383,"description":"Dense dirt/gravel ground texture (1024px) from the ez-tree demo app (MIT) — the reference meadow ground. Terrain3D grassland themes tile it for slope + noise-patch dirt by default; also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"ground_dirt_normal","file":"vegetation/ground/dirt_normal.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/dirt_normal.jpg","kind":"foliage","bytes":123478,"description":"Dirt ground normal map (1024px) from the ez-tree demo app (MIT). Terrain3D grassland themes apply it across the whole ground band (demo parity); also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"ground_grass","file":"vegetation/ground/grass.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/grass.jpg","kind":"foliage","bytes":322486,"description":"Mossy meadow grass ground texture (1024px) from the ez-tree demo app (MIT). Terrain3D grassland themes (meadow/forest generators) tile it as the grass splat layer by default; also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"heal","file":"audio/heal.mp3","url":"incanto/assets/audio/heal.mp3","kind":"audio","bytes":29764,"description":"Soothing health-restore / heal spell SFX."},{"name":"hit-metal-bang","file":"audio/hit_metal_bang.mp3","url":"incanto/assets/audio/hit_metal_bang.mp3","kind":"audio","bytes":17972,"description":"Metallic impact — hitting armor, metal, or a blocked attack."},{"name":"hp_potion","file":"items/hp_potion.png","url":"incanto/assets/items/hp_potion.png","kind":"item","bytes":3513,"description":"Health potion item sprite for Dungeons and Dungeoners. Consumable healing item that restores player health points when used."},{"name":"ice-spear","file":"audio/ice_spear.mp3","url":"incanto/assets/audio/ice_spear.mp3","kind":"audio","bytes":21315,"description":"Sharp piercing ice projectile fire SFX."},{"name":"leaves_ash","file":"vegetation/ash_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ash_color.png","kind":"foliage","bytes":181423,"description":"Ash leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for broadleaf/dead ash variants by default; copy it next to your game and set leafTexture to serve offline."},{"name":"leaves_aspen","file":"vegetation/aspen_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/aspen_color.png","kind":"foliage","bytes":142116,"description":"Aspen leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for high-tier broadleaf aspen variants; copy + leafTexture for offline serving."},{"name":"leaves_oak","file":"vegetation/oak_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/oak_color.png","kind":"foliage","bytes":238115,"description":"Oak leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for broadleaf oak variants by default; copy + leafTexture for offline serving."},{"name":"leaves_pine","file":"vegetation/pine_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/pine_color.png","kind":"foliage","bytes":303684,"description":"Pine needle-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for conifer variants by default; copy + leafTexture for offline serving."},{"name":"locked_item_box","file":"items/locked_item_box.png","url":"incanto/assets/items/locked_item_box.png","kind":"item","bytes":11074,"description":"Locked item box sprite for Dungeons and Dungeoners. Container sprite requiring key or lockpick to open, containing valuable rewards."},{"name":"map","file":"items/map.png","url":"incanto/assets/items/map.png","kind":"item","bytes":3754,"description":"Map item sprite for Dungeons and Dungeoners. Navigation item revealing dungeon layout or providing exploration assistance."},{"name":"medieval-knight","file":"characters/medieval-knight.png","url":"incanto/assets/characters/medieval-knight.png","kind":"character","bytes":84367,"description":"(frame size 192x192) Using a medieval-themed SD(Super Deformed) knight sprite sheet image, you can apply idle, move, and attack animations, among others.","animation":"characters/medieval-knight.json","frameWidth":192,"frameHeight":192},{"name":"minecraft-tiles","file":"tiles/minecraft-tiles.png","url":"incanto/assets/tiles/minecraft-tiles.png","kind":"tile","bytes":10511,"description":"Minecraft-themed tiles sprite sheet image (frame size 16x16)"},{"name":"monster-died","file":"audio/monster_died.mp3","url":"incanto/assets/audio/monster_died.mp3","kind":"audio","bytes":16836,"description":"Enemy defeat / death SFX."},{"name":"resurrection_potion","file":"items/resurrection_potion.png","url":"incanto/assets/items/resurrection_potion.png","kind":"item","bytes":3471,"description":"Resurrection potion item sprite for Dungeons and Dungeoners. Rare consumable that revives fallen party members or prevents death."},{"name":"slash","file":"audio/slash.mp3","url":"incanto/assets/audio/slash.mp3","kind":"audio","bytes":10425,"description":"Quick sword swing / melee slash SFX."},{"name":"smite","file":"audio/smite.mp3","url":"incanto/assets/audio/smite.mp3","kind":"audio","bytes":12956,"description":"Powerful holy downward-strike SFX."},{"name":"spells-cast","file":"audio/spells_cast.mp3","url":"incanto/assets/audio/spells_cast.mp3","kind":"audio","bytes":22151,"description":"Generic magical spell-cast / chant SFX."},{"name":"super_box","file":"items/super_box.png","url":"incanto/assets/items/super_box.png","kind":"item","bytes":12184,"description":"Super item box sprite for Dungeons and Dungeoners. Premium container sprite containing rare or powerful items and equipment."},{"name":"swoosh","file":"effects/swoosh.png","url":"incanto/assets/effects/swoosh.png","kind":"effect","bytes":2599,"description":"Swoosh effect sprite for Dungeons and Dungeoners. Motion blur or attack trail effect used for melee attacks, sword slashes, or fast movement animations."},{"name":"trap","file":"items/trap.png","url":"incanto/assets/items/trap.png","kind":"item","bytes":3969,"description":"Trap object sprite for Dungeons and Dungeoners. Hazard sprite that damages players when triggered in dungeon exploration."},{"name":"ui-click","file":"audio/ui_click.wav","url":"incanto/assets/audio/ui_click.wav","kind":"audio","bytes":17332,"description":"Short tactile UI click for menus and buttons."},{"name":"walk","file":"audio/walk.mp3","url":"incanto/assets/audio/walk.mp3","kind":"audio","bytes":5642,"description":"Single footstep SFX for character movement (loop or one-shot)."},{"name":"wall00","file":"tiles/wall00.jpg","url":"incanto/assets/tiles/wall00.jpg","kind":"tile","bytes":44344,"description":"Basic wall tile texture for Dungeons and Dungeoners project, suitable for dungeon vertical boundaries."}]');function BN(e,t,n,r){return{cx:Math.floor((n-e.x)/t),cy:Math.floor((r-e.y)/t)}}function VN(e,t,n,r){if(t<0||n<0||r.length!==1)return null;let i=e.map(e=>typeof e==`string`?e:e.map(e=>e>=0&&e<=9?String(e):`.`).join(``)),a=Math.max(t+1,...i.map(e=>e.length)),o=Math.max(n+1,i.length),s=[];for(let e=0;e<o;e++){let o=i[e]??``;o=o.padEnd(a,`.`),e===n&&(o=o.slice(0,t)+r+o.slice(t+1)),s.push(o)}return s}function HN(e,t){let n=new Set([`.`,`0`,`1`]);for(let t of e)if(typeof t==`string`)for(let e of t)e!==` `&&n.add(e);for(let e of Object.keys(t))n.add(e);return[...n]}var UN=zN;function WN(e){return(e.kind===`foliage`||e.kind===`tile`)&&!e.animation}function GN(e,t,n){if(e.textContent=``,t.selection===null){qN(e,t,n);return}let r=t.nodeAt(t.selection);r&&$N(e,t,r,n)}var KN=[`input`,`multiplayer`];function qN(e,t,n){e.appendChild(wP(`scene`)),e.appendChild(OP(`name`,String(t.working.name??``),e=>{t.mutate(()=>{t.working.name=e})}));let r=document.createElement(`select`);for(let e of[`2d`,`3d`]){let n=document.createElement(`option`);n.value=e,n.textContent=e,(t.working.dimension??`2d`)===e&&(n.selected=!0),r.appendChild(n)}r.addEventListener(`change`,()=>{t.mutate(()=>{t.working.dimension=r.value})}),e.appendChild(EP(`dimension`,r)),e.appendChild(wP(`physics`,`physics`));let i=(t.working.physics??{}).gravity??(t.working.dimension===`3d`?[0,-9.81,0]:[0,980]),a=t.working.dimension===`3d`?[0,-9.81,0]:[0,980];e.appendChild(AP(`gravity`,i,e=>{t.mutate(()=>{if(JSON.stringify(e)===JSON.stringify(a)){let e={...t.working.physics};delete e.gravity,Object.keys(e).length===0?delete t.working.physics:t.working.physics=e}else t.working.physics={...t.working.physics,gravity:e}})})),e.appendChild(wP(`environment`)),JN(e,t),e.appendChild(wP(`constants`)),vP(e,t,n),e.appendChild(wP(`advanced`));for(let n of KN)e.appendChild(MP(n,t.working[n],e=>{t.mutate(()=>{e===void 0?delete t.working[n]:t.working[n]=e})}))}function JN(e,t){let n=t.working.environment??{},r=e=>{t.mutate(()=>{let n={...t.working.environment??{},...e};for(let e of Object.keys(n))n[e]===void 0&&delete n[e];Object.keys(n).length===0?delete t.working.environment:t.working.environment=n})};e.appendChild(YN(`background`,n.background??``,e=>{r({background:e===``?void 0:e})})),e.appendChild(YN(`ambient color`,n.ambient?.color??``,e=>{let t={...n.ambient,color:e===``?void 0:e};t.color===void 0&&delete t.color,r({ambient:Object.keys(t).length?t:void 0})})),e.appendChild(kP(`ambient power`,n.ambient?.intensity??0,e=>{r({ambient:{...n.ambient,intensity:e}})}));let i=n.rendering??{},a=e=>{let t={...i,...e};for(let e of Object.keys(t))t[e]===void 0&&delete t[e];r({rendering:Object.keys(t).length?t:void 0})},o=document.createElement(`input`);o.type=`checkbox`,o.checked=i.antialias!==!1,o.addEventListener(`change`,()=>{a({antialias:o.checked?void 0:!1})}),e.appendChild(EP(`antialias`,o));let s=document.createElement(`select`);for(let[e,t]of[[``,`1 — soft hiDPI upscale (default)`],[`device`,`device — crisp retina`],[`2`,`2`]]){let n=document.createElement(`option`);n.value=e,n.textContent=t,String(i.pixelRatio??``)===e&&(n.selected=!0),s.appendChild(n)}s.addEventListener(`change`,()=>{a({pixelRatio:s.value===``?void 0:s.value===`device`?`device`:Number(s.value)})}),e.appendChild(EP(`pixel ratio`,s))}function YN(e,t,n){let r=document.createElement(`div`);r.className=`color-row`;let i=document.createElement(`input`);i.type=`color`,i.value=/^#[0-9a-fA-F]{6}$/.test(t)?t:`#000000`;let a=document.createElement(`input`);return a.type=`text`,a.className=`mono`,a.placeholder=`unset`,a.value=t,i.addEventListener(`input`,()=>{a.value=i.value}),i.addEventListener(`change`,()=>n(i.value)),a.addEventListener(`change`,()=>n(a.value.trim())),r.append(i,a),EP(e,r)}function XN(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.textContent=`underwater`,n.appendChild(r);let i=t.props?.underwater,a=i!==!1,o=i&&typeof i==`object`&&!Array.isArray(i)?i:{},s=n=>{e.mutate(()=>{t.props||={},n===!0?delete t.props.underwater:t.props.underwater=n,Object.keys(t.props).length===0&&delete t.props})},c=(e,t)=>{let n={...o};t===void 0||t===``?delete n[e]:n[e]=t,s(Object.keys(n).length===0?!0:n)},l=document.createElement(`input`);if(l.type=`checkbox`,l.checked=a,l.addEventListener(`change`,()=>s(l.checked)),n.appendChild(EP(`enabled`,l)),a){n.appendChild(YN(`murk color`,String(o.color??``),e=>c(`color`,e))),n.appendChild(kP(`visibility (m)`,Number(o.visibility??22),e=>c(`visibility`,e===22?void 0:e),()=>c(`visibility`,void 0)));let e=document.createElement(`input`);e.type=`checkbox`,e.checked=(o.caustics??!0)!==!1,e.addEventListener(`change`,()=>c(`caustics`,e.checked?void 0:!1)),n.appendChild(EP(`caustics`,e))}return n}function ZN(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.textContent=`material`,n.appendChild(r);let i=t.props?.material??{},a=(n,r)=>{let i={...t.props?.material??{}};r===void 0||r===``?delete i[n]:i[n]=r;let a=Object.keys(i).length===0?void 0:i;e.mutate(()=>{t.props||={},a===void 0?(delete t.props.material,Object.keys(t.props).length===0&&delete t.props):t.props.material=a},e.selection?{path:e.selection,key:`material`,value:a}:void 0)};n.appendChild(YN(`color`,String(i.color??``),e=>a(`color`,e))),n.appendChild(QN(`roughness`,Number(i.roughness??1),e=>a(`roughness`,e))),n.appendChild(QN(`metalness`,Number(i.metalness??0),e=>a(`metalness`,e))),n.appendChild(YN(`emissive`,String(i.emissive??``),e=>a(`emissive`,e))),n.appendChild(QN(`emissive power`,Number(i.emissiveIntensity??1),e=>a(`emissiveIntensity`,e===1?void 0:e),2)),n.appendChild(QN(`opacity`,Number(i.opacity??1),e=>a(`opacity`,e===1?void 0:e))),n.appendChild(QN(`clearcoat`,Number(i.clearcoat??0),e=>a(`clearcoat`,e===0?void 0:e))),n.appendChild(QN(`clearcoat rough`,Number(i.clearcoatRoughness??0),e=>a(`clearcoatRoughness`,e===0?void 0:e))),n.appendChild(QN(`reflection`,Number(i.envMapIntensity??1),e=>a(`envMapIntensity`,e===1?void 0:e),3));let o=document.createElement(`input`);o.type=`checkbox`,o.checked=i.wireframe===!0,o.addEventListener(`change`,()=>a(`wireframe`,o.checked||void 0)),n.appendChild(EP(`wireframe`,o));let s=document.createElement(`input`);s.type=`checkbox`,s.checked=i.flatShading===!0,s.addEventListener(`change`,()=>a(`flatShading`,s.checked||void 0)),n.appendChild(EP(`flatShading`,s));let c=document.createElement(`input`);c.type=`checkbox`,c.checked=i.depthTest===!1,c.addEventListener(`change`,()=>{a(`depthTest`,c.checked?!1:void 0),a(`depthWrite`,c.checked?!1:void 0)}),n.appendChild(EP(`draw on top (decal)`,c)),n.appendChild(lP(`map (texture)`,String(i.map??``),uP(e=>WN(e)&&!e.name.includes(`normal`)&&!e.name.includes(`roughness`)),e=>a(`map`,e.trim()),{placeholder:`built-in or custom URL`})),n.appendChild(lP(`normal map`,String(i.normalMap??``),uP(e=>WN(e)&&e.name.includes(`normal`)),e=>a(`normalMap`,e.trim()),{placeholder:`built-in or custom URL`}));let l=!!(i.map||i.normalMap),u=Array.isArray(i.repeat)?i.repeat:[1,1],d=AP(`repeat [u,v]`,[u[0]??1,u[1]??1],e=>{let[t,n]=e;!Number.isFinite(t)||!Number.isFinite(n)||t===1&&n===1||!t&&!n?a(`repeat`,void 0):a(`repeat`,[t,n])});return d.title=l?`Texture tiling across the mesh UVs.`:`Only takes effect with a map/normal map set (engine validates).`,n.appendChild(d),n}function QN(e,t,n,r=1){let i=document.createElement(`div`);i.className=`slider-row`;let a=document.createElement(`input`);a.type=`range`,a.min=`0`,a.max=String(r),a.step=`0.05`,a.value=String(Number.isFinite(t)?t:0);let o=document.createElement(`input`);return o.type=`number`,o.step=`0.05`,o.min=`0`,o.max=String(r),o.value=a.value,a.addEventListener(`input`,()=>{o.value=a.value}),a.addEventListener(`change`,()=>n(Number(a.value))),o.addEventListener(`change`,()=>{a.value=o.value,n(Number(o.value))}),i.append(a,o),EP(e,i)}function $N(e,t,n,r){if(e.appendChild(wP(n.type??`instance`)),e.appendChild(eP(n)),e.appendChild(OP(`name`,n.name??``,e=>{e.trim()!==``&&t.mutate(()=>{n.name=e.trim()})})),n.type===`TileMap2D`&&r?.paint&&e.appendChild(jP(n,r.paint)),n.type){let i;try{i=ge(n.type)}catch{i={}}for(let[a,o]of Object.entries(i))if(a===`collider`)e.appendChild(iP(t,n,o.default));else if(a===`material`)e.appendChild(ZN(t,n));else if(n.type===`ModelInstance3D`&&a===`model`&&r)e.appendChild(sP(`model`,String(n.props?.model??``),r.modelRefs(),e=>aP(t,n,`model`,e,``)));else if(n.type===`BoneAttachment3D`&&a===`bone`&&r?.bonesForSelection)e.appendChild(sP(`bone`,String(n.props?.bone??``),r.bonesForSelection(String(n.props?.target??``)),e=>aP(t,n,`bone`,e,``)));else if(n.type===`ModelInstance3D`&&a===`animation`&&r)e.appendChild(sP(`animation`,String(n.props?.animation??``),r.animationsForSelection(),e=>aP(t,n,`animation`,e,``)));else if(n.type===`Tree3D`&&a===`leafTexture`)e.appendChild(lP(`leaf texture`,String(n.props?.leafTexture??``),uP(e=>e.name.startsWith(`leaves_`)),e=>aP(t,n,`leafTexture`,e.trim(),``),{placeholder:`default (per-type) or URL`}));else if(n.type===`Terrain3D`&&a===`textureBase`)e.appendChild(lP(`texture base`,String(n.props?.textureBase??o.default??``),fP,e=>aP(t,n,`textureBase`,e.trim(),o.default),{placeholder:`splat texture base URL`}));else if(n.type===`AnimatedSprite2D`&&a===`sheet`||n.type===`Sprite2D`&&a===`texture`){let i=a===`sheet`;e.appendChild(pP(t,n,a,r,i))}else n.type===`AudioPlayer`&&a===`src`?e.appendChild(lP(`src (audio file)`,String(n.props?.src??``),dP(),e=>aP(t,n,`src`,e.trim(),``),{placeholder:`built-in or custom URL — or use preset`,note:"For zero-asset SFX, set the `preset` prop instead of src."})):n.type===`Flowers3D`&&a===`varieties`?e.appendChild(mP(t,n)):n.type===`Water3D`&&a===`underwater`?e.appendChild(XN(t,n)):e.appendChild(bP(t,n,a,o.default,o.options))}e.appendChild(wP(`structure`)),e.appendChild(tP(t,n)),e.appendChild(nP(t,n)),e.appendChild(rP(t,n))}function eP(e){let t=document.createElement(`div`);t.className=`field uid-line`;let n=document.createElement(`span`);n.textContent=`uid`;let r=document.createElement(`div`);r.className=`uid-value`;let i=document.createElement(`code`);i.textContent=String(e.uid??``);let a=document.createElement(`button`);return a.type=`button`,a.className=`uid-copy`,a.title=`Copy uid`,a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,a.addEventListener(`click`,()=>{navigator.clipboard?.writeText(String(e.uid??``)),a.classList.add(`copied`),a.innerHTML=`✓`,setTimeout(()=>{a.classList.remove(`copied`),a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`},800)}),r.append(i,a),t.append(n,r),t}function tP(e,t){let n=document.createElement(`label`);n.className=`field wide`;let r=document.createElement(`span`);r.append(`groups `,RN(`groups`));let i=document.createElement(`div`);i.className=`chips`;for(let n of t.groups??[])i.appendChild(TP(n,()=>{e.mutate(()=>{t.groups=(t.groups??[]).filter(e=>e!==n),t.groups.length===0&&delete t.groups})}));let a=document.createElement(`input`);return a.placeholder=(t.groups?.length??0)===0?`add a tag… (e.g. coins)`:``,a.addEventListener(`keydown`,n=>{if(n.key!==`Enter`)return;let r=a.value.trim();r&&e.mutate(()=>{t.groups=[...t.groups??[],r]})}),i.appendChild(a),i.addEventListener(`click`,()=>a.focus()),n.append(r,i),n}function nP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.append(`script `,RN(`script`));let i=document.createElement(`span`);i.className=`spacer`,r.appendChild(i);let a=t.script;if(a){let n=document.createElement(`button`);n.type=`button`,n.className=`linklike`,n.textContent=`detach`,n.addEventListener(`click`,()=>{e.mutate(()=>{delete t.script})}),r.appendChild(n)}if(n.appendChild(r),!a){let r=document.createElement(`div`);r.className=`muted-note`,r.textContent=`No behavior attached. Behaviors are TypeScript classes in your game.`;let i=document.createElement(`button`);return i.type=`button`,i.className=`ghost`,i.textContent=`+ attach behavior`,i.addEventListener(`click`,()=>{e.mutate(()=>{t.script={name:`MyBehavior`}})}),n.append(r,i),n}n.appendChild(OP(`name`,a.name??``,n=>{e.mutate(()=>{t.script.name=n.trim()})})),n.appendChild(MP(`props`,a.props,n=>{e.mutate(()=>{n===void 0?delete t.script.props:t.script.props=n})}));let o=document.createElement(`div`);return o.className=`muted-note`,o.textContent=`? has copy-paste boilerplate for the game side.`,n.appendChild(o),n}function rP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.append(`network `,RN(`network`)),n.appendChild(r);let i=t.network,a=document.createElement(`select`);for(let[e,t]of[[``,`not replicated`],[`owner`,`owner — this player broadcasts it`]]){let n=document.createElement(`option`);n.value=e,n.textContent=t,(i?.mode??``)===e&&(n.selected=!0),a.appendChild(n)}if(a.addEventListener(`change`,()=>{e.mutate(()=>{a.value===``?delete t.network:t.network={mode:a.value,sync:i?.sync??[`position`]}})}),n.appendChild(EP(`mode`,a)),i?.mode===`owner`){let r=document.createElement(`div`);r.className=`chips`;for(let n of i.sync??[])r.appendChild(TP(n,()=>{e.mutate(()=>{t.network.sync=(i.sync??[]).filter(e=>e!==n)})}));let a=document.createElement(`input`);a.placeholder=`position · Skin.animation…`,a.addEventListener(`keydown`,n=>{if(n.key!==`Enter`)return;let r=a.value.trim();r&&e.mutate(()=>{t.network.sync=[...i.sync??[],r]})}),r.appendChild(a);let o=document.createElement(`label`);o.className=`field wide`;let s=document.createElement(`span`);s.textContent=`sync keys`,o.append(s,r),n.appendChild(o),n.appendChild(kP(`throttle ms`,i.throttleMs??50,n=>{e.mutate(()=>{t.network.throttleMs=n})}))}return n}function iP(e,t,n){let r=document.createElement(`div`);r.className=`subcard`;let i=document.createElement(`div`);i.className=`subcard-head`,i.append(`collider `,RN(`collider`)),r.appendChild(i);let a=t.props?.collider??{},o=n=>{e.mutate(()=>{t.props||={};let e=t.props;Object.keys(n).length===0?(delete e.collider,Object.keys(e).length===0&&delete t.props):e.collider=n})},s=(t.type??``).endsWith(`3D`),c=s?[[``,`none`],[`box`,`box — crates, floors`],[`sphere`,`sphere — balls, pickups`],[`capsule`,`capsule — characters`]]:[[``,`none`],[`rect`,`rect — boxes, platforms`],[`circle`,`circle — coins, balls`],[`capsule`,`capsule — characters`]],l=document.createElement(`select`);for(let[e,t]of c){let n=document.createElement(`option`);n.value=e,n.textContent=t,(a.shape??``)===e&&(n.selected=!0),l.appendChild(n)}return l.addEventListener(`change`,()=>{l.value===``?o({}):l.value===`rect`?o({shape:`rect`,size:a.size??[32,32]}):l.value===`box`?o({shape:`box`,size:a.size??[1,1,1]}):l.value===`circle`?o({shape:`circle`,radius:a.radius??16}):l.value===`sphere`?o({shape:`sphere`,radius:a.radius??.5}):o(s?{shape:`capsule`,radius:a.radius??.4,height:a.height??1}:{shape:`capsule`,radius:a.radius??12,height:a.height??16})}),r.appendChild(EP(`shape`,l)),a.shape===`rect`||a.shape===`box`?r.appendChild(AP(`size`,a.size??(s?[1,1,1]:[32,32]),e=>o({...a,size:e}))):a.shape===`circle`||a.shape===`sphere`?r.appendChild(kP(`radius`,a.radius??(s?.5:16),e=>o({...a,radius:e}))):a.shape===`capsule`&&(r.appendChild(kP(`radius`,a.radius??12,e=>o({...a,radius:e}))),r.appendChild(kP(`height`,a.height??16,e=>o({...a,height:e})))),a.shape&&r.appendChild(AP(`offset`,a.offset??(s?[0,0,0]:[0,0]),e=>o({...a,offset:e}))),r}function aP(e,t,n,r,i){e.mutate(()=>{t.props||={},JSON.stringify(r)===JSON.stringify(i)?(delete t.props[n],Object.keys(t.props).length===0&&delete t.props):t.props[n]=r})}var oP=0;function sP(e,t,n,r){let i=document.createElement(`input`);i.type=`text`,i.value=t;let a=`suggest-${oP++}`;i.setAttribute(`list`,a);let o=document.createElement(`datalist`);o.id=a;for(let e of n){let t=document.createElement(`option`);t.value=e,o.appendChild(t)}i.addEventListener(`change`,()=>r(i.value.trim()));let s=EP(e,i);return s.appendChild(o),s}var cP=0;function lP(e,t,n,r,i={}){let a=document.createElement(`label`);a.className=`field wide asset-field`;let o=document.createElement(`span`);o.textContent=e,a.appendChild(o);let s=document.createElement(`input`);s.type=`text`,s.value=t,i.placeholder&&(s.placeholder=i.placeholder),s.addEventListener(`change`,()=>r(s.value.trim()));let c=document.createElement(`button`);c.type=`button`,c.className=`asset-toggle`,c.title=`Browse built-in assets`,c.textContent=`▾`;let l=document.createElement(`div`);l.className=`asset-control`,l.append(s,c),a.appendChild(l);let u=document.createElement(`div`);u.className=`asset-panel`,u.hidden=!0;let d=document.createElement(`input`);d.type=`text`,d.className=`asset-search`,d.placeholder=`search ${n.length} built-in${n.length===1?``:`s`}…`;let f=document.createElement(`div`);f.className=`asset-options`,u.append(d,f),a.appendChild(u);let p=e=>{f.textContent=``;let t=e.trim().toLowerCase(),i=n.filter(e=>t===``||e.label.toLowerCase().includes(t)||(e.hint?.toLowerCase().includes(t)??!1)||e.value.toLowerCase().includes(t));if(i.length===0){let e=document.createElement(`div`);e.className=`asset-empty`,e.textContent=`no match — type a custom URL above`,f.appendChild(e);return}for(let e of i){let t=document.createElement(`button`);t.type=`button`,t.className=`asset-option`;let n=document.createElement(`strong`);if(n.textContent=e.label,t.appendChild(n),e.hint){let n=document.createElement(`small`);n.textContent=e.hint,t.appendChild(n)}t.addEventListener(`click`,()=>{s.value=e.value,u.hidden=!0,r(e.value)}),f.appendChild(t)}};if(c.addEventListener(`click`,()=>{u.hidden=!u.hidden,u.hidden||(p(d.value),d.focus())}),d.addEventListener(`input`,()=>p(d.value)),d.addEventListener(`keydown`,e=>{e.key===`Escape`&&(u.hidden=!0)}),i.note){let e=document.createElement(`div`);e.className=`muted-note asset-note`,e.textContent=i.note,a.appendChild(e)}return s.id=`asset-input-${cP++}`,a.htmlFor=s.id,a}function uP(e){return UN.filter(e).map(e=>({label:e.name,value:e.url,hint:`${e.kind} · ${e.description.slice(0,70)}`}))}function dP(){return UN.filter(e=>e.kind===`audio`).map(e=>({label:e.name,value:e.url,hint:`audio · ${e.description.slice(0,70)}`}))}var fP=[{label:`agent8 default terrain`,value:`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,hint:`sand/grass/stone/snow splat set (Terrain3D default)`}];function pP(e,t,n,r,i){let a=String(t.props?.[n]??``),o=i?[`spritesheet`]:[`texture`,`spritesheet`],s=(r?.assetRefs?.(o)??[]).map(e=>({label:e,value:e,hint:`scene asset`})),c=UN.filter(e=>i?!!e.animation:e.kind===`character`||e.kind===`item`||e.kind===`tile`);for(let e of c)s.push({label:`built-in: ${e.name}`,value:`$${e.name}`,hint:`${e.kind} · creates a scene asset (${e.animation?`spritesheet`:`texture`})`});return lP(i?`sheet`:`texture`,a,s,i=>{let a=i.startsWith(`$`)&&c.find(e=>`$${e.name}`===i);if(a&&r?.addAsset){let i={type:a.animation?`spritesheet`:`texture`,url:a.url};if(a.animation){let e=a.frameWidth,t=a.frameHeight;e&&(i.frameWidth=e),t&&(i.frameHeight=t)}aP(e,t,n,`$${r.addAsset(a.name,i).replace(/^\$/,``)}`,``);return}aP(e,t,n,i.trim(),``)},{placeholder:`$assetKey`,note:"Picks a $asset ref. Built-ins create the scene asset; packaged sprites need `incanto-assets copy` (or a bundler import) to serve at runtime."})}function mP(e,t){let n=document.createElement(`label`);n.className=`field wide`;let r=document.createElement(`span`);r.textContent=`varieties`,n.appendChild(r);let i=new Set(Array.isArray(t.props?.varieties)?t.props.varieties:[]),a=document.createElement(`div`);a.className=`chips varieties`;let o=()=>{let n=iw.filter(e=>i.has(e));aP(e,t,`varieties`,n.length===0||n.length===iw.length?[]:n,[])};for(let e of iw){let t=document.createElement(`label`);t.className=`variety-opt`;let n=document.createElement(`input`);n.type=`checkbox`,n.checked=i.size===0||i.has(e),n.addEventListener(`change`,()=>{if(i.size===0)for(let e of iw)i.add(e);n.checked?i.add(e):i.delete(e),o()});let r=document.createElement(`span`);r.textContent=e,t.append(n,r),a.appendChild(t)}n.appendChild(a);let s=document.createElement(`div`);return s.className=`muted-note`,s.textContent=`All (or none) = the default mix of all three.`,n.appendChild(s),n}var hP=[[`number`,()=>0],[`text`,()=>``],[`boolean`,()=>!1],[`color`,()=>`#ffffff`],[`vec2`,()=>[0,0]],[`vec3`,()=>[0,0,0]]];function gP(e,t){let n=0,r=e=>{if(dt(e)){e[`@const`]===t&&(n+=1);return}if(Array.isArray(e))for(let t of e)r(t);else if(e&&typeof e==`object`)for(let t of Object.values(e))r(t)};for(let[t,n]of Object.entries(e))t!==`constants`&&r(n);return n}function _P(e,t,n){let r=e=>{if(dt(e))return e[`@const`]===t?JSON.parse(JSON.stringify(n??null)):e;if(Array.isArray(e))return e.map(r);if(e&&typeof e==`object`){let t=e;for(let e of Object.keys(t))t[e]=r(t[e]);return t}return e};for(let t of Object.keys(e))t!==`constants`&&(e[t]=r(e[t]))}function vP(e,t,n){let r=t.working.constants??{},i=Object.keys(r),a=(e,n)=>{t.mutate(()=>{let r={...t.working.constants??{}};r[e]=n,t.working.constants=r})},o=(e,n)=>{t.mutate(()=>{n&&_P(t.working,e,r[e]);let i={...t.working.constants??{}};delete i[e],Object.keys(i).length===0?delete t.working.constants:t.working.constants=i})},s=e=>{let r=gP(t.working,e);if(r>0&&n?.confirm){n.confirm(`"${e}" is used by ${r} prop${r===1?``:`s`}. Unlink them (inline its current value) and delete?`,`unlink & delete`,()=>o(e,!0));return}o(e,r>0)};if(i.length===0){let t=document.createElement(`div`);t.className=`hint`,t.textContent=`No constants yet. Add one, then bind props to it with the 🔗 picker.`,e.appendChild(t)}for(let t of i){let n=document.createElement(`div`);n.className=`const-row`,n.appendChild(yP(t,r[t],e=>a(t,e)));let i=document.createElement(`button`);i.type=`button`,i.className=`const-del`,i.textContent=`✕`,i.title=`delete constant "${t}"`,i.addEventListener(`click`,()=>s(t)),n.appendChild(i),e.appendChild(n)}let c=document.createElement(`div`);c.className=`const-add`;let l=document.createElement(`input`);l.type=`text`,l.placeholder=`new constant name`;let u=document.createElement(`select`);for(let[e]of hP){let t=document.createElement(`option`);t.value=e,t.textContent=e,u.appendChild(t)}let d=document.createElement(`button`);d.type=`button`,d.textContent=`+ add`,d.addEventListener(`click`,()=>{let e=l.value.trim();e&&(t.working.constants??{})[e]===void 0&&(a(e,(hP.find(([e])=>e===u.value)?.[1]??(()=>0))()),l.value=``)}),c.append(l,u,d),e.appendChild(c)}function yP(e,t,n){let r=ue(t);if(r===`number`)return kP(e,t,e=>n(e),()=>n(0));if(r===`boolean`){let r=document.createElement(`input`);return r.type=`checkbox`,r.checked=t===!0,r.addEventListener(`change`,()=>n(r.checked)),EP(e,r)}return r===`array`&&Array.isArray(t)&&t.every(e=>typeof e==`number`)?AP(e,t,e=>n(e)):r===`string`?OP(e,String(t),e=>n(e)):MP(e,t,e=>n(e??null),JSON.stringify(t))}function bP(e,t,n,r,i){let a=t.props?.[n]??r,o=ue(r),s=o===`number`||o===`boolean`||o===`string`||o===`array`,c=i=>{let a=dt(i);e.mutate(()=>{t.props||={};let e=t.props;JSON.stringify(i)===JSON.stringify(r)?(delete e[n],Object.keys(e).length===0&&delete t.props):e[n]=i},e.selection&&s&&!a?{path:e.selection,key:n,value:i}:void 0)},l=xP(e,o,r);if(dt(a))return SP(n,a[`@const`],l,c,r);let u=e=>l.length>0?CP(e,l,c):e;if(o===`number`)return u(kP(n,a,e=>c(e),()=>c(r)));if(o===`boolean`){let e=document.createElement(`input`);return e.type=`checkbox`,e.checked=a===!0,e.addEventListener(`change`,()=>c(e.checked)),u(EP(n,e))}return o===`string`?i&&i.length>0?u(DP(n,String(a??``),i,e=>c(e))):u(OP(n,String(a??``),e=>c(e))):o===`array`&&Array.isArray(r)&&r.length>0&&r.every(e=>typeof e==`number`)?u(AP(n,a??r,e=>c(e))):MP(n,a===r?void 0:a,e=>{c(e===void 0?r:e)},JSON.stringify(r))}function xP(e,t,n){let r=e.working.constants??{};return Object.keys(r).filter(e=>{let i=r[e];return ue(i)===t?t===`array`&&Array.isArray(n)&&Array.isArray(i)?i.length===n.length:!0:!1})}function SP(e,t,n,r,i){let a=document.createElement(`select`),o=n.includes(t)?n:[t,...n];for(let e of o){let n=document.createElement(`option`);n.value=e,n.textContent=e,e===t&&(n.selected=!0),a.appendChild(n)}let s=document.createElement(`option`);s.value=``,s.textContent=`↺ custom value`,a.appendChild(s),a.addEventListener(`change`,()=>{r(a.value?{"@const":a.value}:i)});let c=EP(`🔗 ${e}`,a);return c.classList.add(`const-bound`),c}function CP(e,t,n){let r=document.createElement(`select`);r.className=`const-picker`,r.title=`Bind to a named constant`;let i=document.createElement(`option`);i.value=``,i.textContent=`🔗`,r.appendChild(i);for(let e of t){let t=document.createElement(`option`);t.value=e,t.textContent=e,r.appendChild(t)}return r.value=``,r.addEventListener(`change`,()=>{r.value&&n({"@const":r.value})}),e.appendChild(r),e}function wP(e,t){let n=document.createElement(`div`);n.className=`section-title`,n.textContent=e,t&&n.appendChild(RN(t));let r=document.createElement(`span`);return r.className=`rule`,n.appendChild(r),n}function TP(e,t){let n=document.createElement(`span`);n.className=`chip`,n.textContent=e;let r=document.createElement(`button`);return r.type=`button`,r.textContent=`✕`,r.addEventListener(`click`,e=>{e.stopPropagation(),t()}),n.appendChild(r),n}function EP(e,t){let n=document.createElement(`label`);n.className=`field`;let r=document.createElement(`span`);return r.textContent=e,n.append(r,t),n}function DP(e,t,n,r){let i=document.createElement(`select`);for(let e of n.includes(t)?n:[t,...n]){let n=document.createElement(`option`);n.value=e,n.textContent=e,e===t&&(n.selected=!0),i.appendChild(n)}return i.addEventListener(`change`,()=>r(i.value)),EP(e,i)}function OP(e,t,n){let r=document.createElement(`input`);return r.type=`text`,r.value=t,r.addEventListener(`change`,()=>n(r.value)),EP(e,r)}function kP(e,t,n,r){let i=document.createElement(`input`);return i.type=`number`,i.step=`any`,i.value=String(t),i.addEventListener(`change`,()=>{if(i.value.trim()===``){r?.();return}let e=Number(i.value);Number.isFinite(e)&&n(e)}),EP(e,i)}function AP(e,t,n){let r=document.createElement(`div`);r.className=`vector-row`;let i=[...t];return i.forEach((e,t)=>{let a=document.createElement(`input`);a.type=`number`,a.step=`any`,a.value=String(e??0),a.addEventListener(`change`,()=>{let e=Number(a.value);Number.isFinite(e)&&(i[t]=e,n([...i]))}),r.appendChild(a)}),EP(e,r)}function jP(e,t){let n=document.createElement(`div`);n.className=`field wide tile-paint`;let r=document.createElement(`button`);r.type=`button`,r.className=t.active()?`paint-toggle on`:`paint-toggle`,r.textContent=t.active()?`🖌 painting — click the canvas`:`🖌 paint tiles`,r.addEventListener(`click`,()=>t.toggle()),n.appendChild(r);let i=document.createElement(`div`);i.className=`paint-palette`;let a=e.props?.cells??[],o=e.props?.legend??{};for(let e of HN(a,o)){let n=document.createElement(`button`);n.type=`button`,n.className=t.brush()===e?`paint-chip on`:`paint-chip`,n.textContent=e===`.`?`␡`:e,n.title=e===`.`?`eraser (empty cell)`:`tile '${e}'`,n.addEventListener(`click`,()=>t.setBrush(e)),i.appendChild(n)}let s=document.createElement(`input`);s.type=`text`,s.maxLength=1,s.className=`paint-brush-input`,s.value=t.brush(),s.title=`brush char (digit or a legend char)`,s.addEventListener(`change`,()=>{s.value.length===1&&t.setBrush(s.value)}),i.appendChild(s),n.appendChild(i);let c=document.createElement(`div`);return c.className=`paint-hint`,c.textContent=`grid grows right/down; digits map to atlas tiles, others need legend`,n.appendChild(c),n}function MP(e,t,n,r=``){let i=document.createElement(`textarea`);i.rows=3,i.placeholder=r,i.value=t===void 0?``:JSON.stringify(t,null,2),i.addEventListener(`change`,()=>{let e=i.value.trim();if(e===``){i.classList.remove(`invalid`),n(void 0);return}try{let t=JSON.parse(e);i.classList.remove(`invalid`),n(t)}catch{i.classList.add(`invalid`)}});let a=EP(e,i);return a.className=`field wide`,a}var NP=class{working;selection=[];extra=[];validator=null;selectedAsset=null;selectedGroup=null;pendingGroups=new Set;pendingLivePatch=null;addingAsset=!1;addingGroup=!1;newAssetGroup=``;newGroupParent=``;startAddingAsset(){this.addingAsset=!0,this.addingGroup=!1,this.newAssetGroup=this.selectedGroup??``,this.clearFocus()}startAddingGroup(){this.addingGroup=!0,this.addingAsset=!1,this.newGroupParent=this.selectedGroup??``,this.clearFocus()}cancelAddForms(){this.addingAsset=!1,this.addingGroup=!1}onError=null;original;undoStack=[];listeners=new Set;constructor(e){this.working=e,this.original=JSON.stringify(e),this.working.root&&PP(this.working.root)}get dirty(){return JSON.stringify(this.working)!==this.original}get canUndo(){return this.undoStack.length>0}nodeAt(e){if(e===null)return null;let t=this.working.root;for(let n of e)t=t?.children?.[n];return t??null}parentOf(e){return e.length===0?null:this.nodeAt(e.slice(0,-1))}mutate(e,t,n){(!n?.coalesce||this.undoStack.length===0)&&(this.undoStack.push(JSON.stringify(this.working)),this.undoStack.length>100&&this.undoStack.shift()),e(),this.pendingLivePatch=t??null,this.emit()}undo(){let e=this.undoStack.pop();e!==void 0&&(this.working=JSON.parse(e),this.selection=[],this.emit())}transact(e){let t=JSON.stringify(this.working),n=e(),r=e=>(this.working=JSON.parse(t),e&&this.onError?.(e),null);if(n===null)return r();let i=this.validator?.(this.working)??null;return i?r(i):(this.undoStack.push(t),this.undoStack.length>100&&this.undoStack.shift(),this.emit(),n)}moveNode(e,t,n){return this.moveNodes([e],t,n)?.[0]??null}moveNodes(e,t,n){let r=zP(e).filter(e=>e.length>0);if(r.length===0)return null;for(let e of r)if(e.length<=t.length&&e.every((e,n)=>e===t[n]))return null;let i=this.working.root,a=r.map(e=>this.nodeAt(e)).filter(e=>e!==null);if(a.length!==r.length)return null;let o=this.nodeAt(t);return!o||a.includes(o)?null:this.transact(()=>{for(let e of a)VP(i,e);let e,t;if(n===`into`)e=o,e.children||=[],t=e.children.length;else{let r=BP(i,o);if(!r)return null;e=r.parent,t=r.index+ +(n===`after`)}let r=[];a.forEach((n,r)=>{n.name=UP(e,n.name??`Node`),e.children?.splice(t+r,0,n)});for(let e of a){let t=HP(i,e);if(!t)return null;r.push(t)}return r})}duplicateNode(e){if(e.length===0)return null;let t=this.nodeAt(e),n=this.parentOf(e);return!t||!n?.children?null:this.transact(()=>{let r=JSON.parse(JSON.stringify(t));r.name=UP(n,t.name??`Node`),FP(r);let i=e[e.length-1]+1;return n.children?.splice(i,0,r),[...e.slice(0,-1),i]})}removeNodes(e){let t=zP(e).filter(e=>e.length>0);if(t.length===0)return!1;let n=this.working.root,r=t.map(e=>this.nodeAt(e)).filter(e=>e!==null);return this.transact(()=>{for(let e of r)VP(n,e);return!0})===!0}deleteRoot(){this.undoStack.push(JSON.stringify(this.working)),delete this.working.root,this.selection=null,this.extra=[],this.emit()}insertNode(e,t){if(!this.working.root){let t=JSON.parse(JSON.stringify(e));return FP(t),this.transact(()=>(this.working.root=t,[]))}let n=this.nodeAt(t);return n?this.transact(()=>{let r=JSON.parse(JSON.stringify(e));return r.name=UP(n,r.name??`Node`),FP(r),n.children||=[],n.children.push(r),[...t,n.children.length-1]}):null}findRemovalReferences(e){let t=zP(e).filter(e=>e.length>0),n=this.working.root,r=t.map(e=>this.nodeAt(e)).filter(e=>e!==null),i=new Set,a=[];for(let e of t){let t=[],r=n;for(let n of e){let e=r.children?.[n];if(!e)break;t.push(String(e.name)),r=e}a.push(t.join(`/`))}let o=e=>{typeof e.uid==`string`&&i.add(e.uid);for(let t of e.children??[])o(t)};for(let e of r)o(e);let s=[];if((this.working.connections??[]).forEach((e,t)=>{for(let n of[`from`,`to`]){let r=String(e[n]??``);if(a.some(e=>r===e||r.startsWith(`${e}/`))){s.push({kind:`connection`,where:`connections[${t}] ${String(e.signal)}: ${String(e.from)} → ${String(e.to)}`,connectionIndex:t});return}}}),i.size>0){let e=(t,n,a)=>{if(typeof t==`string`){!a&&i.has(t)&&s.push({kind:`uid`,where:n,value:t});return}if(Array.isArray(t)){t.forEach((t,r)=>{e(t,`${n}[${r}]`,a)});return}if(typeof t==`object`&&t){let i=t,o=a||r.includes(i),s=typeof i.name==`string`&&(i.type||i.children||i.instance)?n?`${n} › ${i.name}`:String(i.name):n;for(let[n,r]of Object.entries(t))n!==`uid`&&e(r,n===`children`||n===`root`?s:`${s?`${s}.`:``}${n}`,o)}};e(this.working,``,!1)}return s}removeNodesUnlinking(e){let t=this.findRemovalReferences(e),n=zP(e).filter(e=>e.length>0),r=this.working.root,i=n.map(e=>this.nodeAt(e)).filter(e=>e!==null),a=new Set(t.filter(e=>e.kind===`uid`).map(e=>e.value)),o=new Set(t.filter(e=>e.kind===`connection`).map(e=>e.connectionIndex));return this.transact(()=>{o.size>0&&(this.working.connections=(this.working.connections??[]).filter((e,t)=>!o.has(t))),a.size>0&&IP(this.working,a,i);for(let e of i)VP(r,e);return!0})===!0}reset(e){this.working=e,this.original=JSON.stringify(e),this.working.root&&PP(this.working.root),this.undoStack=[],this.selection=[],this.emit()}markSaved(){this.original=JSON.stringify(this.working),this.emit()}emitChange(){this.emit()}clearFocus(){this.selection=null,this.extra=[],this.selectedAsset=null,this.selectedGroup=null,this.emit()}selectAsset(e){this.selectedAsset=e,e!==null&&(this.cancelAddForms(),this.selectedGroup=null,this.selection=null,this.extra=[]),this.emit()}selectGroup(e){this.selectedGroup=e,e!==null&&(this.cancelAddForms(),this.selectedAsset=null,this.selection=null,this.extra=[]),this.emit()}assetMap(){return this.working.assets??{}}groupCount(e){return Object.keys(this.assetMap()).filter(t=>t.startsWith(`${e}/`)).length}addGroup(e){this.pendingGroups.add(e),this.selectGroup(e)}renameGroup(e,t){if(!t||t===e)return!1;let n=this.assetMap(),r=Object.keys(n).filter(t=>t.startsWith(`${e}/`));return this.pendingGroups.delete(e)&&this.pendingGroups.add(t),this.selectedGroup=t,this.mutate(()=>{for(let i of r){let r=`${t}/${i.slice(e.length+1)}`;n[r]=n[i],delete n[i],LP(this.working,`$${i}`,`$${r}`)}}),r.length===0&&this.emit(),!0}moveGroup(e,t){if(t===e||t.startsWith(`${e}/`))return!1;let n=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,r=t?`${t}/${n}`:n;return r===e?!1:this.renameGroup(e,r)}renameAssetKey(e,t){let n=this.assetMap();return!(e in n)||!t||t===e||t in n?!1:(this.selectedAsset=t,this.mutate(()=>{n[t]=n[e],delete n[e],LP(this.working,`$${e}`,`$${t}`)}),!0)}deleteGroup(e){let t=this.assetMap(),n=Object.keys(t).filter(t=>t.startsWith(`${e}/`));n.length>0&&this.mutate(()=>{for(let e of n)delete t[e];Object.keys(t).length===0&&delete this.working.assets}),this.pendingGroups.delete(e),this.selectedGroup===e&&(this.selectedGroup=null),this.emit()}moveAsset(e,t){let n=this.assetMap();if(!(e in n))return!1;let r=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,i=t?`${t}/${r}`:r;if(i===e)return!1;for(;i in n;)i=`${i}2`;return this.renameAssetKey(e,i)}select(e,t){if(this.cancelAddForms(),this.selectedAsset=null,this.selectedGroup=null,t?.toggle&&e!==null){let t=e.join(`.`);this.selection!==null&&this.selection.join(`.`)===t?this.selection=this.extra.shift()??this.selection:this.extra.some(e=>e.join(`.`)===t)?this.extra=this.extra.filter(e=>e.join(`.`)!==t):this.selection===null?this.selection=e:this.extra.push(e)}else this.selection=e,this.extra=[];this.emit()}allSelections(){return[...this.selection===null?[]:[this.selection,...this.extra]].sort(RP)}isSelected(e){let t=e.join(`.`);return this.selection!==null&&this.selection.join(`.`)===t||this.extra.some(e=>e.join(`.`)===t)}onChange(e){this.listeners.add(e)}emit(){for(let e of this.listeners)e()}};function PP(e){(typeof e.uid!=`string`||e.uid===``)&&(e.uid=Pt());for(let t of e.children??[])PP(t)}function FP(e){e.uid=Pt();for(let t of e.children??[])FP(t)}function IP(e,t,n){if(Array.isArray(e)){for(let r=e.length-1;r>=0;r--)typeof e[r]==`string`&&t.has(e[r])?e.splice(r,1):IP(e[r],t,n);return}if(typeof e==`object`&&e){if(n.includes(e))return;for(let[r,i]of Object.entries(e))r!==`uid`&&(typeof i==`string`&&t.has(i)?delete e[r]:IP(i,t,n))}}function LP(e,t,n){if(Array.isArray(e)){e.forEach((r,i)=>{r===t?e[i]=n:LP(r,t,n)});return}if(typeof e==`object`&&e)for(let[r,i]of Object.entries(e))i===t?e[r]=n:LP(i,t,n)}function RP(e,t){for(let n=0;n<Math.min(e.length,t.length);n++)if(e[n]!==t[n])return e[n]-t[n];return e.length-t.length}function zP(e){let t=[...e].sort(RP),n=[];for(let e of t)n.some(t=>t.length<=e.length&&t.every((t,n)=>t===e[n]))||n.push(e);return n}function BP(e,t){let n=e.children?.indexOf(t)??-1;if(n>=0)return{parent:e,index:n};for(let n of e.children??[]){let e=BP(n,t);if(e)return e}return null}function VP(e,t){let n=BP(e,t);n?.parent.children?.splice(n.index,1)}function HP(e,t){if(e===t)return[];for(let[n,r]of(e.children??[]).entries()){let e=HP(r,t);if(e)return[n,...e]}return null}function UP(e,t){let n=new Set((e.children??[]).map(e=>e.name));if(!n.has(t))return t;let r=2;for(;n.has(`${t}${r}`);)r+=1;return`${t}${r}`}var WP=new Map(Vj.flatMap(e=>e.nodes.map(e=>[e.type,e.summary]))),GP=new Set,KP=null;function qP(e){KP=e}var JP=null,YP=null,XP=null;function ZP(e){return e?e.includes(`Body`)||e.includes(`Area`)||e.includes(`Controller`)?`cat-body`:e===`NetworkSpawner`?`cat-net`:e.endsWith(`3D`)?`cat-3d`:e.endsWith(`2D`)||e===`Label`||e===`UILayer`?`cat-2d`:`cat-core`:`cat-core`}function QP(e,t){e.textContent=``;let n=document.createElement(`div`);n.className=`tree-row scene-row${t.selection===null&&t.selectedAsset===null&&t.selectedGroup===null&&!t.addingAsset&&!t.addingGroup?` selected`:``}`,n.textContent=`⚙ ${String(t.working.name??`scene`)}`,n.addEventListener(`click`,()=>t.select(null)),e.appendChild(n);let r=t.working.root;if(!r){let t=document.createElement(`div`);t.className=`muted-note explorer-empty`,t.textContent=`no root node — pick a type below and + to start the scene`,e.appendChild(t);return}$P(r,t.selection),e.appendChild(eF(r,[],t,``))}function $P(e,t){if(!t)return;let n=e,r=``;for(let e of t){r=r?`${r}/${n.name}`:String(n.name),GP.delete(r);let t=n.children?.[e];if(!t)return;n=t}}function eF(e,t,n,r){let i=r?`${r}/${e.name}`:String(e.name),a=(e.children?.length??0)>0,o=GP.has(i),s=document.createElement(`div`);s.className=`tree-branch`;let c=document.createElement(`div`);c.className=`tree-row${n.isSelected(t)?` selected`:``}`,c.draggable=t.length>0&&XP!==i;let l=document.createElement(`span`);l.className=`chevron${a?``:` leaf`}${o?` collapsed`:``}`,a?l.appendChild(sj()):l.textContent=`·`,a&&l.addEventListener(`click`,e=>{e.stopPropagation(),o?GP.delete(i):GP.add(i),n.select(n.selection)});let u=document.createElement(`span`);if(u.className=`tree-icon ${ZP(e.type)}`,u.appendChild(oj(e.type)),u.title=e.type??`instance`,u.addEventListener(`click`,t=>{t.stopPropagation(),tF(u,e.type??`instance`)}),c.append(l,u),XP===i){let t=document.createElement(`input`);t.className=`rename-input`,t.value=e.name??``;let r=()=>{XP=null;let r=t.value.trim();r&&r!==e.name?n.mutate(()=>{e.name=r}):n.select(n.selection)};t.addEventListener(`keydown`,e=>{e.stopPropagation(),e.key===`Enter`&&r(),e.key===`Escape`&&(XP=null,n.select(n.selection))});for(let e of[`click`,`pointerdown`,`dblclick`,`mousedown`])t.addEventListener(e,e=>e.stopPropagation());t.addEventListener(`blur`,r),c.appendChild(t),queueMicrotask(()=>{t.focus(),t.select()})}else{let r=document.createElement(`span`);r.className=`tree-name`,r.textContent=e.name??`(unnamed)`,r.addEventListener(`dblclick`,e=>{e.stopPropagation(),XP=i,n.select(t)}),c.appendChild(r)}if(c.addEventListener(`click`,e=>{a&&!e.metaKey&&!e.ctrlKey&&(o?GP.delete(i):GP.add(i)),n.select(t,{toggle:e.metaKey||e.ctrlKey})}),c.addEventListener(`contextmenu`,e=>{e.preventDefault(),n.isSelected(t)||n.select(t),nF(e.clientX,e.clientY,n,t,i)}),dF(c,t,n),s.appendChild(c),a&&!o){let r=document.createElement(`div`);r.className=`tree-children`,(e.children??[]).forEach((e,a)=>{r.appendChild(eF(e,[...t,a],n,i))}),s.appendChild(r)}return s}function tF(e,t){sF();let n=document.createElement(`div`);n.className=`balloon floating`;let r=document.createElement(`span`);r.className=`balloon-title`,r.textContent=t,n.appendChild(r);let i=WP.get(t);if(i){let e=document.createElement(`span`);e.textContent=rj(i),n.appendChild(e)}document.body.appendChild(n);let a=e.getBoundingClientRect();n.style.left=`${Math.min(innerWidth-240,a.right+8)}px`,n.style.top=`${Math.max(8,a.top-6)}px`,cF(n)}function nF(e,t,n,r,i){sF();let a=n.allSelections(),o=a.length===1&&r.length>0,s=document.createElement(`div`);s.className=`context-menu floating`;let c=(e,t,n)=>{let r=document.createElement(`button`);r.type=`button`,r.className=`menu-item${n?.danger?` danger`:``}`,r.disabled=t===null;let i=document.createElement(`span`);if(i.textContent=e,r.appendChild(i),n?.kbd){let e=document.createElement(`kbd`);e.textContent=n.kbd,r.appendChild(e)}t&&r.addEventListener(`click`,()=>{sF(),t()}),s.appendChild(r)};c(`duplicate${a.length>1?` ×${a.length}`:``}`,()=>{for(let e of[...a].reverse())n.duplicateNode(e)}),c(`rename`,o?()=>{XP=i,n.select(r)}:null,{kbd:`dbl-click`}),s.appendChild(rF()),c(`cut`,r.length>0?()=>iF(n,!0):null),c(`copy`,r.length>0?()=>iF(n,!1):null),c(`paste as child${YP?` (${YP.nodes.length})`:``}`,YP?()=>aF(n,r):null),s.appendChild(rF()),c(`delete`,r.length>0?()=>(KP??(e=>n.removeNodes(e)))(a):null,{danger:!0}),document.body.appendChild(s),s.style.left=`${Math.min(innerWidth-200-8,e)}px`,s.style.top=`${Math.min(innerHeight-s.offsetHeight-8,t)}px`,cF(s)}function rF(){let e=document.createElement(`div`);return e.className=`menu-divider`,e}function iF(e,t){let n=e.allSelections().filter(e=>e.length>0).map(t=>e.nodeAt(t)).filter(e=>e!==null);YP={nodes:n.map(e=>JSON.parse(JSON.stringify(e))),cut:t?n:null}}function aF(e,t){if(YP){for(let n of YP.nodes)e.insertNode(n,t);if(YP.cut){let t=e.working.root,n=YP.cut.map(e=>oF(t,e)).filter(e=>e!==null);n.length>0&&e.removeNodes(n),YP={nodes:YP.nodes,cut:null}}}}function oF(e,t){if(e===t)return[];for(let[n,r]of(e.children??[]).entries()){let e=oF(r,t);if(e)return[n,...e]}return null}function sF(){for(let e of document.querySelectorAll(`.floating`))e.remove()}function cF(e){let t=r=>{e.contains(r.target)||(e.remove(),document.removeEventListener(`pointerdown`,t,!0),document.removeEventListener(`keydown`,n,!0))},n=r=>{r.key===`Escape`&&(e.remove(),document.removeEventListener(`pointerdown`,t,!0),document.removeEventListener(`keydown`,n,!0))};setTimeout(()=>{document.addEventListener(`pointerdown`,t,!0),document.addEventListener(`keydown`,n,!0)},0)}function lF(e,t){let n=t.getBoundingClientRect(),r=(e.clientY-n.top)/n.height;return r<.25?`before`:r>.75?`after`:`into`}function uF(e){e.classList.remove(`drop-into`,`drop-before`,`drop-after`)}function dF(e,t,n){e.addEventListener(`dragstart`,r=>{JP=n.isSelected(t)?n.allSelections():[t],r.dataTransfer?.setData(`text/plain`,``),r.dataTransfer&&(r.dataTransfer.effectAllowed=`move`),e.classList.add(`dragging`)}),e.addEventListener(`dragend`,()=>{JP=null,e.classList.remove(`dragging`)}),e.addEventListener(`dragover`,n=>{if(!JP||JP.some(e=>e.length<=t.length&&e.every((e,n)=>e===t[n])))return;n.preventDefault(),n.dataTransfer&&(n.dataTransfer.dropEffect=`move`),uF(e);let r=t.length===0?`into`:lF(n,e);e.classList.add(`drop-${r}`)}),e.addEventListener(`dragleave`,()=>uF(e)),e.addEventListener(`drop`,r=>{if(uF(e),!JP)return;r.preventDefault();let i=t.length===0?`into`:lF(r,e),a=n.moveNodes(JP,t,i);JP=null,a?.[0]&&n.select(a[0])})}var fF={x:`#fb7185`,y:`#86efac`,z:`#7aa2ff`};function pF(e,t,n){let r=t-e.origin.x,i=n-e.origin.y;if(Math.abs(r)<=e.centerSize&&Math.abs(i)<=e.centerSize)return{kind:`center`};for(let t of e.axes){let e=t.sx*t.sx+t.sy*t.sy;if(e<1)continue;let n=Math.max(0,Math.min(1,(r*t.sx+i*t.sy)/e)),a=r-t.sx*n,o=i-t.sy*n;if(n>.25&&Math.hypot(a,o)<=8)return{kind:`axis`,axis:t.axis}}return null}function mF(e,t,n){let r=e.sx*e.sx+e.sy*e.sy;return r<1?0:(t*e.sx+n*e.sy)/r*e.worldPerUnit}function hF(e,t,n,r=!1){let{origin:i,axes:a,centerSize:o}=t;for(let t of a){let a=n?.kind===`axis`&&n.axis===t.axis;e.strokeStyle=t.color,e.fillStyle=t.color,e.globalAlpha=a?1:.9,e.lineWidth=a?3:2,e.beginPath(),e.moveTo(i.x,i.y),e.lineTo(i.x+t.sx,i.y+t.sy),e.stroke();let o=Math.hypot(t.sx,t.sy)||1,s=t.sx/o,c=t.sy/o,l=i.x+t.sx,u=i.y+t.sy;e.beginPath(),r?e.rect(l-5,u-5,10,10):(e.moveTo(l+s*9,u+c*9),e.lineTo(l-c*4.5,u+s*4.5),e.lineTo(l+c*4.5,u-s*4.5),e.closePath()),e.fill(),e.font=`700 9px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(t.axis.toUpperCase(),l+s*18,u+c*18)}let s=n?.kind===`center`;e.globalAlpha=s?1:.95,e.fillStyle=s?`#ffffff`:`#e2e6f0`,e.strokeStyle=`#0b0d14`,e.lineWidth=1.5,e.beginPath(),e.rect(i.x-o,i.y-o,o*2,o*2),e.fill(),e.stroke(),e.globalAlpha=1}function gF(e,t,n){return Math.atan2(n-e.y,t-e.x)*180/Math.PI}function _F(e,t){let n=t-e;for(;n>180;)n-=360;for(;n<=-180;)n+=360;return n}function vF(e,t,n,r){let i=null,a=r;for(let r of e)for(let e of r.points){let o=Math.hypot(t-e.x,n-e.y);o<a&&(a=o,i=r.axis)}return i}function yF(e,t,n){for(let r of t){if(r.points.length<2)continue;let t=n===r.axis;e.strokeStyle=fF[r.axis],e.globalAlpha=t?1:.75,e.lineWidth=t?3:2,e.beginPath();let i=r.points[0];e.moveTo(i.x,i.y);for(let t of r.points.slice(1))e.lineTo(t.x,t.y);e.closePath(),e.stroke()}e.globalAlpha=1}function bF(e,t,n,r){e.font=`600 11px ui-monospace, Menlo, monospace`;let i=e.measureText(r).width+14;e.fillStyle=`rgba(16, 19, 29, 0.92)`,e.strokeStyle=`rgba(110, 231, 220, 0.5)`,e.lineWidth=1,e.beginPath(),e.roundRect(t+14,n-26,i,20,5),e.fill(),e.stroke(),e.fillStyle=`#6ee7dc`,e.textAlign=`left`,e.textBaseline=`middle`,e.fillText(r,t+21,n-16)}var xF=class{engine;editCanvas;overlay;playCanvas;cb;renderer2d=null;renderer3d=null;rendererDim=null;orbit={yaw:.6,pitch:.35,dist:10,target:[0,1,0]};pathOf=new Map;reindexNeeded=!1;nodeAtPath=new Map;selectedPath=null;paintHandler=null;extraPaths=[];hoveredNode=null;hoveredGizmo=null;lastGood=null;lastAppliedKey=null;playEngine=null;playRenderer=null;setPaintHandler(e){this.paintHandler=e}get playing(){return this.playEngine!==null}constructor(e,t,n,r){this.editCanvas=e,this.overlay=t,this.playCanvas=n,this.cb=r;let i=this;this.engine=new Ae({scheduler:e=>{let t=0,n=performance.now(),r=requestAnimationFrame(function a(o){t+=.001;let s=Math.min(.1,(o-n)/1e3);n=o;try{e(t),i.tickAmbientPreviews(s)}catch(e){console.error(`incanto-editor viewport:`,e)}r=requestAnimationFrame(a)});return()=>cancelAnimationFrame(r)}}),this.engine.start(),this.engine.updated.connect(()=>this.drawOverlay()),window.addEventListener(`keydown`,e=>{e.key===`Shift`&&(this.shiftHeld=!0)}),window.addEventListener(`keyup`,e=>{e.key===`Shift`&&(this.shiftHeld=!1)}),this.bindPointer()}apply(e){e.root||(e={...e,root:{name:`__empty`,type:(e.dimension??`2d`)===`3d`?`Node3D`:`Node2D`}});let t=JSON.stringify(e);if(t===this.lastAppliedKey&&this.rendererDim===(e.dimension??`2d`))return null;let n;try{let t=structuredClone(e);delete t.connections,IF(t.root),zF(t),n=xt(t)}catch(e){return e instanceof Error?e.message:String(e)}this.lastGood=e,this.lastAppliedKey=t;let r=e.dimension??`2d`;if(this.rendererDim!==r){if(this.renderer2d?.dispose(),this.renderer3d?.dispose(),this.renderer2d=null,this.renderer3d=null,r===`2d`)this.renderer2d=new ug({canvas:this.editCanvas,engine:this.engine}),this.renderer2d.ignoreStatic=!0,this.renderer2d.viewOverride=this.defaultView(e);else{this.renderer3d=new yA({canvas:this.editCanvas,engine:this.engine}),this.renderer3d.ignoreStatic=!0;let t=PF(e.root);if(t){let[e,n,r]=t;this.orbit.dist=Math.max(2,Math.hypot(e,n,r)),this.orbit.yaw=Math.atan2(e,r),this.orbit.pitch=Math.asin(Math.max(-.99,Math.min(.99,n/this.orbit.dist))),this.orbit.target=[0,Math.min(2,Math.abs(n)/2),0]}this.syncOrbit()}this.rendererDim=r}return this.engine.setScene(n),this.indexTree(n.root),this.hoveredNode=null,null}setSelection(e,t=[]){this.selectedPath=e,this.extraPaths=t}validate(e){if(!e.root)return null;try{let t=structuredClone(e);return delete t.connections,IF(t.root),zF(t),xt(t),null}catch(e){return e instanceof Error?e.message:String(e)}}defaultView(e){let t=FF(e.root);if(t)return{cx:t[0],cy:t[1],zoom:1};let n=this.editCanvas.clientWidth||960,r=this.editCanvas.clientHeight||540;return{cx:n/2,cy:r/2,zoom:1}}indexTree(e){this.pathOf=new Map,this.nodeAtPath=new Map;let t=(e,n)=>{this.pathOf.set(e,n),this.nodeAtPath.set(n.join(`.`),e),e.children.forEach((e,r)=>{t(e,[...n,r])})};t(e,[])}liveSelected(){return this.selectedPath===null?null:this.nodeAtPath.get(this.selectedPath.join(`.`))??null}patchProp(e,t,n,r){if(this.playing)return!1;let i=this.nodeAtPath.get(t.join(`.`));if(!i)return!1;try{i[n]=r===void 0?void 0:structuredClone(r)}catch{return!1}return this.reindexNeeded=!0,this.lastAppliedKey=JSON.stringify(e),!0}gizmoActive=null;gizmoMode=`move`;activeRing=null;readout=null;cancelActiveDrag=()=>{};shiftHeld=!1;showColliders=!0;get mode(){return this.gizmoMode}setMode(e){this.gizmoMode=e,this.cb.onModeChanged(e)}gizmoLayout(){let e=this.liveSelected();if(!e)return null;if(this.rendererDim===`2d`&&this.renderer2d){let t=e.position;if(!Array.isArray(t))return null;let n=NF(e),r=this.renderer2d.screenFromWorld(n.x,n.y),i=this.renderer2d.view().zoom;return{origin:r,centerSize:7,axes:[{axis:`x`,sx:64,sy:0,worldPerUnit:64/i,color:fF.x},{axis:`y`,sx:0,sy:64,worldPerUnit:64/i,color:fF.y}]}}if(this.rendererDim===`3d`&&this.renderer3d){let t=e._object3D,n=e.position;if(!t||!Array.isArray(n))return null;t.getWorldPosition(OF);let r=this.renderer3d.screenFromWorld(OF.x,OF.y,OF.z);if(r.behind)return null;let i=[],a=this.orbit.dist,o=Math.max(.2,a*.18);for(let[e,t]of[[`x`,[1,0,0]],[`y`,[0,1,0]],[`z`,[0,0,1]]]){let n=this.renderer3d.screenFromWorld(OF.x+t[0]*o,OF.y+t[1]*o,OF.z+t[2]*o);n.behind||i.push({axis:e,sx:n.x-r.x,sy:n.y-r.y,worldPerUnit:o,color:fF[e]})}return{origin:{x:r.x,y:r.y},centerSize:7,axes:i}}return null}ringLayout(){let e=this.liveSelected();if(!e)return null;if(this.rendererDim===`2d`&&this.renderer2d){let t=NF(e),n=this.renderer2d.screenFromWorld(t.x,t.y),r=[];for(let e=0;e<48;e++){let t=e/48*Math.PI*2;r.push({x:n.x+56*Math.cos(t),y:n.y+56*Math.sin(t)})}return{origin:n,rings:[{axis:`z`,points:r}]}}if(this.rendererDim===`3d`&&this.renderer3d){let t=e._object3D;if(!t)return null;t.getWorldPosition(OF);let n={x:OF.x,y:OF.y,z:OF.z},r=this.renderer3d.screenFromWorld(n.x,n.y,n.z);if(r.behind)return null;let i=Math.max(.2,this.orbit.dist*.16),a=[];for(let e of[`x`,`y`,`z`]){let t=[];for(let r=0;r<48;r++){let a=r/48*Math.PI*2,o=Math.cos(a)*i,s=Math.sin(a)*i,c=e===`x`?this.renderer3d.screenFromWorld(n.x,n.y+o,n.z+s):e===`y`?this.renderer3d.screenFromWorld(n.x+o,n.y,n.z+s):this.renderer3d.screenFromWorld(n.x+o,n.y+s,n.z);c.behind||t.push({x:c.x,y:c.y})}a.push({axis:e,points:t})}return{origin:{x:r.x,y:r.y},rings:a}}return null}orbitVectors(){let{yaw:e,pitch:t,dist:n,target:r}=this.orbit,i=Math.cos(t),a=new H(r[0]+n*i*Math.sin(e),r[1]+n*Math.sin(t),r[2]+n*i*Math.cos(e)),o=new H(r[0],r[1],r[2]).sub(a).normalize(),s=new H().crossVectors(o,wF).normalize();return{pos:a,right:s,up:new H().crossVectors(s,o).normalize(),forward:o}}syncOrbit(){if(!this.renderer3d)return;let{pos:e}=this.orbitVectors();this.renderer3d.viewOverride={position:[e.x,e.y,e.z],target:[...this.orbit.target]}}gameView(){if(this.rendererDim===`3d`&&this.renderer3d){let e=null;for(let[t]of this.pathOf)if(t instanceof hC&&(t.current||!e)&&(e=t,t.current))break;let t=e?e._ensureObject3D():null;if(t){t.getWorldPosition(TF),EF.set(0,0,-1).applyQuaternion(t.getWorldQuaternion(DF));let e=Math.min(40,Math.max(3,this.orbit.dist));this.orbit.target=[TF.x+EF.x*e,TF.y+EF.y*e,TF.z+EF.z*e],this.orbit.dist=e,this.orbit.yaw=Math.atan2(-EF.x,-EF.z),this.orbit.pitch=Math.asin(Math.max(-.99,Math.min(.99,-EF.y)))}this.renderer3d.viewOverride=null;return}this.renderer2d&&(this.renderer2d.viewOverride=null)}snapView(e,t){e===`y`?(this.orbit.pitch=t*1.45,this.orbit.yaw=0):(this.orbit.pitch=0,this.orbit.yaw=e===`z`?t===1?0:Math.PI:Math.PI/2*t),this.syncOrbit()}gizmoCenter(){return{x:this.overlay.clientWidth-58,y:58,r:36}}gizmoHandles(){let{right:e,up:t,forward:n}=this.orbitVectors(),r=this.gizmoCenter(),i=[];for(let[a,o]of[[`x`,new H(1,0,0)],[`y`,new H(0,1,0)],[`z`,new H(0,0,1)]])for(let s of[1,-1]){let c=o.clone().multiplyScalar(s);i.push({axis:a,sign:s,x:r.x+c.dot(e)*26,y:r.y-c.dot(t)*26,z:-c.dot(n)})}return i.sort((e,t)=>e.z-t.z)}gizmoHit(e,t){let n=this.gizmoCenter();if(Math.hypot(e-n.x,t-n.y)>n.r+8)return null;let r=null,i=14;for(let n of this.gizmoHandles()){let a=Math.hypot(e-n.x,t-n.y);a<i&&(i=a,r={axis:n.axis,sign:n.sign})}return r??{axis:`z`,sign:1}}gizmoHandleAt(e,t){let n=this.gizmoCenter();if(Math.hypot(e-n.x,t-n.y)>n.r+8)return null;let r=null,i=12;for(let n of this.gizmoHandles()){let a=Math.hypot(e-n.x,t-n.y);a<i&&(i=a,r={axis:n.axis,sign:n.sign})}return r}tickAmbientPreviews(e){if(!this.playing)for(let[t]of this.pathOf)(t instanceof AE||t instanceof Hh||t instanceof NE||t instanceof Nm||t instanceof GT)&&t.update(e)}modelAnimationsAt(e){let t=this.nodeAtPath.get(e.join(`.`));return t instanceof AE?t.availableAnimations():[]}boneNamesAt(e,t){let n=this.nodeAtPath.get(e.join(`.`));if(!n||t===``)return[];let r=n.getNodeOrNull(t);return r instanceof AE?r.boneNames():[]}drawOverlay(){if(this.reindexNeeded){this.reindexNeeded=!1;let e=this.engine.scene?.tree.root;e&&this.indexTree(e)}let e=this.overlay.getContext(`2d`);if(!e)return;let t=this.overlay.clientWidth,n=this.overlay.clientHeight,r=Math.min(devicePixelRatio||1,2);if((this.overlay.width!==t*r||this.overlay.height!==n*r)&&(this.overlay.width=t*r,this.overlay.height=n*r),e.setTransform(r,0,0,r,0,0),e.clearRect(0,0,t,n),this.playing)return;if(this.rendererDim===`3d`){this.showColliders&&this.drawColliders3D(e),this.drawGizmo(e),this.drawModeGizmo(e),this.readout&&bF(e,this.readout.x,this.readout.y,this.readout.text);return}if(!this.renderer2d)return;if(this.drawAxes2D(e),this.showColliders)for(let[t]of this.pathOf){let n=t.collider;n&&typeof n==`object`&&`shape`in n&&this.drawCollider(e,t,n)}if(this.hoveredNode&&this.hoveredNode!==this.liveSelected()){let t=this.renderer2d.boundsOf(this.hoveredNode);t&&(e.strokeStyle=`rgba(110, 231, 220, 0.45)`,e.lineWidth=1.5,e.setLineDash([]),e.strokeRect(t.x,t.y,t.w,t.h))}for(let t of this.extraPaths){let n=this.nodeAtPath.get(t.join(`.`)),r=n?this.renderer2d.boundsOf(n):null;r&&(e.strokeStyle=`rgba(110, 231, 220, 0.7)`,e.lineWidth=1.5,e.setLineDash([4,3]),e.strokeRect(r.x-2,r.y-2,r.w+4,r.h+4),e.setLineDash([]))}let i=this.liveSelected();if(i){let t=this.renderer2d.boundsOf(i)??this.pointBounds(i);if(t){e.strokeStyle=`#6ee7dc`,e.lineWidth=2,e.setLineDash([6,4]),e.lineDashOffset=-(performance.now()/50%10),e.strokeRect(t.x-2,t.y-2,t.w+4,t.h+4),e.setLineDash([]),e.fillStyle=`#6ee7dc`;for(let[n,r]of[[t.x-2,t.y-2],[t.x+t.w+2,t.y-2],[t.x-2,t.y+t.h+2],[t.x+t.w+2,t.y+t.h+2]])e.fillRect(n-3,r-3,6,6)}}this.drawModeGizmo(e),this.readout&&bF(e,this.readout.x,this.readout.y,this.readout.text)}drawModeGizmo(e){if(this.gizmoMode===`rotate`){let t=this.ringLayout();t&&yF(e,t.rings,this.activeRing);return}let t=this.gizmoLayout();t&&hF(e,t,this.gizmoActive,this.gizmoMode===`scale`)}drawGizmo(e){let t=this.gizmoCenter();e.beginPath(),e.arc(t.x,t.y,t.r,0,Math.PI*2),e.fillStyle=`rgba(16, 19, 29, 0.72)`,e.fill(),e.strokeStyle=`rgba(52, 60, 84, 0.9)`,e.lineWidth=1,e.stroke();let n={x:`#fb7185`,y:`#86efac`,z:`#7aa2ff`},r={x1:`right`,"x-1":`left`,y1:`top`,"y-1":`bottom`,z1:`front`,"z-1":`back`};for(let r of this.gizmoHandles()){let i=this.hoveredGizmo?.axis===r.axis&&this.hoveredGizmo?.sign===r.sign,a=n[r.axis],o=(r.z+1)/2;e.globalAlpha=i?1:.45+o*.55,e.strokeStyle=a,e.lineWidth=1.5,e.beginPath(),e.moveTo(t.x,t.y),e.lineTo(r.x,r.y),e.stroke(),e.beginPath(),e.arc(r.x,r.y,(r.sign===1?7:5)+(i?2:0),0,Math.PI*2),r.sign===1?(e.fillStyle=a,e.fill(),e.fillStyle=`#0b0d14`,e.font=`700 8px ui-monospace, monospace`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(r.axis.toUpperCase(),r.x,r.y+.5)):(e.fillStyle=`rgba(16, 19, 29, 0.9)`,e.fill(),e.stroke())}if(e.globalAlpha=1,this.hoveredGizmo){let n=r[`${this.hoveredGizmo.axis}${this.hoveredGizmo.sign}`];e.fillStyle=`#9aa3bd`,e.font=`600 10px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`bottom`,e.fillText(`${n} view`,t.x,t.y-t.r-6)}}drawColliders3D(e){let t=this.renderer3d;if(!t)return;e.save(),e.strokeStyle=SF,e.lineWidth=1.5;let n=(e,n,r)=>t.screenFromWorld(e,n,r),r=(t,r=!1)=>{e.beginPath();let i=!1;for(let[r,a,o]of t){let t=n(r,a,o);if(t.behind){i=!1;continue}i?e.lineTo(t.x,t.y):e.moveTo(t.x,t.y),i=!0}r&&e.closePath(),e.stroke()},i=(e,t,n,i,a)=>{let o=[];for(let r=0;r<=32;r++){let s=r/32*Math.PI*2,c=Math.cos(s)*i,l=Math.sin(s)*i;a===`xz`?o.push([e+c,t,n+l]):a===`xy`?o.push([e+c,t+l,n]):o.push([e,t+c,n+l])}r(o)};for(let[e]of this.pathOf){let t=e.collider,n=e._object3D;if(!t||typeof t!=`object`||!(`shape`in t)||!n)continue;n.getWorldPosition(OF);let a=t.offset??[0,0,0],o=OF.x+(a[0]??0),s=OF.y+(a[1]??0),c=OF.z+(a[2]??0);if(t.shape===`box`){let e=t.size??[1,1,1],n=(e[0]??1)/2,i=(e[1]??1)/2,a=(e[2]??1)/2;r([[o-n,s-i,c-a],[o+n,s-i,c-a],[o+n,s-i,c+a],[o-n,s-i,c+a]],!0),r([[o-n,s+i,c-a],[o+n,s+i,c-a],[o+n,s+i,c+a],[o-n,s+i,c+a]],!0);for(let[e,t]of[[-1,-1],[1,-1],[1,1],[-1,1]])r([[o+e*n,s-i,c+t*a],[o+e*n,s+i,c+t*a]])}else if(t.shape===`sphere`){let e=t.radius??.5;i(o,s,c,e,`xz`),i(o,s,c,e,`xy`),i(o,s,c,e,`yz`)}else if(t.shape===`capsule`){let e=t.radius??.4,n=(t.height??1)/2;i(o,s+n,c,e,`xz`),i(o,s-n,c,e,`xz`);for(let[t,i]of[[e,0],[-e,0],[0,e],[0,-e]])r([[o+t,s-n,c+i],[o+t,s+n,c+i]])}}e.restore()}drawAxes2D(e){let t=this.gizmoCenter();e.save(),e.shadowColor=`rgba(0, 0, 0, 0.25)`,e.shadowBlur=10,e.shadowOffsetY=2,e.beginPath(),e.arc(t.x,t.y,31,0,Math.PI*2),e.fillStyle=`rgba(13, 16, 24, 0.42)`,e.fill(),e.shadowColor=`transparent`,e.strokeStyle=`rgba(255, 255, 255, 0.16)`,e.lineWidth=1,e.stroke();let n=t.x-9,r=t.y-9;e.lineCap=`round`;let i=(t,i,a,o)=>{let s=n+t*21,c=r+i*21,l=e.createLinearGradient(n,r,s,c);l.addColorStop(0,`${a}55`),l.addColorStop(1,a),e.strokeStyle=l,e.lineWidth=2,e.beginPath(),e.moveTo(n,r),e.lineTo(s,c),e.stroke(),e.beginPath(),e.arc(s,c,6.5,0,Math.PI*2),e.fillStyle=a,e.fill(),e.font=`800 8px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillStyle=`#0b0d14`,e.fillText(o,s,c+.5)};i(1,0,`#fb7185`,`X`),i(0,1,`#86efac`,`Y`),e.beginPath(),e.arc(n,r,2.5,0,Math.PI*2),e.fillStyle=`#e2e6f0`,e.fill(),e.restore()}pointBounds(e){if(!this.renderer2d)return null;let t=e.position;if(!Array.isArray(t))return null;let n=NF(e),r=this.renderer2d.screenFromWorld(n.x,n.y);return{x:r.x-12,y:r.y-12,w:24,h:24}}drawCollider(e,t,n){if(!this.renderer2d)return;let r=NF(t),i=n.offset??[0,0],a=this.renderer2d.screenFromWorld(r.x+(i[0]??0),r.y+(i[1]??0)),o=this.renderer2d.view().zoom;e.strokeStyle=SF,e.lineWidth=1.5,e.setLineDash([]);let s=n.shape;if(s===`rect`){let t=n.size??[32,32],r=(t[0]??32)/2*o,i=(t[1]??32)/2*o;e.strokeRect(a.x-r,a.y-i,r*2,i*2)}else if(s===`circle`){let t=(n.radius??16)*o;e.beginPath(),e.arc(a.x,a.y,t,0,Math.PI*2),e.stroke()}else if(s===`capsule`){let t=(n.radius??16)*o,r=(n.height??32)/2*o;e.beginPath(),e.arc(a.x,a.y-r,t,Math.PI,0),e.arc(a.x,a.y+r,t,0,Math.PI),e.closePath(),e.stroke()}e.setLineDash([])}bindPointer(){let e=this.overlay,t=null,n=null,r=!1,i=null,a=null,o=null,s=null,c=null,l=t=>{let n=this.ringLayout();if(!n)return!1;let r=vF(n.rings,t.offsetX,t.offsetY,9);if(!r)return!1;let i=this.liveSelected();if(!i)return!1;e.setPointerCapture(t.pointerId);let a=i.rotation,o=1;if(this.rendererDim===`3d`&&this.renderer3d){let{forward:e}=this.renderer3d.cameraBasis();o=(r===`x`?e.x:r===`y`?e.y:e.z)>0?1:-1}return c={axis:r,node:i,origin:n.origin,startAngle:gF(n.origin,t.offsetX,t.offsetY),startRotation:Array.isArray(a)?[...a]:a??0,sign:o},this.activeRing=r,!0},u=e=>{if(!c)return;let{axis:t,node:n,origin:r,startAngle:i,startRotation:a,sign:o}=c,s=_F(i,gF(r,e.offsetX,e.offsetY))*o,l=e.shiftKey||this.shiftHeld?15:null,u=e=>{let t=e+s;return l?Math.round(t/l)*l:Math.round(t*10)/10},d;if(Array.isArray(a)){let e={x:0,y:1,z:2}[t],r=[...a];r[e]=u(a[e]??0),d=r[e],n.rotation=r}else{let e=u(a);d=e,n.rotation=e}this.readout={x:e.offsetX,y:e.offsetY,text:`${d}°${l?` ⌁15°`:``}`}},d=e=>{if(!c)return;let{node:t,startRotation:n}=c;if(!e)t.rotation=n;else{let e=this.pathOf.get(t),n=t.rotation;e!==void 0&&n!==void 0&&(Array.isArray(n)?this.cb.onNodeRotated3D(e,[n[0]??0,n[1]??0,n[2]??0]):this.cb.onNodeRotated2D(e,n))}c=null,this.activeRing=null,this.readout=null};this.cancelActiveDrag=()=>{d(!1),s&&(s.node.position=s.startPos,s.node.scale=s.startScale,s=null,this.gizmoActive=null,this.readout=null)};let f=t=>{if(this.gizmoMode===`rotate`)return l(t);let n=this.gizmoLayout();if(!n)return!1;let r=pF(n,t.offsetX,t.offsetY);if(!r)return!1;let i=this.liveSelected();if(!i)return!1;e.setPointerCapture(t.pointerId);let a=[...i.position??[]],o=[...i.scale??[]];return s={hit:r,mode:this.gizmoMode===`scale`||t.button===2?`scale`:`move`,startX:t.offsetX,startY:t.offsetY,layout:n,node:i,startPos:a,startScale:o},this.gizmoActive=r,!0},p=e=>{if(!s)return;let{hit:t,mode:n,layout:r,node:i,startPos:a,startScale:o}=s,c=e.offsetX-s.startX,l=e.offsetY-s.startY,u=this.rendererDim===`3d`,d={x:0,y:1,z:2},f=e.shiftKey||this.shiftHeld,p=f?u?.5:10:null,m=f?.25:null,h=e=>p?Math.round(e/p)*p:e,g=e=>m?Math.max(m,Math.round(e/m)*m):e;if(n===`scale`){let n=Math.max(.05,1+(c-l)*.005),r=[...o];if(t.kind===`axis`)r[d[t.axis]]=CF(g((o[d[t.axis]]??1)*n));else for(let e=0;e<r.length;e++)r[e]=CF(g((o[e]??1)*n));i.scale=r,this.readout={x:e.offsetX,y:e.offsetY,text:`×${r.map(e=>CF(e)).join(`, `)}`};return}let _=[...a];if(t.kind===`axis`){let e=r.axes.find(e=>e.axis===t.axis);if(!e)return;let n=mF(e,c,l);if(u)_[d[t.axis]]=CF(h((a[d[t.axis]]??0)+n));else{let e=MF(i,t.axis===`x`?n:0,t.axis===`y`?n:0),r=t.axis===`x`?e.x:e.y;_[d[t.axis]]=Math.round(h((a[d[t.axis]]??0)+r))}}else if(u&&this.renderer3d){let{right:e,up:t}=this.renderer3d.cameraBasis(),n=this.orbit.dist*.0016;_[0]=CF(h((a[0]??0)+(e.x*c-t.x*l)*n)),_[1]=CF(h((a[1]??0)+(e.y*c-t.y*l)*n)),_[2]=CF(h((a[2]??0)+(e.z*c-t.z*l)*n))}else if(this.renderer2d){let e=this.renderer2d.view(),t=MF(i,c/e.zoom,l/e.zoom);_[0]=Math.round(h((a[0]??0)+t.x)),_[1]=Math.round(h((a[1]??0)+t.y))}i.position=_,this.readout={x:e.offsetX,y:e.offsetY,text:`[${_.map(e=>CF(e)).join(`, `)}]`}},m=()=>{if(!s)return;let{node:e,mode:t}=s,n=this.pathOf.get(e);if(n)if(t===`scale`){let t=e.scale??[];this.rendererDim===`3d`?this.cb.onNodeScaled3D(n,[t[0]??1,t[1]??1,t[2]??1]):this.cb.onNodeScaled(n,[t[0]??1,t[1]??1])}else{let t=e.position??[];this.rendererDim===`3d`?this.cb.onNodeMoved3D(n,[t[0]??0,t[1]??0,t[2]??0]):this.cb.onNodeMoved(n,[t[0]??0,t[1]??0])}s=null,this.gizmoActive=null};e.addEventListener(`pointerdown`,s=>{if(this.playing||f(s))return;if(this.rendererDim===`3d`){let t=this.gizmoHit(s.offsetX,s.offsetY);if(t){this.snapView(t.axis,t.sign);return}e.setPointerCapture(s.pointerId),s.button===1||s.button===2||s.shiftKey?a={x:s.offsetX,y:s.offsetY,target:[...this.orbit.target]}:(i={x:s.offsetX,y:s.offsetY,yaw:this.orbit.yaw,pitch:this.orbit.pitch},o={x:s.offsetX,y:s.offsetY,toggle:s.ctrlKey||s.metaKey});return}if(!this.renderer2d)return;if(e.setPointerCapture(s.pointerId),s.button===1||s.button===2||s.shiftKey){let e=this.renderer2d.view();n={startX:s.offsetX,startY:s.offsetY,cx:e.cx,cy:e.cy};return}if(this.paintHandler&&s.button===0){let e=this.renderer2d.worldFromScreen(s.offsetX,s.offsetY);this.paintHandler(e.x,e.y,!0),r=!0;return}let c=this.renderer2d.pick(s.offsetX,s.offsetY),l=c?this.pathOf.get(c)??null:null;if(this.cb.onPick(l,{toggle:s.ctrlKey||s.metaKey}),this.selectedPath=l,c&&l&&Array.isArray(c.position)){let e=c.position;t={node:c,startWorld:this.renderer2d.worldFromScreen(s.offsetX,s.offsetY),startPos:[e[0]??0,e[1]??0]}}}),e.addEventListener(`pointermove`,o=>{if(!this.playing){if(c){u(o);return}if(s){p(o);return}if(this.rendererDim===`3d`){if(!i&&!a?(this.hoveredGizmo=this.gizmoHandleAt(o.offsetX,o.offsetY),e.style.cursor=this.hoveredGizmo?`pointer`:`grab`):e.style.cursor=`grabbing`,i)this.orbit.yaw=i.yaw-(o.offsetX-i.x)*.006,this.orbit.pitch=Math.max(-1.5,Math.min(1.5,i.pitch+(o.offsetY-i.y)*.006)),this.syncOrbit();else if(a){let{right:e,up:t}=this.orbitVectors(),n=this.orbit.dist*.0016,r=(o.offsetX-a.x)*n,i=(o.offsetY-a.y)*n;this.orbit.target=[a.target[0]-e.x*r+t.x*i,a.target[1]-e.y*r+t.y*i,a.target[2]-e.z*r+t.z*i],this.syncOrbit()}return}if(this.renderer2d){if(e.style.cursor=`crosshair`,r&&this.paintHandler){let e=this.renderer2d.worldFromScreen(o.offsetX,o.offsetY);this.paintHandler(e.x,e.y,!1);return}if(n){let e=this.renderer2d.view();this.renderer2d.viewOverride={cx:n.cx-(o.offsetX-n.startX)/e.zoom,cy:n.cy-(o.offsetY-n.startY)/e.zoom,zoom:e.zoom};return}if(t){let e=this.renderer2d.worldFromScreen(o.offsetX,o.offsetY),n=MF(t.node,e.x-t.startWorld.x,e.y-t.startWorld.y),r=Math.round(t.startPos[0]+n.x),i=Math.round(t.startPos[1]+n.y);t.node.position=[r,i];return}this.hoveredNode=this.renderer2d.pick(o.offsetX,o.offsetY)}}});let h=e=>{if(r=!1,d(!0),m(),this.readout=null,o&&e&&this.renderer3d&&Math.hypot(e.offsetX-o.x,e.offsetY-o.y)<4){let e=this.renderer3d.pick(o.x,o.y),t=e?this.pathOf.get(e)??null:null;t&&(this.cb.onPick(t,{toggle:o.toggle}),this.selectedPath=t)}if(o=null,i=null,a=null,t){let e=this.pathOf.get(t.node),n=t.node.position;e&&(n[0]!==t.startPos[0]||n[1]!==t.startPos[1])&&this.cb.onNodeMoved(e,[n[0]??0,n[1]??0]),t=null}n=null};e.addEventListener(`pointerup`,h),e.addEventListener(`pointercancel`,h),e.addEventListener(`contextmenu`,e=>e.preventDefault()),e.addEventListener(`dblclick`,e=>{if(this.playing)return;let t=this.rendererDim===`3d`?this.renderer3d?.pick(e.offsetX,e.offsetY)??null:this.renderer2d?.pick(e.offsetX,e.offsetY)??null,n=t?this.pathOf.get(t)??null:null;n&&(this.cb.onPick(n,{toggle:e.ctrlKey||e.metaKey}),this.selectedPath=n)}),e.addEventListener(`wheel`,e=>{if(this.playing)return;e.preventDefault();let t=e.deltaY<0?1.1:1/1.1;if(this.rendererDim===`3d`){this.orbit.dist=Math.max(.3,Math.min(800,this.orbit.dist/t)),this.syncOrbit();return}if(!this.renderer2d)return;let n=this.liveSelected();if(e.altKey&&n&&Array.isArray(n.scale)){let e=n.scale,r=[Math.round((e[0]??1)*t*100)/100,Math.round((e[1]??1)*t*100)/100];n.scale=r;let i=this.pathOf.get(n);i&&this.cb.onNodeScaled(i,r);return}let r=this.renderer2d.view(),i=this.renderer2d.worldFromScreen(e.offsetX,e.offsetY),a=Math.min(8,Math.max(.1,r.zoom*t));this.renderer2d.viewOverride={cx:i.x-(e.offsetX-r.w/2)/a,cy:i.y-(e.offsetY-r.h/2)/a,zoom:a}},{passive:!1})}zoomToFit(){if(this.rendererDim===`3d`){let e=new Sa;for(let[t]of this.pathOf){let n=t._object3D;n&&(e.expandByObject(n),e.expandByPoint(n.getWorldPosition(OF)))}if(e.isEmpty())this.orbit.target=[0,1,0],this.orbit.dist=10;else{let t=e.getCenter(new H),n=e.getSize(new H);this.orbit.target=[t.x,t.y,t.z],this.orbit.dist=Math.max(2.5,n.length()*.85)}this.syncOrbit();return}if(!this.renderer2d)return;let e=this.editCanvas.clientWidth||960,t=this.editCanvas.clientHeight||540,n=1/0,r=1/0,i=-1/0,a=-1/0;for(let[e]of this.pathOf){let t=e.position;if(!Array.isArray(t))continue;let o=NF(e);n=Math.min(n,o.x),r=Math.min(r,o.y),i=Math.max(i,o.x),a=Math.max(a,o.y)}if(!Number.isFinite(n))return;let o=(n+i)/2,s=(r+a)/2,c=Math.max(i-n+200,200),l=Math.max(a-r+200,200),u=Math.min(2,Math.min(e/c,t/l));this.renderer2d.viewOverride={cx:o,cy:s,zoom:u}}async play(e){if(this.playing)return null;let t=structuredClone(e);IF(t.root),zF(t);let n;try{n=xt(structuredClone(t),{declareConnectionSignals:!0})}catch{delete t.connections;try{n=xt(structuredClone(t))}catch(e){return e instanceof Error?e.message:String(e)}}let r=new Ae;r.setScene(n),r.input.attachKeyboard(window),this.playCanvas.hidden=!1;let i=e.dimension??`2d`;try{if(i===`2d`){this.playRenderer=new ug({canvas:this.playCanvas,engine:r});let{enablePhysics2D:e}=await _h(async()=>{let{enablePhysics2D:e}=await Promise.resolve().then(()=>_g);return{enablePhysics2D:e}},void 0,import.meta.url),t=await e(r);t.debugDraw=this.showColliders}else{this.playRenderer=new yA({canvas:this.playCanvas,engine:r});let{enablePhysics3D:e}=await _h(async()=>{let{enablePhysics3D:e}=await Promise.resolve().then(()=>kA);return{enablePhysics3D:e}},void 0,import.meta.url),t=await e(r);t.debugDraw=this.showColliders}}catch(e){return this.stop(),e instanceof Error?e.message:String(e)}return r.start(),this.playEngine=r,this.cb.onPlayStateChanged(!0),null}stop(){this.playEngine?.input.dispose(),this.playEngine?.stop(),this.playEngine=null,this.playRenderer?.dispose(),this.playRenderer=null,this.playCanvas.hidden=!0,this.cb.onPlayStateChanged(!1),this.lastAppliedKey=null,this.lastGood&&this.apply(this.lastGood)}},SF=`rgba(0, 255, 110, 0.95)`;function CF(e){return Math.round(e*100)/100}var wF=new H(0,1,0),TF=new H,EF=new H,DF=new V,OF=new H,kF=new W,AF=new H,jF=new H;function MF(e,t,n){let r=e._object2D?.parent;return r?(kF.copy(r.matrixWorld).invert(),AF.set(t,-n,0).applyMatrix4(kF),jF.set(0,0,0).applyMatrix4(kF),{x:AF.x-jF.x,y:-(AF.y-jF.y)}):{x:t,y:n}}function NF(e){let t=e._object2D;if(t)return t.getWorldPosition(OF),{x:OF.x,y:-OF.y};let n=0,r=0,i=e;for(;i;)Array.isArray(i.position)&&(n+=i.position[0]??0,r+=i.position[1]??0),i=i.parent;return{x:n,y:r}}function PF(e){if(!e)return null;if(e.type===`Camera3D`){let t=e.props?.position??[0,2,8];return[t[0]??0,t[1]??2,t[2]??8]}for(let t of e.children??[]){let e=PF(t);if(e)return e}return null}function FF(e){if(!e)return null;if(e.type===`Camera2D`){let t=e.props?.position??[0,0];return[t[0]??0,t[1]??0]}for(let t of e.children??[]){let e=FF(t);if(e)return e}return null}function IF(e){if(typeof e!=`object`||!e)return;let t=e;delete t.script;for(let e of t.children??[])IF(e)}var LF=null;function RF(){if(LF)return LF;let e=document.createElement(`canvas`);e.width=16,e.height=16;let t=e.getContext(`2d`);for(let e=0;e<2;e++)for(let n=0;n<2;n++)t.fillStyle=(n+e)%2==0?`#c252c2`:`#2b2b3b`,t.fillRect(n*8,e*8,8,8);return LF=e.toDataURL(),LF}function zF(e){let t=e.assets;if(t)for(let e of Object.values(t))typeof e?.url==`string`&&!e.url.includes(`/`)&&!e.url.includes(`.`)&&(e.url=RF())}ct(),Qh(),tk(),zA();var $=e=>{let t=document.querySelector(e);if(!t)throw Error(`missing ${e}`);return t};async function BF(){let e=await KA();$(`#engine-version`).textContent=`incanto@${e.version}`,LN($(`#popover`)),Kj(),$(`#docs-btn`).addEventListener(`click`,()=>Wj());let t=$(`#lang-btn`),n=[{code:`en`,label:`English`},{code:`ko`,label:`한국어`}],r=()=>{$(`#lang-current`).textContent=ej()===`ko`?`한국어`:`EN`};r(),t.addEventListener(`click`,()=>{document.querySelector(`.lang-menu`)?.remove();let e=document.createElement(`div`);e.className=`context-menu floating lang-menu`;for(let{code:t,label:r}of n){let n=document.createElement(`button`);n.type=`button`,n.className=`menu-item`;let i=document.createElement(`span`);i.textContent=r;let a=document.createElement(`span`);a.textContent=ej()===t?`✓`:``,a.className=`lang-check`,n.append(i,a),n.addEventListener(`click`,()=>{e.remove(),tj(t)}),e.appendChild(n)}document.body.appendChild(e);let r=t.getBoundingClientRect();e.style.left=`${r.left}px`,e.style.top=`${r.bottom+6}px`;let i=n=>{e.contains(n.target)||n.target===t||(e.remove(),document.removeEventListener(`pointerdown`,i,!0))};setTimeout(()=>document.addEventListener(`pointerdown`,i,!0),0)}),nj(()=>{r(),qj(),i.select(i.selection)});let i=new NP({format:1,type:`scene`,name:``,root:null}),a=$(`#tree`),o=$(`#inspector`),s=$(`#save-btn`),c=$(`#undo-btn`),l=$(`#play-btn`),u=$(`#error-banner`),d=$(`#play-notice`),f=$(`#add-type`),p=$(`#picker`),m=$(`#picker-list`),h=$(`#scenes-btn`),g=e.input,_=e.output,v,y=!1,b=e=>{u.hidden=!1,u.textContent=e,Lj.error(e)},x={on:!1,brush:`0`},S=e=>{let t=0,n=0,r=i.working.root,a=e=>{let r=e?.props?.position;Array.isArray(r)&&(t+=Number(r[0]??0),n+=Number(r[1]??0))};a(r);for(let t of e)r=r?.children?.[t],a(r);return{x:t,y:n}},C=!1,w=(e,t,n=!0)=>{n&&(C=!1);let r=i.selection,a=i.nodeAt(r);if(!r||a?.type!==`TileMap2D`)return;let{cx:o,cy:s}=BN(S(r),Number(a.props?.tileSize??32),e,t),c=a.props?.cells??[],l=VN(c,o,s,x.brush);!l||JSON.stringify(l)===JSON.stringify(c)||(i.mutate(()=>{a.props||={},a.props.cells=l},{path:r,key:`cells`,value:l},{coalesce:C}),C=!0)},T=()=>{let e=i.nodeAt(i.selection);x.on&&e?.type!==`TileMap2D`&&(x.on=!1),E.setPaintHandler(x.on?w:null)},E=new xF($(`#viewport`),$(`#overlay`),$(`#play-canvas`),{onPick:(e,t)=>i.select(e??null,t),onNodeMoved:(e,t)=>re(e,`position`,t,[0,0]),onNodeScaled:(e,t)=>re(e,`scale`,t,[1,1]),onNodeMoved3D:(e,t)=>re(e,`position`,t,[0,0,0]),onNodeScaled3D:(e,t)=>re(e,`scale`,t,[1,1,1]),onNodeRotated2D:(e,t)=>ne(e,`rotation`,t,0),onNodeRotated3D:(e,t)=>re(e,`rotation`,t,[0,0,0]),onModeChanged:e=>{for(let t of[`move`,`rotate`,`scale`])$(`#tool-${t}`).classList.toggle(`active`,t===e)},onPlayStateChanged:e=>{document.body.classList.toggle(`playing`,e),l.classList.toggle(`stop`,e),l.innerHTML=e?`<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12"/></svg> stop`:`<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg> play`,d.hidden=!e,e&&(d.textContent=`▶ simulating — physics + input live; game scripts run only in your real game. Esc or stop to return.`)},onError:b}),D=he().sort(),O=``,k=e=>{if(e===O)return;O=e,f.textContent=``;let t=e===`3d`?[`3D`,`3D Physics`,`Core`,`Network`,`2D`,`2D Physics`]:[`2D`,`2D Physics`,`Core`,`Network`,`3D`,`3D Physics`];for(let[e]of zj)t.includes(e)||t.push(e);for(let e of t){let t=zj.find(([t])=>t===e)?.[1];if(!t)continue;let n=document.createElement(`optgroup`);n.label=e;for(let e of D.filter(t)){let t=document.createElement(`option`);t.value=e,t.textContent=e,n.appendChild(t)}n.children.length>0&&f.appendChild(n)}f.value=e===`3d`?`MeshInstance3D`:`Sprite2D`};k(`2d`);let A=()=>{let e=i.selection??[];for(let t of f.querySelectorAll(`option`)){let n=structuredClone(i.working),r=n.root;if(!n.root)n.root={name:`__probe`,type:t.value};else{for(let t of e)r=r?.children?.[t];if(!r)continue;r.children||=[],r.children.push({name:`__probe`,type:t.value})}t.disabled=E.validate(n)!==null}};f.addEventListener(`mousedown`,A),f.addEventListener(`focus`,A);let ee=!1,te=()=>{if(!y)return;QP(a,i),hj($(`#asset-tree`),i),o.textContent=``,gj(o,i,j)||GN(o,i,{modelRefs:()=>HF(i,`model`),animationsForSelection:()=>i.selection?E.modelAnimationsAt(i.selection):[],bonesForSelection:e=>i.selection?E.boneNamesAt(i.selection,e):[],assetRefs:e=>UF(i,e),addAsset:(e,t)=>WF(i,e,t),confirm:j,paint:{active:()=>x.on,brush:()=>x.brush,toggle:()=>{x.on=!x.on,T(),te()},setBrush:e=>{x.brush=e,te()}}}),k(i.working.dimension??`2d`),$(`#hints`).hidden=(i.working.dimension??`2d`)===`3d`,$(`#hints-3d`).hidden=(i.working.dimension??`2d`)!==`3d`,E.setSelection(i.selection,i.extra),T();let e=i.pendingLivePatch;if(i.pendingLivePatch=null,!E.playing)if(e&&E.patchProp(i.working,e.path,e.key,e.value))u.hidden=!0;else{let e=E.apply(i.working);u.hidden=e===null,e!==null&&b(e)}s.disabled=!i.dirty||!i.working.root,s.title=i.working.root?``:`Add a root node before saving`,c.disabled=!i.canUndo,i.dirty!==ee&&(ee=i.dirty,Lj.change(i.dirty))};i.onChange(te),i.validator=e=>E.validate(e),i.onError=b;let ne=(e,t,n,r)=>{let a=i.nodeAt(e);a&&i.mutate(()=>{a.props||={},n===r?(delete a.props[t],Object.keys(a.props).length===0&&delete a.props):a.props[t]=n},{path:e,key:t,value:n})},re=(e,t,n,r)=>{let a=i.nodeAt(e);a&&i.mutate(()=>{a.props||={},JSON.stringify(n)===JSON.stringify(r)?(delete a.props[t],Object.keys(a.props).length===0&&delete a.props):a.props[t]=n},{path:e,key:t,value:n})},ie=async(t,n,r)=>{E.playing&&E.stop();let a=await XA(t);v=t,g=n,_=r,y=!0,$(`#file-path`).textContent=t??n,$(`#file-chip`).title=`input: ${n}\noutput: ${r}`,p.hidden=!0,i.reset(a),e.mode===`project`&&Lj.open(n,r)},ae=async()=>{let e=await qA();if(m.textContent=``,e.length===0){let e=document.createElement(`div`);e.className=`tree-row`,e.textContent=`no *.scene.json found — create one below`,m.appendChild(e)}for(let t of e){let e=document.createElement(`div`);e.className=`tree-row`,e.textContent=t.rel,e.addEventListener(`click`,()=>{ie(t.rel,t.abs,t.abs).catch(e=>b(e instanceof Error?e.message:String(e)))}),m.appendChild(e)}p.hidden=!1},oe=()=>{p.hidden=!0};if($(`#picker-close`).addEventListener(`click`,oe),p.addEventListener(`pointerdown`,e=>{e.target===p&&oe()}),$(`#picker-create`).addEventListener(`click`,()=>{(async()=>{let e=$(`#picker-path`).value.trim();if(e)try{let t=await JA(e.endsWith(`.scene.json`)?e:`${e}.scene.json`);await ie(t.rel,t.abs,t.abs)}catch(e){b(e instanceof Error?e.message:String(e))}})()}),e.mode===`project`){h.hidden=!1,h.addEventListener(`click`,()=>void ae());let e=await qA(),t=e.length===1?e[0]:void 0;t?await ie(t.rel,t.abs,t.abs):await ae()}else await ie(void 0,e.input,e.output);$(`#add-btn`).addEventListener(`click`,()=>{let e=i.selection??[],t=f.value,n=i.insertNode({name:t,type:t},e);n&&i.select(n)});let se=$(`#generate`);jN(i),$(`#generate-btn`).addEventListener(`click`,()=>kN(i));let ce=$(`#confirm`),le=e=>{if(i.selection===null&&e.length===0){b(`The scene itself cannot be deleted — it IS the file.`);return}if(e.length===0){let e=i.working.root;if(!e)return;let t=VF(e);j(`This deletes the ROOT '${String(e.name??``)}'${t>0?` AND its ${t} descendant node${t===1?``:`s`}`:``} — the scene goes empty, and the next node you add becomes the new root.`,`delete root`,()=>i.deleteRoot());return}let t=e[0]?.slice(0,-1)??[],n=i.findRemovalReferences(e);if(n.length===0){let n=e.reduce((e,t)=>{let n=i.nodeAt(t);return e+(n?VF(n):0)},0);if(n>0){j(`This deletes ${e.length>1?`${e.length} nodes`:`'${String(i.nodeAt(e[0]??[])?.name??``)}'`} AND ${n} descendant node${n===1?``:`s`}.`,`delete ${e.length+n} nodes`,()=>{i.removeNodes(e)&&i.select(t)});return}i.removeNodes(e)&&i.select(t);return}$(`#confirm-text`).textContent=`${n.length} reference${n.length>1?`s`:``} still point at the node(s) you are deleting. Unlink them and delete, or cancel.`;let r=$(`#confirm-list`);r.textContent=``;for(let e of n){let t=document.createElement(`div`);t.textContent=`${e.kind===`uid`?`◆ uid`:`⇄ connection`} ${e.where}`,r.appendChild(t)}$(`#confirm-title`).textContent=`still referenced`,$(`#confirm-delete`).textContent=`unlink & delete`,ce.hidden=!1,ue={selections:e,parentOfFirst:t}},ue=null,de=null;function j(e,t,n){$(`#confirm-title`).textContent=`are you sure?`,$(`#confirm-text`).textContent=e,$(`#confirm-list`).textContent=``,$(`#confirm-delete`).textContent=t,de=n,ce.hidden=!1}function fe(){ce.hidden=!0,ue=null,de=null}$(`#confirm-close`).addEventListener(`click`,fe),$(`#confirm-cancel`).addEventListener(`click`,fe),ce.addEventListener(`pointerdown`,e=>{e.target===ce&&fe()}),$(`#confirm-delete`).addEventListener(`click`,()=>{if(de){de(),fe();return}ue&&i.removeNodesUnlinking(ue.selections)&&i.select(ue.parentOfFirst),fe()}),qP(le),$(`#asset-add-btn`).addEventListener(`click`,e=>{e.stopPropagation(),i.startAddingAsset()}),$(`#group-add-btn`).addEventListener(`click`,e=>{e.stopPropagation(),i.startAddingGroup()});for(let e of document.querySelectorAll(`.section-toggle`)){let t=e.dataset.section??``,n=document.querySelector(`[data-body="${t}"]`),r=`incanto-editor-section-${t}`,i=t=>{e.classList.toggle(`collapsed`,t),n&&(n.hidden=t),localStorage.setItem(r,t?`1`:``)};i(localStorage.getItem(r)===`1`),e.addEventListener(`click`,()=>i(!e.classList.contains(`collapsed`)))}$(`#delete-btn`).addEventListener(`click`,()=>{le(i.allSelections().filter(e=>e.length>0))}),l.addEventListener(`click`,()=>{if(E.playing){E.stop(),te();return}E.play(i.working).then(e=>{e&&b(e)})});for(let e of[`move`,`rotate`,`scale`])$(`#tool-${e}`).addEventListener(`click`,()=>E.setMode(e));E.setMode(`move`);let pe=$(`#tool-colliders`),M=`incanto-editor-show-colliders`,me=e=>{E.showColliders=e,pe.classList.toggle(`active`,e),localStorage.setItem(M,e?``:`0`)};me(localStorage.getItem(M)!==`0`),pe.addEventListener(`click`,()=>me(!E.showColliders));let ge=$(`#hints-dock`),_e=`incanto-editor-hints-open`;ge.classList.toggle(`open`,localStorage.getItem(_e)===`1`),$(`#hints-toggle`).addEventListener(`click`,()=>{let e=ge.classList.toggle(`open`);localStorage.setItem(_e,e?`1`:``)}),$(`#fit-btn`).addEventListener(`click`,()=>E.zoomToFit()),$(`#gameview-btn`).addEventListener(`click`,()=>E.gameView()),s.addEventListener(`click`,()=>{(async()=>{try{await ZA(i.working,v),i.markSaved(),Lj.save(g,_,i.working)}catch(e){b(e instanceof Error?e.message:String(e))}})()}),c.addEventListener(`click`,()=>i.undo()),window.addEventListener(`keydown`,e=>{if(e.key===`Escape`&&E.cancelActiveDrag(),e.key===`Escape`&&!$(`#docs`).hidden){Gj();return}if(e.key===`Escape`&&!ce.hidden){fe();return}if(e.key===`Escape`&&!se.hidden){AN();return}if(e.key===`Escape`&&!p.hidden){oe();return}if(e.key===`Escape`&&E.playing){E.stop(),te();return}if(E.playing)return;let t=e.target.matches(`input, textarea, select`);(e.metaKey||e.ctrlKey)&&e.key===`z`?(e.preventDefault(),i.undo()):(e.metaKey||e.ctrlKey)&&e.key===`s`?(e.preventDefault(),s.disabled||s.click()):!t&&e.code===`KeyF`?E.zoomToFit():!t&&(e.code===`Digit0`||e.code===`Numpad0`)?E.gameView():!t&&e.code===`KeyW`?E.setMode(`move`):!t&&e.code===`KeyE`?E.setMode(`rotate`):!t&&e.code===`KeyR`&&E.setMode(`scale`)}),te(),Lj.ready(g,_,e.version)}function VF(e){let t=0;for(let n of e.children??[])t+=1+VF(n);return t}function HF(e,t){let n=e.working.assets;return n?Object.entries(n).filter(([,e])=>e?.type===t).map(([e])=>`$${e}`):[]}function UF(e,t){let n=e.working.assets;return n?Object.entries(n).filter(([,e])=>!t||e?.type!==void 0&&t.includes(e.type)).map(([e])=>`$${e}`):[]}function WF(e,t,n){let r=e.working.assets??{};for(let[e,t]of Object.entries(r))if(t?.url===n.url)return`$${e}`;let i=t;for(let e=2;i in r;e++)i=`${t}-${e}`;return e.mutate(()=>{e.working.assets||(e.working.assets={}),e.working.assets[i]=n}),`$${i}`}BF().catch(e=>{let t=document.querySelector(`#error-banner`);t&&(t.hidden=!1,t.textContent=e instanceof Error?e.message:String(e))});export{_h as t};
|
|
8330
|
+
`}},network:{title:{en:`network — replicate to other players`,ko:`network — 다른 플레이어에게 복제`},body:{en:`mode "owner" means THIS player owns the node and broadcasts the listed sync keys to everyone in the room (one owner node per player — usually your player character). Other players see it via a NetworkSpawner. Keys are relative to this node: "position", or "Skin.animation" for a child prop.`,ko:`mode "owner"는 이 플레이어가 노드를 소유하고 sync 키 목록을 방의 모두에게 송출한다는 뜻입니다(플레이어당 owner 노드 하나 — 보통 내 캐릭터). 다른 플레이어는 NetworkSpawner로 봅니다. 키는 이 노드 기준 상대 표기입니다: "position", 자식 prop은 "Skin.animation".`},example:`{ "mode": "owner", "sync": ["position"], "throttleMs": 50 }`},collider:{title:{en:`collider — the physics shape`,ko:`collider — 물리 모양`},body:{en:`Shapes: rect (size [w,h]), circle (radius), capsule (radius + height — good for characters). offset shifts the shape from the node position. The green dashed outline in the viewport shows exactly where it is.`,ko:`모양: rect(size [w,h]), circle(radius), capsule(radius+height — 캐릭터에 적합). offset이 노드 위치에서 모양을 이동시킵니다. 뷰포트의 초록 점선이 정확한 위치를 보여줍니다.`},example:`{ "shape": "capsule", "radius": 12, "height": 16 }`},physics:{title:{en:`physics — scene gravity`,ko:`physics — 씬 중력`},body:{en:`World gravity in px/s² (y-down: positive y pulls DOWN). [0, 1400] feels platformer-y; [0, 0] for top-down. Takes effect when the game calls enablePhysics2D — and in the editor’s play mode.`,ko:`월드 중력, px/s² 단위(y-아래: 양수 y가 아래로 당김). [0, 1400]이면 플랫포머 느낌, 탑다운은 [0, 0]. 게임이 enablePhysics2D를 부를 때 — 그리고 에디터 플레이 모드에서 — 적용됩니다.`},example:`"physics": { "gravity": [0, 1400] }`}},uP=null;function dP(e){document.addEventListener(`click`,t=>{let n=t.target,r=n.closest(`[data-help]`);if(!r){e.contains(n)||(e.hidden=!0);return}let i=lP[r.dataset.help??``];if(!i)return;if(!e.hidden&&uP===r){e.hidden=!0;return}uP=r,e.textContent=``;let a=document.createElement(`h4`);a.textContent=jj(i.title);let o=document.createElement(`div`);if(o.textContent=jj(i.body),e.append(a,o),i.example){let t=document.createElement(`pre`);t.textContent=i.example,e.appendChild(t)}if(i.copy){let t=document.createElement(`div`);t.className=`pop-actions`;let n=document.createElement(`button`);n.type=`button`,n.className=`linklike`,n.textContent=`⧉ ${i.copy.label}`,n.addEventListener(`click`,()=>{navigator.clipboard.writeText(i.copy?.text??``),n.textContent=`✓ copied`}),t.appendChild(n),e.appendChild(t)}e.hidden=!1;let s=r.getBoundingClientRect();e.style.left=`${Math.max(8,Math.min(innerWidth-300-8,s.left-300+20))}px`,e.style.top=`${Math.min(innerHeight-60,s.bottom+8)}px`})}function fP(e){let t=document.createElement(`button`);return t.type=`button`,t.className=`help-btn`,t.dataset.help=e,t.textContent=`?`,t.title=`What is this?`,t}var pP=JSON.parse('[{"name":"2dbasic","file":"characters/2dbasic.png","url":"incanto/assets/characters/2dbasic.png","kind":"character","bytes":30499,"description":"2dbasic sprite sheet image.anything,base character. (frame size 192x192)","animation":"characters/2dbasic.json","frameWidth":111,"frameHeight":83},{"name":"attacked","file":"audio/attacked.mp3","url":"incanto/assets/audio/attacked.mp3","kind":"audio","bytes":8757,"description":"Short hurt / took-damage SFX for the player or an enemy."},{"name":"bark_birch_color","file":"vegetation/bark/birch_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_color_1k.jpg","kind":"foliage","bytes":194186,"description":"Birch bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_birch_normal","file":"vegetation/bark/birch_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_normal_1k.jpg","kind":"foliage","bytes":378046,"description":"Birch bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_birch_roughness","file":"vegetation/bark/birch_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/birch_roughness_1k.jpg","kind":"foliage","bytes":127387,"description":"Birch bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_color","file":"vegetation/bark/oak_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_color_1k.jpg","kind":"foliage","bytes":297877,"description":"Oak bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_normal","file":"vegetation/bark/oak_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_normal_1k.jpg","kind":"foliage","bytes":67610,"description":"Oak bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_oak_roughness","file":"vegetation/bark/oak_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/oak_roughness_1k.jpg","kind":"foliage","bytes":16648,"description":"Oak bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_color","file":"vegetation/bark/pine_color_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_color_1k.jpg","kind":"foliage","bytes":196361,"description":"Pine bark base color texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_normal","file":"vegetation/bark/pine_normal_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_normal_1k.jpg","kind":"foliage","bytes":58237,"description":"Pine bark tangent-space normal texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"bark_pine_roughness","file":"vegetation/bark/pine_roughness_1k.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/bark/pine_roughness_1k.jpg","kind":"foliage","bytes":36136,"description":"Pine bark roughness texture (1k), ambientcg Bark (CC0) packaged by ez-tree (MIT). Tree3D trunks/branches sample it by default from the agent8 CDN (the only sanctioned external host); the bundled `incanto/assets` copy (see this entry’s `file`) serves it offline."},{"name":"box","file":"items/box.png","url":"incanto/assets/items/box.png","kind":"item","bytes":10861,"description":"Item box sprite for Dungeons and Dungeoners. Container sprite that holds random items or rewards when opened by player."},{"name":"buff_potion","file":"items/buff_potion.png","url":"incanto/assets/items/buff_potion.png","kind":"item","bytes":3809,"description":"Buff potion item sprite for Dungeons and Dungeoners. Consumable item that grants temporary stat boosts or positive effects to player character."},{"name":"coin","file":"items/coin.png","url":"incanto/assets/items/coin.png","kind":"item","bytes":1689,"description":"Gold coin collectible sprite for Dungeons and Dungeoners. Currency item with metallic sheen, used as in-game money or collectible reward."},{"name":"explosion","file":"audio/explosion.mp3","url":"incanto/assets/audio/explosion.mp3","kind":"audio","bytes":40124,"description":"Impactful explosion / large destructive hit SFX. Pair with the Particles2D \\"explosion\\" preset."},{"name":"floor00","file":"tiles/floor00.jpg","url":"incanto/assets/tiles/floor00.jpg","kind":"tile","bytes":28736,"description":"Basic floor tile texture for Dungeons and Dungeoners project, suitable for dungeon ground surfaces."},{"name":"gem","file":"items/gem.png","url":"incanto/assets/items/gem.png","kind":"item","bytes":8762,"description":"Gem collectible sprite for Dungeons and Dungeoners. Valuable gemstone item used as currency, crafting material, or quest objective."},{"name":"ghost","file":"characters/ghost.png","url":"incanto/assets/characters/ghost.png","kind":"character","bytes":22933,"description":"Ghost character with translucent appearance sprite sheet image (frame size 112x128)","animation":"characters/ghost.json","frameWidth":112,"frameHeight":128},{"name":"goblin","file":"characters/goblin.png","url":"incanto/assets/characters/goblin.png","kind":"character","bytes":57994,"description":"Medieval goblin with torch sprite sheet image (frame size 192x192)","animation":"characters/goblin.json","frameWidth":192,"frameHeight":192},{"name":"gold","file":"items/gold.png","url":"incanto/assets/items/gold.png","kind":"item","bytes":22313,"description":"Gold item sprite for Dungeons and Dungeoners. Gold pile or gold bar sprite representing valuable currency or treasure reward."},{"name":"gold-loot","file":"audio/gold_loot.mp3","url":"incanto/assets/audio/gold_loot.mp3","kind":"audio","bytes":7506,"description":"Metallic coin / gold pickup jingle — collecting currency."},{"name":"ground_dirt","file":"vegetation/ground/dirt_color.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/dirt_color.jpg","kind":"foliage","bytes":231383,"description":"Dense dirt/gravel ground texture (1024px) from the ez-tree demo app (MIT) — the reference meadow ground. Terrain3D grassland themes tile it for slope + noise-patch dirt by default; also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"ground_dirt_normal","file":"vegetation/ground/dirt_normal.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/dirt_normal.jpg","kind":"foliage","bytes":123478,"description":"Dirt ground normal map (1024px) from the ez-tree demo app (MIT). Terrain3D grassland themes apply it across the whole ground band (demo parity); also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"ground_grass","file":"vegetation/ground/grass.jpg","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ground/grass.jpg","kind":"foliage","bytes":322486,"description":"Mossy meadow grass ground texture (1024px) from the ez-tree demo app (MIT). Terrain3D grassland themes (meadow/forest generators) tile it as the grass splat layer by default; also bundled in `incanto/assets` (see `file`) for offline use."},{"name":"heal","file":"audio/heal.mp3","url":"incanto/assets/audio/heal.mp3","kind":"audio","bytes":29764,"description":"Soothing health-restore / heal spell SFX."},{"name":"hit-metal-bang","file":"audio/hit_metal_bang.mp3","url":"incanto/assets/audio/hit_metal_bang.mp3","kind":"audio","bytes":17972,"description":"Metallic impact — hitting armor, metal, or a blocked attack."},{"name":"hp_potion","file":"items/hp_potion.png","url":"incanto/assets/items/hp_potion.png","kind":"item","bytes":3513,"description":"Health potion item sprite for Dungeons and Dungeoners. Consumable healing item that restores player health points when used."},{"name":"ice-spear","file":"audio/ice_spear.mp3","url":"incanto/assets/audio/ice_spear.mp3","kind":"audio","bytes":21315,"description":"Sharp piercing ice projectile fire SFX."},{"name":"leaves_ash","file":"vegetation/ash_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/ash_color.png","kind":"foliage","bytes":181423,"description":"Ash leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for broadleaf/dead ash variants by default; copy it next to your game and set leafTexture to serve offline."},{"name":"leaves_aspen","file":"vegetation/aspen_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/aspen_color.png","kind":"foliage","bytes":142116,"description":"Aspen leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for high-tier broadleaf aspen variants; copy + leafTexture for offline serving."},{"name":"leaves_oak","file":"vegetation/oak_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/oak_color.png","kind":"foliage","bytes":238115,"description":"Oak leaf-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for broadleaf oak variants by default; copy + leafTexture for offline serving."},{"name":"leaves_pine","file":"vegetation/pine_color.png","url":"https://agent8-games.verse8.io/assets/3D/default/textures/vegetation/pine_color.png","kind":"foliage","bytes":303684,"description":"Pine needle-cluster alpha-cutout texture (1024px) from ez-tree by Dan Greenheck (MIT). Tree3D samples it for conifer variants by default; copy + leafTexture for offline serving."},{"name":"locked_item_box","file":"items/locked_item_box.png","url":"incanto/assets/items/locked_item_box.png","kind":"item","bytes":11074,"description":"Locked item box sprite for Dungeons and Dungeoners. Container sprite requiring key or lockpick to open, containing valuable rewards."},{"name":"map","file":"items/map.png","url":"incanto/assets/items/map.png","kind":"item","bytes":3754,"description":"Map item sprite for Dungeons and Dungeoners. Navigation item revealing dungeon layout or providing exploration assistance."},{"name":"medieval-knight","file":"characters/medieval-knight.png","url":"incanto/assets/characters/medieval-knight.png","kind":"character","bytes":84367,"description":"(frame size 192x192) Using a medieval-themed SD(Super Deformed) knight sprite sheet image, you can apply idle, move, and attack animations, among others.","animation":"characters/medieval-knight.json","frameWidth":192,"frameHeight":192},{"name":"minecraft-tiles","file":"tiles/minecraft-tiles.png","url":"incanto/assets/tiles/minecraft-tiles.png","kind":"tile","bytes":10511,"description":"Minecraft-themed tiles sprite sheet image (frame size 16x16)"},{"name":"monster-died","file":"audio/monster_died.mp3","url":"incanto/assets/audio/monster_died.mp3","kind":"audio","bytes":16836,"description":"Enemy defeat / death SFX."},{"name":"resurrection_potion","file":"items/resurrection_potion.png","url":"incanto/assets/items/resurrection_potion.png","kind":"item","bytes":3471,"description":"Resurrection potion item sprite for Dungeons and Dungeoners. Rare consumable that revives fallen party members or prevents death."},{"name":"slash","file":"audio/slash.mp3","url":"incanto/assets/audio/slash.mp3","kind":"audio","bytes":10425,"description":"Quick sword swing / melee slash SFX."},{"name":"smite","file":"audio/smite.mp3","url":"incanto/assets/audio/smite.mp3","kind":"audio","bytes":12956,"description":"Powerful holy downward-strike SFX."},{"name":"spells-cast","file":"audio/spells_cast.mp3","url":"incanto/assets/audio/spells_cast.mp3","kind":"audio","bytes":22151,"description":"Generic magical spell-cast / chant SFX."},{"name":"super_box","file":"items/super_box.png","url":"incanto/assets/items/super_box.png","kind":"item","bytes":12184,"description":"Super item box sprite for Dungeons and Dungeoners. Premium container sprite containing rare or powerful items and equipment."},{"name":"swoosh","file":"effects/swoosh.png","url":"incanto/assets/effects/swoosh.png","kind":"effect","bytes":2599,"description":"Swoosh effect sprite for Dungeons and Dungeoners. Motion blur or attack trail effect used for melee attacks, sword slashes, or fast movement animations."},{"name":"trap","file":"items/trap.png","url":"incanto/assets/items/trap.png","kind":"item","bytes":3969,"description":"Trap object sprite for Dungeons and Dungeoners. Hazard sprite that damages players when triggered in dungeon exploration."},{"name":"ui-click","file":"audio/ui_click.wav","url":"incanto/assets/audio/ui_click.wav","kind":"audio","bytes":17332,"description":"Short tactile UI click for menus and buttons."},{"name":"walk","file":"audio/walk.mp3","url":"incanto/assets/audio/walk.mp3","kind":"audio","bytes":5642,"description":"Single footstep SFX for character movement (loop or one-shot)."},{"name":"wall00","file":"tiles/wall00.jpg","url":"incanto/assets/tiles/wall00.jpg","kind":"tile","bytes":44344,"description":"Basic wall tile texture for Dungeons and Dungeoners project, suitable for dungeon vertical boundaries."}]');function mP(e,t,n,r){return{cx:Math.floor((n-e.x)/t),cy:Math.floor((r-e.y)/t)}}function hP(e,t,n,r){if(t<0||n<0||r.length!==1)return null;let i=e.map(e=>typeof e==`string`?e:e.map(e=>e>=0&&e<=9?String(e):`.`).join(``)),a=Math.max(t+1,...i.map(e=>e.length)),o=Math.max(n+1,i.length),s=[];for(let e=0;e<o;e++){let o=i[e]??``;o=o.padEnd(a,`.`),e===n&&(o=o.slice(0,t)+r+o.slice(t+1)),s.push(o)}return s}function gP(e,t){let n=new Set([`.`,`0`,`1`]);for(let t of e)if(typeof t==`string`)for(let e of t)e!==` `&&n.add(e);for(let e of Object.keys(t))n.add(e);return[...n]}var _P=pP;function vP(e){return(e.kind===`foliage`||e.kind===`tile`)&&!e.animation}function yP(e,t,n){if(e.textContent=``,t.selection===null){xP(e,t,n);return}let r=t.nodeAt(t.selection);r&&DP(e,t,r,n)}var bP=[`input`,`multiplayer`];function xP(e,t,n){e.appendChild(QP(`scene`)),e.appendChild(nF(`name`,String(t.working.name??``),e=>{t.mutate(()=>{t.working.name=e})}));let r=document.createElement(`select`);for(let e of[`2d`,`3d`]){let n=document.createElement(`option`);n.value=e,n.textContent=e,(t.working.dimension??`2d`)===e&&(n.selected=!0),r.appendChild(n)}r.addEventListener(`change`,()=>{t.mutate(()=>{t.working.dimension=r.value})}),e.appendChild(eF(`dimension`,r)),e.appendChild(QP(`physics`,`physics`));let i=(t.working.physics??{}).gravity??(t.working.dimension===`3d`?[0,-9.81,0]:[0,980]),a=t.working.dimension===`3d`?[0,-9.81,0]:[0,980];e.appendChild(iF(`gravity`,i,e=>{t.mutate(()=>{if(JSON.stringify(e)===JSON.stringify(a)){let e={...t.working.physics};delete e.gravity,Object.keys(e).length===0?delete t.working.physics:t.working.physics=e}else t.working.physics={...t.working.physics,gravity:e}})})),e.appendChild(QP(`environment`)),SP(e,t),e.appendChild(QP(`constants`)),KP(e,t,n),e.appendChild(QP(`advanced`));for(let n of bP)e.appendChild(oF(n,t.working[n],e=>{t.mutate(()=>{e===void 0?delete t.working[n]:t.working[n]=e})}))}function SP(e,t){let n=t.working.environment??{},r=e=>{t.mutate(()=>{let n={...t.working.environment??{},...e};for(let e of Object.keys(n))n[e]===void 0&&delete n[e];Object.keys(n).length===0?delete t.working.environment:t.working.environment=n})};e.appendChild(CP(`background`,n.background??``,e=>{r({background:e===``?void 0:e})})),e.appendChild(CP(`ambient color`,n.ambient?.color??``,e=>{let t={...n.ambient,color:e===``?void 0:e};t.color===void 0&&delete t.color,r({ambient:Object.keys(t).length?t:void 0})})),e.appendChild(rF(`ambient power`,n.ambient?.intensity??0,e=>{r({ambient:{...n.ambient,intensity:e}})}));let i=n.rendering??{},a=e=>{let t={...i,...e};for(let e of Object.keys(t))t[e]===void 0&&delete t[e];r({rendering:Object.keys(t).length?t:void 0})},o=document.createElement(`input`);o.type=`checkbox`,o.checked=i.antialias!==!1,o.addEventListener(`change`,()=>{a({antialias:o.checked?void 0:!1})}),e.appendChild(eF(`antialias`,o));let s=document.createElement(`select`);for(let[e,t]of[[``,`1 — soft hiDPI upscale (default)`],[`device`,`device — crisp retina`],[`2`,`2`]]){let n=document.createElement(`option`);n.value=e,n.textContent=t,String(i.pixelRatio??``)===e&&(n.selected=!0),s.appendChild(n)}s.addEventListener(`change`,()=>{a({pixelRatio:s.value===``?void 0:s.value===`device`?`device`:Number(s.value)})}),e.appendChild(eF(`pixel ratio`,s))}function CP(e,t,n){let r=document.createElement(`div`);r.className=`color-row`;let i=document.createElement(`input`);i.type=`color`,i.value=/^#[0-9a-fA-F]{6}$/.test(t)?t:`#000000`;let a=document.createElement(`input`);return a.type=`text`,a.className=`mono`,a.placeholder=`unset`,a.value=t,i.addEventListener(`input`,()=>{a.value=i.value}),i.addEventListener(`change`,()=>n(i.value)),a.addEventListener(`change`,()=>n(a.value.trim())),r.append(i,a),eF(e,r)}function wP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.textContent=`underwater`,n.appendChild(r);let i=t.props?.underwater,a=i!==!1,o=i&&typeof i==`object`&&!Array.isArray(i)?i:{},s=n=>{e.mutate(()=>{t.props||={},n===!0?delete t.props.underwater:t.props.underwater=n,Object.keys(t.props).length===0&&delete t.props})},c=(e,t)=>{let n={...o};t===void 0||t===``?delete n[e]:n[e]=t,s(Object.keys(n).length===0?!0:n)},l=document.createElement(`input`);if(l.type=`checkbox`,l.checked=a,l.addEventListener(`change`,()=>s(l.checked)),n.appendChild(eF(`enabled`,l)),a){n.appendChild(CP(`murk color`,String(o.color??``),e=>c(`color`,e))),n.appendChild(rF(`visibility (m)`,Number(o.visibility??22),e=>c(`visibility`,e===22?void 0:e),()=>c(`visibility`,void 0)));let e=document.createElement(`input`);e.type=`checkbox`,e.checked=(o.caustics??!0)!==!1,e.addEventListener(`change`,()=>c(`caustics`,e.checked?void 0:!1)),n.appendChild(eF(`caustics`,e))}return n}function TP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.textContent=`material`,n.appendChild(r);let i=t.props?.material??{},a=(n,r)=>{let i={...t.props?.material??{}};r===void 0||r===``?delete i[n]:i[n]=r;let a=Object.keys(i).length===0?void 0:i;e.mutate(()=>{t.props||={},a===void 0?(delete t.props.material,Object.keys(t.props).length===0&&delete t.props):t.props.material=a},e.selection?{path:e.selection,key:`material`,value:a}:void 0)};n.appendChild(CP(`color`,String(i.color??``),e=>a(`color`,e))),n.appendChild(EP(`roughness`,Number(i.roughness??1),e=>a(`roughness`,e))),n.appendChild(EP(`metalness`,Number(i.metalness??0),e=>a(`metalness`,e))),n.appendChild(CP(`emissive`,String(i.emissive??``),e=>a(`emissive`,e))),n.appendChild(EP(`emissive power`,Number(i.emissiveIntensity??1),e=>a(`emissiveIntensity`,e===1?void 0:e),2)),n.appendChild(EP(`opacity`,Number(i.opacity??1),e=>a(`opacity`,e===1?void 0:e))),n.appendChild(EP(`clearcoat`,Number(i.clearcoat??0),e=>a(`clearcoat`,e===0?void 0:e))),n.appendChild(EP(`clearcoat rough`,Number(i.clearcoatRoughness??0),e=>a(`clearcoatRoughness`,e===0?void 0:e))),n.appendChild(EP(`reflection`,Number(i.envMapIntensity??1),e=>a(`envMapIntensity`,e===1?void 0:e),3));let o=document.createElement(`input`);o.type=`checkbox`,o.checked=i.wireframe===!0,o.addEventListener(`change`,()=>a(`wireframe`,o.checked||void 0)),n.appendChild(eF(`wireframe`,o));let s=document.createElement(`input`);s.type=`checkbox`,s.checked=i.flatShading===!0,s.addEventListener(`change`,()=>a(`flatShading`,s.checked||void 0)),n.appendChild(eF(`flatShading`,s));let c=document.createElement(`input`);c.type=`checkbox`,c.checked=i.depthTest===!1,c.addEventListener(`change`,()=>{a(`depthTest`,c.checked?!1:void 0),a(`depthWrite`,c.checked?!1:void 0)}),n.appendChild(eF(`draw on top (decal)`,c)),n.appendChild(LP(`map (texture)`,String(i.map??``),RP(e=>vP(e)&&!e.name.includes(`normal`)&&!e.name.includes(`roughness`)),e=>a(`map`,e.trim()),{placeholder:`built-in or custom URL`})),n.appendChild(LP(`normal map`,String(i.normalMap??``),RP(e=>vP(e)&&e.name.includes(`normal`)),e=>a(`normalMap`,e.trim()),{placeholder:`built-in or custom URL`}));let l=!!(i.map||i.normalMap),u=Array.isArray(i.repeat)?i.repeat:[1,1],d=iF(`repeat [u,v]`,[u[0]??1,u[1]??1],e=>{let[t,n]=e;!Number.isFinite(t)||!Number.isFinite(n)||t===1&&n===1||!t&&!n?a(`repeat`,void 0):a(`repeat`,[t,n])});return d.title=l?`Texture tiling across the mesh UVs.`:`Only takes effect with a map/normal map set (engine validates).`,n.appendChild(d),n}function EP(e,t,n,r=1){let i=document.createElement(`div`);i.className=`slider-row`;let a=document.createElement(`input`);a.type=`range`,a.min=`0`,a.max=String(r),a.step=`0.05`,a.value=String(Number.isFinite(t)?t:0);let o=document.createElement(`input`);return o.type=`number`,o.step=`0.05`,o.min=`0`,o.max=String(r),o.value=a.value,a.addEventListener(`input`,()=>{o.value=a.value}),a.addEventListener(`change`,()=>n(Number(a.value))),o.addEventListener(`change`,()=>{a.value=o.value,n(Number(o.value))}),i.append(a,o),eF(e,i)}function DP(e,t,n,r){if(e.appendChild(QP(n.type??`instance`)),e.appendChild(OP(n)),e.appendChild(nF(`name`,n.name??``,e=>{e.trim()!==``&&t.mutate(()=>{n.name=e.trim()})})),n.type===`TileMap2D`&&r?.paint&&e.appendChild(aF(n,r.paint)),n.type){let i;try{i=ge(n.type)}catch{i={}}for(let[a,o]of Object.entries(i))if(a===`collider`)e.appendChild(MP(t,n,o.default));else if(a===`material`)e.appendChild(TP(t,n));else if(n.type===`ModelInstance3D`&&a===`model`&&r)e.appendChild(FP(`model`,String(n.props?.model??``),r.modelRefs(),e=>NP(t,n,`model`,e,``)));else if(n.type===`BoneAttachment3D`&&a===`bone`&&r?.bonesForSelection)e.appendChild(FP(`bone`,String(n.props?.bone??``),r.bonesForSelection(String(n.props?.target??``)),e=>NP(t,n,`bone`,e,``)));else if(n.type===`ModelInstance3D`&&a===`animation`&&r)e.appendChild(FP(`animation`,String(n.props?.animation??``),r.animationsForSelection(),e=>NP(t,n,`animation`,e,``)));else if(n.type===`Tree3D`&&a===`leafTexture`)e.appendChild(LP(`leaf texture`,String(n.props?.leafTexture??``),RP(e=>e.name.startsWith(`leaves_`)),e=>NP(t,n,`leafTexture`,e.trim(),``),{placeholder:`default (per-type) or URL`}));else if(n.type===`Terrain3D`&&a===`textureBase`)e.appendChild(LP(`texture base`,String(n.props?.textureBase??o.default??``),BP,e=>NP(t,n,`textureBase`,e.trim(),o.default),{placeholder:`splat texture base URL`}));else if(n.type===`AnimatedSprite2D`&&a===`sheet`||n.type===`Sprite2D`&&a===`texture`){let i=a===`sheet`;e.appendChild(VP(t,n,a,r,i))}else n.type===`AudioPlayer`&&a===`src`?e.appendChild(LP(`src (audio file)`,String(n.props?.src??``),zP(),e=>NP(t,n,`src`,e.trim(),``),{placeholder:`built-in or custom URL — or use preset`,note:"For zero-asset SFX, set the `preset` prop instead of src."})):n.type===`Flowers3D`&&a===`varieties`?e.appendChild(HP(t,n)):n.type===`Water3D`&&a===`underwater`?e.appendChild(wP(t,n)):e.appendChild(JP(t,n,a,o.default,o.options))}e.appendChild(QP(`structure`)),e.appendChild(kP(t,n)),e.appendChild(AP(t,n)),e.appendChild(jP(t,n))}function OP(e){let t=document.createElement(`div`);t.className=`field uid-line`;let n=document.createElement(`span`);n.textContent=`uid`;let r=document.createElement(`div`);r.className=`uid-value`;let i=document.createElement(`code`);i.textContent=String(e.uid??``);let a=document.createElement(`button`);return a.type=`button`,a.className=`uid-copy`,a.title=`Copy uid`,a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,a.addEventListener(`click`,()=>{navigator.clipboard?.writeText(String(e.uid??``)),a.classList.add(`copied`),a.innerHTML=`✓`,setTimeout(()=>{a.classList.remove(`copied`),a.innerHTML=`<svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`},800)}),r.append(i,a),t.append(n,r),t}function kP(e,t){let n=document.createElement(`label`);n.className=`field wide`;let r=document.createElement(`span`);r.append(`groups `,fP(`groups`));let i=document.createElement(`div`);i.className=`chips`;for(let n of t.groups??[])i.appendChild($P(n,()=>{e.mutate(()=>{t.groups=(t.groups??[]).filter(e=>e!==n),t.groups.length===0&&delete t.groups})}));let a=document.createElement(`input`);return a.placeholder=(t.groups?.length??0)===0?`add a tag… (e.g. coins)`:``,a.addEventListener(`keydown`,n=>{if(n.key!==`Enter`)return;let r=a.value.trim();r&&e.mutate(()=>{t.groups=[...t.groups??[],r]})}),i.appendChild(a),i.addEventListener(`click`,()=>a.focus()),n.append(r,i),n}function AP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.append(`script `,fP(`script`));let i=document.createElement(`span`);i.className=`spacer`,r.appendChild(i);let a=t.script;if(a){let n=document.createElement(`button`);n.type=`button`,n.className=`linklike`,n.textContent=`detach`,n.addEventListener(`click`,()=>{e.mutate(()=>{delete t.script})}),r.appendChild(n)}if(n.appendChild(r),!a){let r=document.createElement(`div`);r.className=`muted-note`,r.textContent=`No behavior attached. Behaviors are TypeScript classes in your game.`;let i=document.createElement(`button`);return i.type=`button`,i.className=`ghost`,i.textContent=`+ attach behavior`,i.addEventListener(`click`,()=>{e.mutate(()=>{t.script={name:`MyBehavior`}})}),n.append(r,i),n}n.appendChild(nF(`name`,a.name??``,n=>{e.mutate(()=>{t.script.name=n.trim()})})),n.appendChild(oF(`props`,a.props,n=>{e.mutate(()=>{n===void 0?delete t.script.props:t.script.props=n})}));let o=document.createElement(`div`);return o.className=`muted-note`,o.textContent=`? has copy-paste boilerplate for the game side.`,n.appendChild(o),n}function jP(e,t){let n=document.createElement(`div`);n.className=`subcard`;let r=document.createElement(`div`);r.className=`subcard-head`,r.append(`network `,fP(`network`)),n.appendChild(r);let i=t.network,a=document.createElement(`select`);for(let[e,t]of[[``,`not replicated`],[`owner`,`owner — this player broadcasts it`]]){let n=document.createElement(`option`);n.value=e,n.textContent=t,(i?.mode??``)===e&&(n.selected=!0),a.appendChild(n)}if(a.addEventListener(`change`,()=>{e.mutate(()=>{a.value===``?delete t.network:t.network={mode:a.value,sync:i?.sync??[`position`]}})}),n.appendChild(eF(`mode`,a)),i?.mode===`owner`){let r=document.createElement(`div`);r.className=`chips`;for(let n of i.sync??[])r.appendChild($P(n,()=>{e.mutate(()=>{t.network.sync=(i.sync??[]).filter(e=>e!==n)})}));let a=document.createElement(`input`);a.placeholder=`position · Skin.animation…`,a.addEventListener(`keydown`,n=>{if(n.key!==`Enter`)return;let r=a.value.trim();r&&e.mutate(()=>{t.network.sync=[...i.sync??[],r]})}),r.appendChild(a);let o=document.createElement(`label`);o.className=`field wide`;let s=document.createElement(`span`);s.textContent=`sync keys`,o.append(s,r),n.appendChild(o),n.appendChild(rF(`throttle ms`,i.throttleMs??50,n=>{e.mutate(()=>{t.network.throttleMs=n})}))}return n}function MP(e,t,n){let r=document.createElement(`div`);r.className=`subcard`;let i=document.createElement(`div`);i.className=`subcard-head`,i.append(`collider `,fP(`collider`)),r.appendChild(i);let a=t.props?.collider??{},o=n=>{e.mutate(()=>{t.props||={};let e=t.props;Object.keys(n).length===0?(delete e.collider,Object.keys(e).length===0&&delete t.props):e.collider=n})},s=(t.type??``).endsWith(`3D`),c=s?[[``,`none`],[`box`,`box — crates, floors`],[`sphere`,`sphere — balls, pickups`],[`capsule`,`capsule — characters`]]:[[``,`none`],[`rect`,`rect — boxes, platforms`],[`circle`,`circle — coins, balls`],[`capsule`,`capsule — characters`]],l=document.createElement(`select`);for(let[e,t]of c){let n=document.createElement(`option`);n.value=e,n.textContent=t,(a.shape??``)===e&&(n.selected=!0),l.appendChild(n)}return l.addEventListener(`change`,()=>{l.value===``?o({}):l.value===`rect`?o({shape:`rect`,size:a.size??[32,32]}):l.value===`box`?o({shape:`box`,size:a.size??[1,1,1]}):l.value===`circle`?o({shape:`circle`,radius:a.radius??16}):l.value===`sphere`?o({shape:`sphere`,radius:a.radius??.5}):o(s?{shape:`capsule`,radius:a.radius??.4,height:a.height??1}:{shape:`capsule`,radius:a.radius??12,height:a.height??16})}),r.appendChild(eF(`shape`,l)),a.shape===`rect`||a.shape===`box`?r.appendChild(iF(`size`,a.size??(s?[1,1,1]:[32,32]),e=>o({...a,size:e}))):a.shape===`circle`||a.shape===`sphere`?r.appendChild(rF(`radius`,a.radius??(s?.5:16),e=>o({...a,radius:e}))):a.shape===`capsule`&&(r.appendChild(rF(`radius`,a.radius??12,e=>o({...a,radius:e}))),r.appendChild(rF(`height`,a.height??16,e=>o({...a,height:e})))),a.shape&&r.appendChild(iF(`offset`,a.offset??(s?[0,0,0]:[0,0]),e=>o({...a,offset:e}))),r}function NP(e,t,n,r,i){e.mutate(()=>{t.props||={},JSON.stringify(r)===JSON.stringify(i)?(delete t.props[n],Object.keys(t.props).length===0&&delete t.props):t.props[n]=r})}var PP=0;function FP(e,t,n,r){let i=document.createElement(`input`);i.type=`text`,i.value=t;let a=`suggest-${PP++}`;i.setAttribute(`list`,a);let o=document.createElement(`datalist`);o.id=a;for(let e of n){let t=document.createElement(`option`);t.value=e,o.appendChild(t)}i.addEventListener(`change`,()=>r(i.value.trim()));let s=eF(e,i);return s.appendChild(o),s}var IP=0;function LP(e,t,n,r,i={}){let a=document.createElement(`label`);a.className=`field wide asset-field`;let o=document.createElement(`span`);o.textContent=e,a.appendChild(o);let s=document.createElement(`input`);s.type=`text`,s.value=t,i.placeholder&&(s.placeholder=i.placeholder),s.addEventListener(`change`,()=>r(s.value.trim()));let c=document.createElement(`button`);c.type=`button`,c.className=`asset-toggle`,c.title=`Browse built-in assets`,c.textContent=`▾`;let l=document.createElement(`div`);l.className=`asset-control`,l.append(s,c),a.appendChild(l);let u=document.createElement(`div`);u.className=`asset-panel`,u.hidden=!0;let d=document.createElement(`input`);d.type=`text`,d.className=`asset-search`,d.placeholder=`search ${n.length} built-in${n.length===1?``:`s`}…`;let f=document.createElement(`div`);f.className=`asset-options`,u.append(d,f),a.appendChild(u);let p=e=>{f.textContent=``;let t=e.trim().toLowerCase(),i=n.filter(e=>t===``||e.label.toLowerCase().includes(t)||(e.hint?.toLowerCase().includes(t)??!1)||e.value.toLowerCase().includes(t));if(i.length===0){let e=document.createElement(`div`);e.className=`asset-empty`,e.textContent=`no match — type a custom URL above`,f.appendChild(e);return}for(let e of i){let t=document.createElement(`button`);t.type=`button`,t.className=`asset-option`;let n=document.createElement(`strong`);if(n.textContent=e.label,t.appendChild(n),e.hint){let n=document.createElement(`small`);n.textContent=e.hint,t.appendChild(n)}t.addEventListener(`click`,()=>{s.value=e.value,u.hidden=!0,r(e.value)}),f.appendChild(t)}};if(c.addEventListener(`click`,()=>{u.hidden=!u.hidden,u.hidden||(p(d.value),d.focus())}),d.addEventListener(`input`,()=>p(d.value)),d.addEventListener(`keydown`,e=>{e.key===`Escape`&&(u.hidden=!0)}),i.note){let e=document.createElement(`div`);e.className=`muted-note asset-note`,e.textContent=i.note,a.appendChild(e)}return s.id=`asset-input-${IP++}`,a.htmlFor=s.id,a}function RP(e){return _P.filter(e).map(e=>({label:e.name,value:e.url,hint:`${e.kind} · ${e.description.slice(0,70)}`}))}function zP(){return _P.filter(e=>e.kind===`audio`).map(e=>({label:e.name,value:e.url,hint:`audio · ${e.description.slice(0,70)}`}))}var BP=[{label:`agent8 default terrain`,value:`https://agent8-games.verse8.io/assets/3D/default/textures/terrain`,hint:`sand/grass/stone/snow splat set (Terrain3D default)`}];function VP(e,t,n,r,i){let a=String(t.props?.[n]??``),o=i?[`spritesheet`]:[`texture`,`spritesheet`],s=(r?.assetRefs?.(o)??[]).map(e=>({label:e,value:e,hint:`scene asset`})),c=_P.filter(e=>i?!!e.animation:e.kind===`character`||e.kind===`item`||e.kind===`tile`);for(let e of c)s.push({label:`built-in: ${e.name}`,value:`$${e.name}`,hint:`${e.kind} · creates a scene asset (${e.animation?`spritesheet`:`texture`})`});return LP(i?`sheet`:`texture`,a,s,i=>{let a=i.startsWith(`$`)&&c.find(e=>`$${e.name}`===i);if(a&&r?.addAsset){let i={type:a.animation?`spritesheet`:`texture`,url:a.url};if(a.animation){let e=a.frameWidth,t=a.frameHeight;e&&(i.frameWidth=e),t&&(i.frameHeight=t)}NP(e,t,n,`$${r.addAsset(a.name,i).replace(/^\$/,``)}`,``);return}NP(e,t,n,i.trim(),``)},{placeholder:`$assetKey`,note:"Picks a $asset ref. Built-ins create the scene asset; packaged sprites need `incanto-assets copy` (or a bundler import) to serve at runtime."})}function HP(e,t){let n=document.createElement(`label`);n.className=`field wide`;let r=document.createElement(`span`);r.textContent=`varieties`,n.appendChild(r);let i=new Set(Array.isArray(t.props?.varieties)?t.props.varieties:[]),a=document.createElement(`div`);a.className=`chips varieties`;let o=()=>{let n=mw.filter(e=>i.has(e));NP(e,t,`varieties`,n.length===0||n.length===mw.length?[]:n,[])};for(let e of mw){let t=document.createElement(`label`);t.className=`variety-opt`;let n=document.createElement(`input`);n.type=`checkbox`,n.checked=i.size===0||i.has(e),n.addEventListener(`change`,()=>{if(i.size===0)for(let e of mw)i.add(e);n.checked?i.add(e):i.delete(e),o()});let r=document.createElement(`span`);r.textContent=e,t.append(n,r),a.appendChild(t)}n.appendChild(a);let s=document.createElement(`div`);return s.className=`muted-note`,s.textContent=`All (or none) = the default mix of all three.`,n.appendChild(s),n}var UP=[[`number`,()=>0],[`text`,()=>``],[`boolean`,()=>!1],[`color`,()=>`#ffffff`],[`vec2`,()=>[0,0]],[`vec3`,()=>[0,0,0]]];function WP(e,t){let n=0,r=e=>{if(dt(e)){e[`@const`]===t&&(n+=1);return}if(Array.isArray(e))for(let t of e)r(t);else if(e&&typeof e==`object`)for(let t of Object.values(e))r(t)};for(let[t,n]of Object.entries(e))t!==`constants`&&r(n);return n}function GP(e,t,n){let r=e=>{if(dt(e))return e[`@const`]===t?JSON.parse(JSON.stringify(n??null)):e;if(Array.isArray(e))return e.map(r);if(e&&typeof e==`object`){let t=e;for(let e of Object.keys(t))t[e]=r(t[e]);return t}return e};for(let t of Object.keys(e))t!==`constants`&&(e[t]=r(e[t]))}function KP(e,t,n){let r=t.working.constants??{},i=Object.keys(r),a=(e,n)=>{t.mutate(()=>{let r={...t.working.constants??{}};r[e]=n,t.working.constants=r})},o=(e,n)=>{t.mutate(()=>{n&&GP(t.working,e,r[e]);let i={...t.working.constants??{}};delete i[e],Object.keys(i).length===0?delete t.working.constants:t.working.constants=i})},s=e=>{let r=WP(t.working,e);if(r>0&&n?.confirm){n.confirm(`"${e}" is used by ${r} prop${r===1?``:`s`}. Unlink them (inline its current value) and delete?`,`unlink & delete`,()=>o(e,!0));return}o(e,r>0)};if(i.length===0){let t=document.createElement(`div`);t.className=`hint`,t.textContent=`No constants yet. Add one, then bind props to it with the 🔗 picker.`,e.appendChild(t)}for(let t of i){let n=document.createElement(`div`);n.className=`const-row`,n.appendChild(qP(t,r[t],e=>a(t,e)));let i=document.createElement(`button`);i.type=`button`,i.className=`const-del`,i.textContent=`✕`,i.title=`delete constant "${t}"`,i.addEventListener(`click`,()=>s(t)),n.appendChild(i),e.appendChild(n)}let c=document.createElement(`div`);c.className=`const-add`;let l=document.createElement(`input`);l.type=`text`,l.placeholder=`new constant name`;let u=document.createElement(`select`);for(let[e]of UP){let t=document.createElement(`option`);t.value=e,t.textContent=e,u.appendChild(t)}let d=document.createElement(`button`);d.type=`button`,d.textContent=`+ add`,d.addEventListener(`click`,()=>{let e=l.value.trim();e&&(t.working.constants??{})[e]===void 0&&(a(e,(UP.find(([e])=>e===u.value)?.[1]??(()=>0))()),l.value=``)}),c.append(l,u,d),e.appendChild(c)}function qP(e,t,n){let r=ue(t);if(r===`number`)return rF(e,t,e=>n(e),()=>n(0));if(r===`boolean`){let r=document.createElement(`input`);return r.type=`checkbox`,r.checked=t===!0,r.addEventListener(`change`,()=>n(r.checked)),eF(e,r)}return r===`array`&&Array.isArray(t)&&t.every(e=>typeof e==`number`)?iF(e,t,e=>n(e)):r===`string`?nF(e,String(t),e=>n(e)):oF(e,t,e=>n(e??null),JSON.stringify(t))}function JP(e,t,n,r,i){let a=t.props?.[n]??r,o=ue(r),s=o===`number`||o===`boolean`||o===`string`||o===`array`,c=i=>{let a=dt(i);e.mutate(()=>{t.props||={};let e=t.props;JSON.stringify(i)===JSON.stringify(r)?(delete e[n],Object.keys(e).length===0&&delete t.props):e[n]=i},e.selection&&s&&!a?{path:e.selection,key:n,value:i}:void 0)},l=YP(e,o,r);if(dt(a))return XP(n,a[`@const`],l,c,r);let u=e=>l.length>0?ZP(e,l,c):e;if(o===`number`)return u(rF(n,a,e=>c(e),()=>c(r)));if(o===`boolean`){let e=document.createElement(`input`);return e.type=`checkbox`,e.checked=a===!0,e.addEventListener(`change`,()=>c(e.checked)),u(eF(n,e))}return o===`string`?i&&i.length>0?u(tF(n,String(a??``),i,e=>c(e))):u(nF(n,String(a??``),e=>c(e))):o===`array`&&Array.isArray(r)&&r.length>0&&r.every(e=>typeof e==`number`)?u(iF(n,a??r,e=>c(e))):oF(n,a===r?void 0:a,e=>{c(e===void 0?r:e)},JSON.stringify(r))}function YP(e,t,n){let r=e.working.constants??{};return Object.keys(r).filter(e=>{let i=r[e];return ue(i)===t?t===`array`&&Array.isArray(n)&&Array.isArray(i)?i.length===n.length:!0:!1})}function XP(e,t,n,r,i){let a=document.createElement(`select`),o=n.includes(t)?n:[t,...n];for(let e of o){let n=document.createElement(`option`);n.value=e,n.textContent=e,e===t&&(n.selected=!0),a.appendChild(n)}let s=document.createElement(`option`);s.value=``,s.textContent=`↺ custom value`,a.appendChild(s),a.addEventListener(`change`,()=>{r(a.value?{"@const":a.value}:i)});let c=eF(`🔗 ${e}`,a);return c.classList.add(`const-bound`),c}function ZP(e,t,n){let r=document.createElement(`select`);r.className=`const-picker`,r.title=`Bind to a named constant`;let i=document.createElement(`option`);i.value=``,i.textContent=`🔗`,r.appendChild(i);for(let e of t){let t=document.createElement(`option`);t.value=e,t.textContent=e,r.appendChild(t)}return r.value=``,r.addEventListener(`change`,()=>{r.value&&n({"@const":r.value})}),e.appendChild(r),e}function QP(e,t){let n=document.createElement(`div`);n.className=`section-title`,n.textContent=e,t&&n.appendChild(fP(t));let r=document.createElement(`span`);return r.className=`rule`,n.appendChild(r),n}function $P(e,t){let n=document.createElement(`span`);n.className=`chip`,n.textContent=e;let r=document.createElement(`button`);return r.type=`button`,r.textContent=`✕`,r.addEventListener(`click`,e=>{e.stopPropagation(),t()}),n.appendChild(r),n}function eF(e,t){let n=document.createElement(`label`);n.className=`field`;let r=document.createElement(`span`);return r.textContent=e,n.append(r,t),n}function tF(e,t,n,r){let i=document.createElement(`select`);for(let e of n.includes(t)?n:[t,...n]){let n=document.createElement(`option`);n.value=e,n.textContent=e,e===t&&(n.selected=!0),i.appendChild(n)}return i.addEventListener(`change`,()=>r(i.value)),eF(e,i)}function nF(e,t,n){let r=document.createElement(`input`);return r.type=`text`,r.value=t,r.addEventListener(`change`,()=>n(r.value)),eF(e,r)}function rF(e,t,n,r){let i=document.createElement(`input`);return i.type=`number`,i.step=`any`,i.value=String(t),i.addEventListener(`change`,()=>{if(i.value.trim()===``){r?.();return}let e=Number(i.value);Number.isFinite(e)&&n(e)}),eF(e,i)}function iF(e,t,n){let r=document.createElement(`div`);r.className=`vector-row`;let i=[...t];return i.forEach((e,t)=>{let a=document.createElement(`input`);a.type=`number`,a.step=`any`,a.value=String(e??0),a.addEventListener(`change`,()=>{let e=Number(a.value);Number.isFinite(e)&&(i[t]=e,n([...i]))}),r.appendChild(a)}),eF(e,r)}function aF(e,t){let n=document.createElement(`div`);n.className=`field wide tile-paint`;let r=document.createElement(`button`);r.type=`button`,r.className=t.active()?`paint-toggle on`:`paint-toggle`,r.textContent=t.active()?`🖌 painting — click the canvas`:`🖌 paint tiles`,r.addEventListener(`click`,()=>t.toggle()),n.appendChild(r);let i=document.createElement(`div`);i.className=`paint-palette`;let a=e.props?.cells??[],o=e.props?.legend??{};for(let e of gP(a,o)){let n=document.createElement(`button`);n.type=`button`,n.className=t.brush()===e?`paint-chip on`:`paint-chip`,n.textContent=e===`.`?`␡`:e,n.title=e===`.`?`eraser (empty cell)`:`tile '${e}'`,n.addEventListener(`click`,()=>t.setBrush(e)),i.appendChild(n)}let s=document.createElement(`input`);s.type=`text`,s.maxLength=1,s.className=`paint-brush-input`,s.value=t.brush(),s.title=`brush char (digit or a legend char)`,s.addEventListener(`change`,()=>{s.value.length===1&&t.setBrush(s.value)}),i.appendChild(s),n.appendChild(i);let c=document.createElement(`div`);return c.className=`paint-hint`,c.textContent=`grid grows right/down; digits map to atlas tiles, others need legend`,n.appendChild(c),n}function oF(e,t,n,r=``){let i=document.createElement(`textarea`);i.rows=3,i.placeholder=r,i.value=t===void 0?``:JSON.stringify(t,null,2),i.addEventListener(`change`,()=>{let e=i.value.trim();if(e===``){i.classList.remove(`invalid`),n(void 0);return}try{let t=JSON.parse(e);i.classList.remove(`invalid`),n(t)}catch{i.classList.add(`invalid`)}});let a=eF(e,i);return a.className=`field wide`,a}var sF=class{working;selection=[];extra=[];validator=null;selectedAsset=null;selectedGroup=null;pendingGroups=new Set;pendingLivePatch=null;addingAsset=!1;addingGroup=!1;newAssetGroup=``;newGroupParent=``;startAddingAsset(){this.addingAsset=!0,this.addingGroup=!1,this.newAssetGroup=this.selectedGroup??``,this.clearFocus()}startAddingGroup(){this.addingGroup=!0,this.addingAsset=!1,this.newGroupParent=this.selectedGroup??``,this.clearFocus()}cancelAddForms(){this.addingAsset=!1,this.addingGroup=!1}onError=null;original;undoStack=[];listeners=new Set;constructor(e){this.working=e,this.original=JSON.stringify(e),this.working.root&&cF(this.working.root)}get dirty(){return JSON.stringify(this.working)!==this.original}get canUndo(){return this.undoStack.length>0}nodeAt(e){if(e===null)return null;let t=this.working.root;for(let n of e)t=t?.children?.[n];return t??null}parentOf(e){return e.length===0?null:this.nodeAt(e.slice(0,-1))}mutate(e,t,n){(!n?.coalesce||this.undoStack.length===0)&&(this.undoStack.push(JSON.stringify(this.working)),this.undoStack.length>100&&this.undoStack.shift()),e(),this.pendingLivePatch=t??null,this.emit()}undo(){let e=this.undoStack.pop();e!==void 0&&(this.working=JSON.parse(e),this.selection=[],this.emit())}transact(e){let t=JSON.stringify(this.working),n=e(),r=e=>(this.working=JSON.parse(t),e&&this.onError?.(e),null);if(n===null)return r();let i=this.validator?.(this.working)??null;return i?r(i):(this.undoStack.push(t),this.undoStack.length>100&&this.undoStack.shift(),this.emit(),n)}moveNode(e,t,n){return this.moveNodes([e],t,n)?.[0]??null}moveNodes(e,t,n){let r=pF(e).filter(e=>e.length>0);if(r.length===0)return null;for(let e of r)if(e.length<=t.length&&e.every((e,n)=>e===t[n]))return null;let i=this.working.root,a=r.map(e=>this.nodeAt(e)).filter(e=>e!==null);if(a.length!==r.length)return null;let o=this.nodeAt(t);return!o||a.includes(o)?null:this.transact(()=>{for(let e of a)hF(i,e);let e,t;if(n===`into`)e=o,e.children||=[],t=e.children.length;else{let r=mF(i,o);if(!r)return null;e=r.parent,t=r.index+ +(n===`after`)}let r=[];a.forEach((n,r)=>{n.name=_F(e,n.name??`Node`),e.children?.splice(t+r,0,n)});for(let e of a){let t=gF(i,e);if(!t)return null;r.push(t)}return r})}duplicateNode(e){if(e.length===0)return null;let t=this.nodeAt(e),n=this.parentOf(e);return!t||!n?.children?null:this.transact(()=>{let r=JSON.parse(JSON.stringify(t));r.name=_F(n,t.name??`Node`),lF(r);let i=e[e.length-1]+1;return n.children?.splice(i,0,r),[...e.slice(0,-1),i]})}removeNodes(e){let t=pF(e).filter(e=>e.length>0);if(t.length===0)return!1;let n=this.working.root,r=t.map(e=>this.nodeAt(e)).filter(e=>e!==null);return this.transact(()=>{for(let e of r)hF(n,e);return!0})===!0}deleteRoot(){this.undoStack.push(JSON.stringify(this.working)),delete this.working.root,this.selection=null,this.extra=[],this.emit()}insertNode(e,t){if(!this.working.root){let t=JSON.parse(JSON.stringify(e));return lF(t),this.transact(()=>(this.working.root=t,[]))}let n=this.nodeAt(t);return n?this.transact(()=>{let r=JSON.parse(JSON.stringify(e));return r.name=_F(n,r.name??`Node`),lF(r),n.children||=[],n.children.push(r),[...t,n.children.length-1]}):null}findRemovalReferences(e){let t=pF(e).filter(e=>e.length>0),n=this.working.root,r=t.map(e=>this.nodeAt(e)).filter(e=>e!==null),i=new Set,a=[];for(let e of t){let t=[],r=n;for(let n of e){let e=r.children?.[n];if(!e)break;t.push(String(e.name)),r=e}a.push(t.join(`/`))}let o=e=>{typeof e.uid==`string`&&i.add(e.uid);for(let t of e.children??[])o(t)};for(let e of r)o(e);let s=[];if((this.working.connections??[]).forEach((e,t)=>{for(let n of[`from`,`to`]){let r=String(e[n]??``);if(a.some(e=>r===e||r.startsWith(`${e}/`))){s.push({kind:`connection`,where:`connections[${t}] ${String(e.signal)}: ${String(e.from)} → ${String(e.to)}`,connectionIndex:t});return}}}),i.size>0){let e=(t,n,a)=>{if(typeof t==`string`){!a&&i.has(t)&&s.push({kind:`uid`,where:n,value:t});return}if(Array.isArray(t)){t.forEach((t,r)=>{e(t,`${n}[${r}]`,a)});return}if(typeof t==`object`&&t){let i=t,o=a||r.includes(i),s=typeof i.name==`string`&&(i.type||i.children||i.instance)?n?`${n} › ${i.name}`:String(i.name):n;for(let[n,r]of Object.entries(t))n!==`uid`&&e(r,n===`children`||n===`root`?s:`${s?`${s}.`:``}${n}`,o)}};e(this.working,``,!1)}return s}removeNodesUnlinking(e){let t=this.findRemovalReferences(e),n=pF(e).filter(e=>e.length>0),r=this.working.root,i=n.map(e=>this.nodeAt(e)).filter(e=>e!==null),a=new Set(t.filter(e=>e.kind===`uid`).map(e=>e.value)),o=new Set(t.filter(e=>e.kind===`connection`).map(e=>e.connectionIndex));return this.transact(()=>{o.size>0&&(this.working.connections=(this.working.connections??[]).filter((e,t)=>!o.has(t))),a.size>0&&uF(this.working,a,i);for(let e of i)hF(r,e);return!0})===!0}reset(e){this.working=e,this.original=JSON.stringify(e),this.working.root&&cF(this.working.root),this.undoStack=[],this.selection=[],this.emit()}markSaved(){this.original=JSON.stringify(this.working),this.emit()}emitChange(){this.emit()}clearFocus(){this.selection=null,this.extra=[],this.selectedAsset=null,this.selectedGroup=null,this.emit()}selectAsset(e){this.selectedAsset=e,e!==null&&(this.cancelAddForms(),this.selectedGroup=null,this.selection=null,this.extra=[]),this.emit()}selectGroup(e){this.selectedGroup=e,e!==null&&(this.cancelAddForms(),this.selectedAsset=null,this.selection=null,this.extra=[]),this.emit()}assetMap(){return this.working.assets??{}}groupCount(e){return Object.keys(this.assetMap()).filter(t=>t.startsWith(`${e}/`)).length}addGroup(e){this.pendingGroups.add(e),this.selectGroup(e)}renameGroup(e,t){if(!t||t===e)return!1;let n=this.assetMap(),r=Object.keys(n).filter(t=>t.startsWith(`${e}/`));return this.pendingGroups.delete(e)&&this.pendingGroups.add(t),this.selectedGroup=t,this.mutate(()=>{for(let i of r){let r=`${t}/${i.slice(e.length+1)}`;n[r]=n[i],delete n[i],dF(this.working,`$${i}`,`$${r}`)}}),r.length===0&&this.emit(),!0}moveGroup(e,t){if(t===e||t.startsWith(`${e}/`))return!1;let n=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,r=t?`${t}/${n}`:n;return r===e?!1:this.renameGroup(e,r)}renameAssetKey(e,t){let n=this.assetMap();return!(e in n)||!t||t===e||t in n?!1:(this.selectedAsset=t,this.mutate(()=>{n[t]=n[e],delete n[e],dF(this.working,`$${e}`,`$${t}`)}),!0)}deleteGroup(e){let t=this.assetMap(),n=Object.keys(t).filter(t=>t.startsWith(`${e}/`));n.length>0&&this.mutate(()=>{for(let e of n)delete t[e];Object.keys(t).length===0&&delete this.working.assets}),this.pendingGroups.delete(e),this.selectedGroup===e&&(this.selectedGroup=null),this.emit()}moveAsset(e,t){let n=this.assetMap();if(!(e in n))return!1;let r=e.includes(`/`)?e.slice(e.lastIndexOf(`/`)+1):e,i=t?`${t}/${r}`:r;if(i===e)return!1;for(;i in n;)i=`${i}2`;return this.renameAssetKey(e,i)}select(e,t){if(this.cancelAddForms(),this.selectedAsset=null,this.selectedGroup=null,t?.toggle&&e!==null){let t=e.join(`.`);this.selection!==null&&this.selection.join(`.`)===t?this.selection=this.extra.shift()??this.selection:this.extra.some(e=>e.join(`.`)===t)?this.extra=this.extra.filter(e=>e.join(`.`)!==t):this.selection===null?this.selection=e:this.extra.push(e)}else this.selection=e,this.extra=[];this.emit()}allSelections(){return[...this.selection===null?[]:[this.selection,...this.extra]].sort(fF)}isSelected(e){let t=e.join(`.`);return this.selection!==null&&this.selection.join(`.`)===t||this.extra.some(e=>e.join(`.`)===t)}onChange(e){this.listeners.add(e)}emit(){for(let e of this.listeners)e()}};function cF(e){(typeof e.uid!=`string`||e.uid===``)&&(e.uid=Pt());for(let t of e.children??[])cF(t)}function lF(e){e.uid=Pt();for(let t of e.children??[])lF(t)}function uF(e,t,n){if(Array.isArray(e)){for(let r=e.length-1;r>=0;r--)typeof e[r]==`string`&&t.has(e[r])?e.splice(r,1):uF(e[r],t,n);return}if(typeof e==`object`&&e){if(n.includes(e))return;for(let[r,i]of Object.entries(e))r!==`uid`&&(typeof i==`string`&&t.has(i)?delete e[r]:uF(i,t,n))}}function dF(e,t,n){if(Array.isArray(e)){e.forEach((r,i)=>{r===t?e[i]=n:dF(r,t,n)});return}if(typeof e==`object`&&e)for(let[r,i]of Object.entries(e))i===t?e[r]=n:dF(i,t,n)}function fF(e,t){for(let n=0;n<Math.min(e.length,t.length);n++)if(e[n]!==t[n])return e[n]-t[n];return e.length-t.length}function pF(e){let t=[...e].sort(fF),n=[];for(let e of t)n.some(t=>t.length<=e.length&&t.every((t,n)=>t===e[n]))||n.push(e);return n}function mF(e,t){let n=e.children?.indexOf(t)??-1;if(n>=0)return{parent:e,index:n};for(let n of e.children??[]){let e=mF(n,t);if(e)return e}return null}function hF(e,t){let n=mF(e,t);n?.parent.children?.splice(n.index,1)}function gF(e,t){if(e===t)return[];for(let[n,r]of(e.children??[]).entries()){let e=gF(r,t);if(e)return[n,...e]}return null}function _F(e,t){let n=new Set((e.children??[]).map(e=>e.name));if(!n.has(t))return t;let r=2;for(;n.has(`${t}${r}`);)r+=1;return`${t}${r}`}var vF=new Map(hM.flatMap(e=>e.nodes.map(e=>[e.type,e.summary]))),yF=new Set,bF=null;function xF(e){bF=e}var SF=null,CF=null,wF=null;function TF(e){return e?e.includes(`Body`)||e.includes(`Area`)||e.includes(`Controller`)?`cat-body`:e===`NetworkSpawner`?`cat-net`:e.endsWith(`3D`)?`cat-3d`:e.endsWith(`2D`)||e===`Label`||e===`UILayer`?`cat-2d`:`cat-core`:`cat-core`}function EF(e,t){e.textContent=``;let n=document.createElement(`div`);n.className=`tree-row scene-row${t.selection===null&&t.selectedAsset===null&&t.selectedGroup===null&&!t.addingAsset&&!t.addingGroup?` selected`:``}`,n.textContent=`⚙ ${String(t.working.name??`scene`)}`,n.addEventListener(`click`,()=>t.select(null)),e.appendChild(n);let r=t.working.root;if(!r){let t=document.createElement(`div`);t.className=`muted-note explorer-empty`,t.textContent=`no root node — pick a type below and + to start the scene`,e.appendChild(t);return}DF(r,t.selection),e.appendChild(OF(r,[],t,``))}function DF(e,t){if(!t)return;let n=e,r=``;for(let e of t){r=r?`${r}/${n.name}`:String(n.name),yF.delete(r);let t=n.children?.[e];if(!t)return;n=t}}function OF(e,t,n,r){let i=r?`${r}/${e.name}`:String(e.name),a=(e.children?.length??0)>0,o=yF.has(i),s=document.createElement(`div`);s.className=`tree-branch`;let c=document.createElement(`div`);c.className=`tree-row${n.isSelected(t)?` selected`:``}`,c.draggable=t.length>0&&wF!==i;let l=document.createElement(`span`);l.className=`chevron${a?``:` leaf`}${o?` collapsed`:``}`,a?l.appendChild(Fj()):l.textContent=`·`,a&&l.addEventListener(`click`,e=>{e.stopPropagation(),o?yF.delete(i):yF.add(i),n.select(n.selection)});let u=document.createElement(`span`);if(u.className=`tree-icon ${TF(e.type)}`,u.appendChild(Pj(e.type)),u.title=e.type??`instance`,u.addEventListener(`click`,t=>{t.stopPropagation(),kF(u,e.type??`instance`)}),c.append(l,u),wF===i){let t=document.createElement(`input`);t.className=`rename-input`,t.value=e.name??``;let r=()=>{wF=null;let r=t.value.trim();r&&r!==e.name?n.mutate(()=>{e.name=r}):n.select(n.selection)};t.addEventListener(`keydown`,e=>{e.stopPropagation(),e.key===`Enter`&&r(),e.key===`Escape`&&(wF=null,n.select(n.selection))});for(let e of[`click`,`pointerdown`,`dblclick`,`mousedown`])t.addEventListener(e,e=>e.stopPropagation());t.addEventListener(`blur`,r),c.appendChild(t),queueMicrotask(()=>{t.focus(),t.select()})}else{let r=document.createElement(`span`);r.className=`tree-name`,r.textContent=e.name??`(unnamed)`,r.addEventListener(`dblclick`,e=>{e.stopPropagation(),wF=i,n.select(t)}),c.appendChild(r)}if(c.addEventListener(`click`,e=>{a&&!e.metaKey&&!e.ctrlKey&&(o?yF.delete(i):yF.add(i)),n.select(t,{toggle:e.metaKey||e.ctrlKey})}),c.addEventListener(`contextmenu`,e=>{e.preventDefault(),n.isSelected(t)||n.select(t),AF(e.clientX,e.clientY,n,t,i)}),zF(c,t,n),s.appendChild(c),a&&!o){let r=document.createElement(`div`);r.className=`tree-children`,(e.children??[]).forEach((e,a)=>{r.appendChild(OF(e,[...t,a],n,i))}),s.appendChild(r)}return s}function kF(e,t){FF();let n=document.createElement(`div`);n.className=`balloon floating`;let r=document.createElement(`span`);r.className=`balloon-title`,r.textContent=t,n.appendChild(r);let i=vF.get(t);if(i){let e=document.createElement(`span`);e.textContent=jj(i),n.appendChild(e)}document.body.appendChild(n);let a=e.getBoundingClientRect();n.style.left=`${Math.min(innerWidth-240,a.right+8)}px`,n.style.top=`${Math.max(8,a.top-6)}px`,IF(n)}function AF(e,t,n,r,i){FF();let a=n.allSelections(),o=a.length===1&&r.length>0,s=document.createElement(`div`);s.className=`context-menu floating`;let c=(e,t,n)=>{let r=document.createElement(`button`);r.type=`button`,r.className=`menu-item${n?.danger?` danger`:``}`,r.disabled=t===null;let i=document.createElement(`span`);if(i.textContent=e,r.appendChild(i),n?.kbd){let e=document.createElement(`kbd`);e.textContent=n.kbd,r.appendChild(e)}t&&r.addEventListener(`click`,()=>{FF(),t()}),s.appendChild(r)};c(`duplicate${a.length>1?` ×${a.length}`:``}`,()=>{for(let e of[...a].reverse())n.duplicateNode(e)}),c(`rename`,o?()=>{wF=i,n.select(r)}:null,{kbd:`dbl-click`}),s.appendChild(jF()),c(`cut`,r.length>0?()=>MF(n,!0):null),c(`copy`,r.length>0?()=>MF(n,!1):null),c(`paste as child${CF?` (${CF.nodes.length})`:``}`,CF?()=>NF(n,r):null),s.appendChild(jF()),c(`delete`,r.length>0?()=>(bF??(e=>n.removeNodes(e)))(a):null,{danger:!0}),document.body.appendChild(s),s.style.left=`${Math.min(innerWidth-200-8,e)}px`,s.style.top=`${Math.min(innerHeight-s.offsetHeight-8,t)}px`,IF(s)}function jF(){let e=document.createElement(`div`);return e.className=`menu-divider`,e}function MF(e,t){let n=e.allSelections().filter(e=>e.length>0).map(t=>e.nodeAt(t)).filter(e=>e!==null);CF={nodes:n.map(e=>JSON.parse(JSON.stringify(e))),cut:t?n:null}}function NF(e,t){if(CF){for(let n of CF.nodes)e.insertNode(n,t);if(CF.cut){let t=e.working.root,n=CF.cut.map(e=>PF(t,e)).filter(e=>e!==null);n.length>0&&e.removeNodes(n),CF={nodes:CF.nodes,cut:null}}}}function PF(e,t){if(e===t)return[];for(let[n,r]of(e.children??[]).entries()){let e=PF(r,t);if(e)return[n,...e]}return null}function FF(){for(let e of document.querySelectorAll(`.floating`))e.remove()}function IF(e){let t=r=>{e.contains(r.target)||(e.remove(),document.removeEventListener(`pointerdown`,t,!0),document.removeEventListener(`keydown`,n,!0))},n=r=>{r.key===`Escape`&&(e.remove(),document.removeEventListener(`pointerdown`,t,!0),document.removeEventListener(`keydown`,n,!0))};setTimeout(()=>{document.addEventListener(`pointerdown`,t,!0),document.addEventListener(`keydown`,n,!0)},0)}function LF(e,t){let n=t.getBoundingClientRect(),r=(e.clientY-n.top)/n.height;return r<.25?`before`:r>.75?`after`:`into`}function RF(e){e.classList.remove(`drop-into`,`drop-before`,`drop-after`)}function zF(e,t,n){e.addEventListener(`dragstart`,r=>{SF=n.isSelected(t)?n.allSelections():[t],r.dataTransfer?.setData(`text/plain`,``),r.dataTransfer&&(r.dataTransfer.effectAllowed=`move`),e.classList.add(`dragging`)}),e.addEventListener(`dragend`,()=>{SF=null,e.classList.remove(`dragging`)}),e.addEventListener(`dragover`,n=>{if(!SF||SF.some(e=>e.length<=t.length&&e.every((e,n)=>e===t[n])))return;n.preventDefault(),n.dataTransfer&&(n.dataTransfer.dropEffect=`move`),RF(e);let r=t.length===0?`into`:LF(n,e);e.classList.add(`drop-${r}`)}),e.addEventListener(`dragleave`,()=>RF(e)),e.addEventListener(`drop`,r=>{if(RF(e),!SF)return;r.preventDefault();let i=t.length===0?`into`:LF(r,e),a=n.moveNodes(SF,t,i);SF=null,a?.[0]&&n.select(a[0])})}var BF={x:`#fb7185`,y:`#86efac`,z:`#7aa2ff`};function VF(e,t,n){let r=t-e.origin.x,i=n-e.origin.y;if(Math.abs(r)<=e.centerSize&&Math.abs(i)<=e.centerSize)return{kind:`center`};for(let t of e.axes){let e=t.sx*t.sx+t.sy*t.sy;if(e<1)continue;let n=Math.max(0,Math.min(1,(r*t.sx+i*t.sy)/e)),a=r-t.sx*n,o=i-t.sy*n;if(n>.25&&Math.hypot(a,o)<=8)return{kind:`axis`,axis:t.axis}}return null}function HF(e,t,n){let r=e.sx*e.sx+e.sy*e.sy;return r<1?0:(t*e.sx+n*e.sy)/r*e.worldPerUnit}function UF(e,t,n,r=!1){let{origin:i,axes:a,centerSize:o}=t;for(let t of a){let a=n?.kind===`axis`&&n.axis===t.axis;e.strokeStyle=t.color,e.fillStyle=t.color,e.globalAlpha=a?1:.9,e.lineWidth=a?3:2,e.beginPath(),e.moveTo(i.x,i.y),e.lineTo(i.x+t.sx,i.y+t.sy),e.stroke();let o=Math.hypot(t.sx,t.sy)||1,s=t.sx/o,c=t.sy/o,l=i.x+t.sx,u=i.y+t.sy;e.beginPath(),r?e.rect(l-5,u-5,10,10):(e.moveTo(l+s*9,u+c*9),e.lineTo(l-c*4.5,u+s*4.5),e.lineTo(l+c*4.5,u-s*4.5),e.closePath()),e.fill(),e.font=`700 9px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(t.axis.toUpperCase(),l+s*18,u+c*18)}let s=n?.kind===`center`;e.globalAlpha=s?1:.95,e.fillStyle=s?`#ffffff`:`#e2e6f0`,e.strokeStyle=`#0b0d14`,e.lineWidth=1.5,e.beginPath(),e.rect(i.x-o,i.y-o,o*2,o*2),e.fill(),e.stroke(),e.globalAlpha=1}function WF(e,t,n){return Math.atan2(n-e.y,t-e.x)*180/Math.PI}function GF(e,t){let n=t-e;for(;n>180;)n-=360;for(;n<=-180;)n+=360;return n}function KF(e,t,n,r){let i=null,a=r;for(let r of e)for(let e of r.points){let o=Math.hypot(t-e.x,n-e.y);o<a&&(a=o,i=r.axis)}return i}function qF(e,t,n){for(let r of t){if(r.points.length<2)continue;let t=n===r.axis;e.strokeStyle=BF[r.axis],e.globalAlpha=t?1:.75,e.lineWidth=t?3:2,e.beginPath();let i=r.points[0];e.moveTo(i.x,i.y);for(let t of r.points.slice(1))e.lineTo(t.x,t.y);e.closePath(),e.stroke()}e.globalAlpha=1}function JF(e,t,n,r){e.font=`600 11px ui-monospace, Menlo, monospace`;let i=e.measureText(r).width+14;e.fillStyle=`rgba(16, 19, 29, 0.92)`,e.strokeStyle=`rgba(110, 231, 220, 0.5)`,e.lineWidth=1,e.beginPath(),e.roundRect(t+14,n-26,i,20,5),e.fill(),e.stroke(),e.fillStyle=`#6ee7dc`,e.textAlign=`left`,e.textBaseline=`middle`,e.fillText(r,t+21,n-16)}var YF=class{engine;editCanvas;overlay;playCanvas;cb;renderer2d=null;renderer3d=null;rendererDim=null;orbit={yaw:.6,pitch:.35,dist:10,target:[0,1,0]};pathOf=new Map;reindexNeeded=!1;nodeAtPath=new Map;selectedPath=null;paintHandler=null;extraPaths=[];hoveredNode=null;hoveredGizmo=null;lastGood=null;lastAppliedKey=null;playEngine=null;playRenderer=null;setPaintHandler(e){this.paintHandler=e}get playing(){return this.playEngine!==null}constructor(e,t,n,r){this.editCanvas=e,this.overlay=t,this.playCanvas=n,this.cb=r;let i=this;this.engine=new Ae({scheduler:e=>{let t=0,n=performance.now(),r=requestAnimationFrame(function a(o){t+=.001;let s=Math.min(.1,(o-n)/1e3);n=o;try{e(t),i.tickAmbientPreviews(s)}catch(e){console.error(`incanto-editor viewport:`,e)}r=requestAnimationFrame(a)});return()=>cancelAnimationFrame(r)}}),this.engine.start(),this.engine.updated.connect(()=>this.drawOverlay()),window.addEventListener(`keydown`,e=>{e.key===`Shift`&&(this.shiftHeld=!0)}),window.addEventListener(`keyup`,e=>{e.key===`Shift`&&(this.shiftHeld=!1)}),this.bindPointer()}apply(e){e.root||(e={...e,root:{name:`__empty`,type:(e.dimension??`2d`)===`3d`?`Node3D`:`Node2D`}});let t=JSON.stringify(e);if(t===this.lastAppliedKey&&this.rendererDim===(e.dimension??`2d`))return null;let n;try{let t=structuredClone(e);delete t.connections,uI(t.root),pI(t),n=xt(t)}catch(e){return e instanceof Error?e.message:String(e)}this.lastGood=e,this.lastAppliedKey=t;let r=e.dimension??`2d`;if(this.rendererDim!==r){if(this.renderer2d?.dispose(),this.renderer3d?.dispose(),this.renderer2d=null,this.renderer3d=null,r===`2d`)this.renderer2d=new bg({canvas:this.editCanvas,engine:this.engine}),this.renderer2d.ignoreStatic=!0,this.renderer2d.viewOverride=this.defaultView(e);else{this.renderer3d=new qA({canvas:this.editCanvas,engine:this.engine}),this.renderer3d.ignoreStatic=!0;let t=cI(e.root);if(t){let[e,n,r]=t;this.orbit.dist=Math.max(2,Math.hypot(e,n,r)),this.orbit.yaw=Math.atan2(e,r),this.orbit.pitch=Math.asin(Math.max(-.99,Math.min(.99,n/this.orbit.dist))),this.orbit.target=[0,Math.min(2,Math.abs(n)/2),0]}this.syncOrbit()}this.rendererDim=r}return this.engine.setScene(n),this.indexTree(n.root),this.hoveredNode=null,null}setSelection(e,t=[]){this.selectedPath=e,this.extraPaths=t}validate(e){if(!e.root)return null;try{let t=structuredClone(e);return delete t.connections,uI(t.root),pI(t),xt(t),null}catch(e){return e instanceof Error?e.message:String(e)}}defaultView(e){let t=lI(e.root);if(t)return{cx:t[0],cy:t[1],zoom:1};let n=this.editCanvas.clientWidth||960,r=this.editCanvas.clientHeight||540;return{cx:n/2,cy:r/2,zoom:1}}indexTree(e){this.pathOf=new Map,this.nodeAtPath=new Map;let t=(e,n)=>{this.pathOf.set(e,n),this.nodeAtPath.set(n.join(`.`),e),e.children.forEach((e,r)=>{t(e,[...n,r])})};t(e,[])}liveSelected(){return this.selectedPath===null?null:this.nodeAtPath.get(this.selectedPath.join(`.`))??null}patchProp(e,t,n,r){if(this.playing)return!1;let i=this.nodeAtPath.get(t.join(`.`));if(!i)return!1;try{i[n]=r===void 0?void 0:structuredClone(r)}catch{return!1}return this.reindexNeeded=!0,this.lastAppliedKey=JSON.stringify(e),!0}gizmoActive=null;gizmoMode=`move`;activeRing=null;readout=null;cancelActiveDrag=()=>{};shiftHeld=!1;showColliders=!0;get mode(){return this.gizmoMode}setMode(e){this.gizmoMode=e,this.cb.onModeChanged(e)}gizmoLayout(){let e=this.liveSelected();if(!e)return null;if(this.rendererDim===`2d`&&this.renderer2d){let t=e.position;if(!Array.isArray(t))return null;let n=sI(e),r=this.renderer2d.screenFromWorld(n.x,n.y),i=this.renderer2d.view().zoom;return{origin:r,centerSize:7,axes:[{axis:`x`,sx:64,sy:0,worldPerUnit:64/i,color:BF.x},{axis:`y`,sx:0,sy:64,worldPerUnit:64/i,color:BF.y}]}}if(this.rendererDim===`3d`&&this.renderer3d){let t=e._object3D,n=e.position;if(!t||!Array.isArray(n))return null;t.getWorldPosition(nI);let r=this.renderer3d.screenFromWorld(nI.x,nI.y,nI.z);if(r.behind)return null;let i=[],a=this.orbit.dist,o=Math.max(.2,a*.18);for(let[e,t]of[[`x`,[1,0,0]],[`y`,[0,1,0]],[`z`,[0,0,1]]]){let n=this.renderer3d.screenFromWorld(nI.x+t[0]*o,nI.y+t[1]*o,nI.z+t[2]*o);n.behind||i.push({axis:e,sx:n.x-r.x,sy:n.y-r.y,worldPerUnit:o,color:BF[e]})}return{origin:{x:r.x,y:r.y},centerSize:7,axes:i}}return null}ringLayout(){let e=this.liveSelected();if(!e)return null;if(this.rendererDim===`2d`&&this.renderer2d){let t=sI(e),n=this.renderer2d.screenFromWorld(t.x,t.y),r=[];for(let e=0;e<48;e++){let t=e/48*Math.PI*2;r.push({x:n.x+56*Math.cos(t),y:n.y+56*Math.sin(t)})}return{origin:n,rings:[{axis:`z`,points:r}]}}if(this.rendererDim===`3d`&&this.renderer3d){let t=e._object3D;if(!t)return null;t.getWorldPosition(nI);let n={x:nI.x,y:nI.y,z:nI.z},r=this.renderer3d.screenFromWorld(n.x,n.y,n.z);if(r.behind)return null;let i=Math.max(.2,this.orbit.dist*.16),a=[];for(let e of[`x`,`y`,`z`]){let t=[];for(let r=0;r<48;r++){let a=r/48*Math.PI*2,o=Math.cos(a)*i,s=Math.sin(a)*i,c=e===`x`?this.renderer3d.screenFromWorld(n.x,n.y+o,n.z+s):e===`y`?this.renderer3d.screenFromWorld(n.x+o,n.y,n.z+s):this.renderer3d.screenFromWorld(n.x+o,n.y+s,n.z);c.behind||t.push({x:c.x,y:c.y})}a.push({axis:e,points:t})}return{origin:{x:r.x,y:r.y},rings:a}}return null}orbitVectors(){let{yaw:e,pitch:t,dist:n,target:r}=this.orbit,i=Math.cos(t),a=new H(r[0]+n*i*Math.sin(e),r[1]+n*Math.sin(t),r[2]+n*i*Math.cos(e)),o=new H(r[0],r[1],r[2]).sub(a).normalize(),s=new H().crossVectors(o,QF).normalize();return{pos:a,right:s,up:new H().crossVectors(s,o).normalize(),forward:o}}syncOrbit(){if(!this.renderer3d)return;let{pos:e}=this.orbitVectors();this.renderer3d.viewOverride={position:[e.x,e.y,e.z],target:[...this.orbit.target]}}gameView(){if(this.rendererDim===`3d`&&this.renderer3d){let e=null;for(let[t]of this.pathOf)if(t instanceof TC&&(t.current||!e)&&(e=t,t.current))break;let t=e?e._ensureObject3D():null;if(t){t.getWorldPosition($F),eI.set(0,0,-1).applyQuaternion(t.getWorldQuaternion(tI));let e=Math.min(40,Math.max(3,this.orbit.dist));this.orbit.target=[$F.x+eI.x*e,$F.y+eI.y*e,$F.z+eI.z*e],this.orbit.dist=e,this.orbit.yaw=Math.atan2(-eI.x,-eI.z),this.orbit.pitch=Math.asin(Math.max(-.99,Math.min(.99,-eI.y)))}this.renderer3d.viewOverride=null;return}this.renderer2d&&(this.renderer2d.viewOverride=null)}snapView(e,t){e===`y`?(this.orbit.pitch=t*1.45,this.orbit.yaw=0):(this.orbit.pitch=0,this.orbit.yaw=e===`z`?t===1?0:Math.PI:Math.PI/2*t),this.syncOrbit()}gizmoCenter(){return{x:this.overlay.clientWidth-58,y:58,r:36}}gizmoHandles(){let{right:e,up:t,forward:n}=this.orbitVectors(),r=this.gizmoCenter(),i=[];for(let[a,o]of[[`x`,new H(1,0,0)],[`y`,new H(0,1,0)],[`z`,new H(0,0,1)]])for(let s of[1,-1]){let c=o.clone().multiplyScalar(s);i.push({axis:a,sign:s,x:r.x+c.dot(e)*26,y:r.y-c.dot(t)*26,z:-c.dot(n)})}return i.sort((e,t)=>e.z-t.z)}gizmoHit(e,t){let n=this.gizmoCenter();if(Math.hypot(e-n.x,t-n.y)>n.r+8)return null;let r=null,i=14;for(let n of this.gizmoHandles()){let a=Math.hypot(e-n.x,t-n.y);a<i&&(i=a,r={axis:n.axis,sign:n.sign})}return r??{axis:`z`,sign:1}}gizmoHandleAt(e,t){let n=this.gizmoCenter();if(Math.hypot(e-n.x,t-n.y)>n.r+8)return null;let r=null,i=12;for(let n of this.gizmoHandles()){let a=Math.hypot(e-n.x,t-n.y);a<i&&(i=a,r={axis:n.axis,sign:n.sign})}return r}tickAmbientPreviews(e){if(!this.playing)for(let[t]of this.pathOf)(t instanceof BE||t instanceof Qh||t instanceof UE||t instanceof Pm||t instanceof tE)&&t.update(e)}modelAnimationsAt(e){let t=this.nodeAtPath.get(e.join(`.`));return t instanceof BE?t.availableAnimations():[]}boneNamesAt(e,t){let n=this.nodeAtPath.get(e.join(`.`));if(!n||t===``)return[];let r=n.getNodeOrNull(t);return r instanceof BE?r.boneNames():[]}drawOverlay(){if(this.reindexNeeded){this.reindexNeeded=!1;let e=this.engine.scene?.tree.root;e&&this.indexTree(e)}let e=this.overlay.getContext(`2d`);if(!e)return;let t=this.overlay.clientWidth,n=this.overlay.clientHeight,r=Math.min(devicePixelRatio||1,2);if((this.overlay.width!==t*r||this.overlay.height!==n*r)&&(this.overlay.width=t*r,this.overlay.height=n*r),e.setTransform(r,0,0,r,0,0),e.clearRect(0,0,t,n),this.playing)return;if(this.rendererDim===`3d`){this.showColliders&&this.drawColliders3D(e),this.drawGizmo(e),this.drawModeGizmo(e),this.readout&&JF(e,this.readout.x,this.readout.y,this.readout.text);return}if(!this.renderer2d)return;if(this.drawAxes2D(e),this.showColliders)for(let[t]of this.pathOf){let n=t.collider;n&&typeof n==`object`&&`shape`in n&&this.drawCollider(e,t,n)}if(this.hoveredNode&&this.hoveredNode!==this.liveSelected()){let t=this.renderer2d.boundsOf(this.hoveredNode);t&&(e.strokeStyle=`rgba(110, 231, 220, 0.45)`,e.lineWidth=1.5,e.setLineDash([]),e.strokeRect(t.x,t.y,t.w,t.h))}for(let t of this.extraPaths){let n=this.nodeAtPath.get(t.join(`.`)),r=n?this.renderer2d.boundsOf(n):null;r&&(e.strokeStyle=`rgba(110, 231, 220, 0.7)`,e.lineWidth=1.5,e.setLineDash([4,3]),e.strokeRect(r.x-2,r.y-2,r.w+4,r.h+4),e.setLineDash([]))}let i=this.liveSelected();if(i){let t=this.renderer2d.boundsOf(i)??this.pointBounds(i);if(t){e.strokeStyle=`#6ee7dc`,e.lineWidth=2,e.setLineDash([6,4]),e.lineDashOffset=-(performance.now()/50%10),e.strokeRect(t.x-2,t.y-2,t.w+4,t.h+4),e.setLineDash([]),e.fillStyle=`#6ee7dc`;for(let[n,r]of[[t.x-2,t.y-2],[t.x+t.w+2,t.y-2],[t.x-2,t.y+t.h+2],[t.x+t.w+2,t.y+t.h+2]])e.fillRect(n-3,r-3,6,6)}}this.drawModeGizmo(e),this.readout&&JF(e,this.readout.x,this.readout.y,this.readout.text)}drawModeGizmo(e){if(this.gizmoMode===`rotate`){let t=this.ringLayout();t&&qF(e,t.rings,this.activeRing);return}let t=this.gizmoLayout();t&&UF(e,t,this.gizmoActive,this.gizmoMode===`scale`)}drawGizmo(e){let t=this.gizmoCenter();e.beginPath(),e.arc(t.x,t.y,t.r,0,Math.PI*2),e.fillStyle=`rgba(16, 19, 29, 0.72)`,e.fill(),e.strokeStyle=`rgba(52, 60, 84, 0.9)`,e.lineWidth=1,e.stroke();let n={x:`#fb7185`,y:`#86efac`,z:`#7aa2ff`},r={x1:`right`,"x-1":`left`,y1:`top`,"y-1":`bottom`,z1:`front`,"z-1":`back`};for(let r of this.gizmoHandles()){let i=this.hoveredGizmo?.axis===r.axis&&this.hoveredGizmo?.sign===r.sign,a=n[r.axis],o=(r.z+1)/2;e.globalAlpha=i?1:.45+o*.55,e.strokeStyle=a,e.lineWidth=1.5,e.beginPath(),e.moveTo(t.x,t.y),e.lineTo(r.x,r.y),e.stroke(),e.beginPath(),e.arc(r.x,r.y,(r.sign===1?7:5)+(i?2:0),0,Math.PI*2),r.sign===1?(e.fillStyle=a,e.fill(),e.fillStyle=`#0b0d14`,e.font=`700 8px ui-monospace, monospace`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillText(r.axis.toUpperCase(),r.x,r.y+.5)):(e.fillStyle=`rgba(16, 19, 29, 0.9)`,e.fill(),e.stroke())}if(e.globalAlpha=1,this.hoveredGizmo){let n=r[`${this.hoveredGizmo.axis}${this.hoveredGizmo.sign}`];e.fillStyle=`#9aa3bd`,e.font=`600 10px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`bottom`,e.fillText(`${n} view`,t.x,t.y-t.r-6)}}drawColliders3D(e){let t=this.renderer3d;if(!t)return;e.save(),e.strokeStyle=XF,e.lineWidth=1.5;let n=(e,n,r)=>t.screenFromWorld(e,n,r),r=(t,r=!1)=>{e.beginPath();let i=!1;for(let[r,a,o]of t){let t=n(r,a,o);if(t.behind){i=!1;continue}i?e.lineTo(t.x,t.y):e.moveTo(t.x,t.y),i=!0}r&&e.closePath(),e.stroke()},i=(e,t,n,i,a)=>{let o=[];for(let r=0;r<=32;r++){let s=r/32*Math.PI*2,c=Math.cos(s)*i,l=Math.sin(s)*i;a===`xz`?o.push([e+c,t,n+l]):a===`xy`?o.push([e+c,t+l,n]):o.push([e,t+c,n+l])}r(o)};for(let[e]of this.pathOf){let t=e.collider,n=e._object3D;if(!t||typeof t!=`object`||!(`shape`in t)||!n)continue;n.getWorldPosition(nI);let a=t.offset??[0,0,0],o=nI.x+(a[0]??0),s=nI.y+(a[1]??0),c=nI.z+(a[2]??0);if(t.shape===`box`){let e=t.size??[1,1,1],n=(e[0]??1)/2,i=(e[1]??1)/2,a=(e[2]??1)/2;r([[o-n,s-i,c-a],[o+n,s-i,c-a],[o+n,s-i,c+a],[o-n,s-i,c+a]],!0),r([[o-n,s+i,c-a],[o+n,s+i,c-a],[o+n,s+i,c+a],[o-n,s+i,c+a]],!0);for(let[e,t]of[[-1,-1],[1,-1],[1,1],[-1,1]])r([[o+e*n,s-i,c+t*a],[o+e*n,s+i,c+t*a]])}else if(t.shape===`sphere`){let e=t.radius??.5;i(o,s,c,e,`xz`),i(o,s,c,e,`xy`),i(o,s,c,e,`yz`)}else if(t.shape===`capsule`){let e=t.radius??.4,n=(t.height??1)/2;i(o,s+n,c,e,`xz`),i(o,s-n,c,e,`xz`);for(let[t,i]of[[e,0],[-e,0],[0,e],[0,-e]])r([[o+t,s-n,c+i],[o+t,s+n,c+i]])}}e.restore()}drawAxes2D(e){let t=this.gizmoCenter();e.save(),e.shadowColor=`rgba(0, 0, 0, 0.25)`,e.shadowBlur=10,e.shadowOffsetY=2,e.beginPath(),e.arc(t.x,t.y,31,0,Math.PI*2),e.fillStyle=`rgba(13, 16, 24, 0.42)`,e.fill(),e.shadowColor=`transparent`,e.strokeStyle=`rgba(255, 255, 255, 0.16)`,e.lineWidth=1,e.stroke();let n=t.x-9,r=t.y-9;e.lineCap=`round`;let i=(t,i,a,o)=>{let s=n+t*21,c=r+i*21,l=e.createLinearGradient(n,r,s,c);l.addColorStop(0,`${a}55`),l.addColorStop(1,a),e.strokeStyle=l,e.lineWidth=2,e.beginPath(),e.moveTo(n,r),e.lineTo(s,c),e.stroke(),e.beginPath(),e.arc(s,c,6.5,0,Math.PI*2),e.fillStyle=a,e.fill(),e.font=`800 8px Inter, system-ui, sans-serif`,e.textAlign=`center`,e.textBaseline=`middle`,e.fillStyle=`#0b0d14`,e.fillText(o,s,c+.5)};i(1,0,`#fb7185`,`X`),i(0,1,`#86efac`,`Y`),e.beginPath(),e.arc(n,r,2.5,0,Math.PI*2),e.fillStyle=`#e2e6f0`,e.fill(),e.restore()}pointBounds(e){if(!this.renderer2d)return null;let t=e.position;if(!Array.isArray(t))return null;let n=sI(e),r=this.renderer2d.screenFromWorld(n.x,n.y);return{x:r.x-12,y:r.y-12,w:24,h:24}}drawCollider(e,t,n){if(!this.renderer2d)return;let r=sI(t),i=n.offset??[0,0],a=this.renderer2d.screenFromWorld(r.x+(i[0]??0),r.y+(i[1]??0)),o=this.renderer2d.view().zoom;e.strokeStyle=XF,e.lineWidth=1.5,e.setLineDash([]);let s=n.shape;if(s===`rect`){let t=n.size??[32,32],r=(t[0]??32)/2*o,i=(t[1]??32)/2*o;e.strokeRect(a.x-r,a.y-i,r*2,i*2)}else if(s===`circle`){let t=(n.radius??16)*o;e.beginPath(),e.arc(a.x,a.y,t,0,Math.PI*2),e.stroke()}else if(s===`capsule`){let t=(n.radius??16)*o,r=(n.height??32)/2*o;e.beginPath(),e.arc(a.x,a.y-r,t,Math.PI,0),e.arc(a.x,a.y+r,t,0,Math.PI),e.closePath(),e.stroke()}e.setLineDash([])}bindPointer(){let e=this.overlay,t=null,n=null,r=!1,i=null,a=null,o=null,s=null,c=null,l=t=>{let n=this.ringLayout();if(!n)return!1;let r=KF(n.rings,t.offsetX,t.offsetY,9);if(!r)return!1;let i=this.liveSelected();if(!i)return!1;e.setPointerCapture(t.pointerId);let a=i.rotation,o=1;if(this.rendererDim===`3d`&&this.renderer3d){let{forward:e}=this.renderer3d.cameraBasis();o=(r===`x`?e.x:r===`y`?e.y:e.z)>0?1:-1}return c={axis:r,node:i,origin:n.origin,startAngle:WF(n.origin,t.offsetX,t.offsetY),startRotation:Array.isArray(a)?[...a]:a??0,sign:o},this.activeRing=r,!0},u=e=>{if(!c)return;let{axis:t,node:n,origin:r,startAngle:i,startRotation:a,sign:o}=c,s=GF(i,WF(r,e.offsetX,e.offsetY))*o,l=e.shiftKey||this.shiftHeld?15:null,u=e=>{let t=e+s;return l?Math.round(t/l)*l:Math.round(t*10)/10},d;if(Array.isArray(a)){let e={x:0,y:1,z:2}[t],r=[...a];r[e]=u(a[e]??0),d=r[e],n.rotation=r}else{let e=u(a);d=e,n.rotation=e}this.readout={x:e.offsetX,y:e.offsetY,text:`${d}°${l?` ⌁15°`:``}`}},d=e=>{if(!c)return;let{node:t,startRotation:n}=c;if(!e)t.rotation=n;else{let e=this.pathOf.get(t),n=t.rotation;e!==void 0&&n!==void 0&&(Array.isArray(n)?this.cb.onNodeRotated3D(e,[n[0]??0,n[1]??0,n[2]??0]):this.cb.onNodeRotated2D(e,n))}c=null,this.activeRing=null,this.readout=null};this.cancelActiveDrag=()=>{d(!1),s&&(s.node.position=s.startPos,s.node.scale=s.startScale,s=null,this.gizmoActive=null,this.readout=null)};let f=t=>{if(this.gizmoMode===`rotate`)return l(t);let n=this.gizmoLayout();if(!n)return!1;let r=VF(n,t.offsetX,t.offsetY);if(!r)return!1;let i=this.liveSelected();if(!i)return!1;e.setPointerCapture(t.pointerId);let a=[...i.position??[]],o=[...i.scale??[]];return s={hit:r,mode:this.gizmoMode===`scale`||t.button===2?`scale`:`move`,startX:t.offsetX,startY:t.offsetY,layout:n,node:i,startPos:a,startScale:o},this.gizmoActive=r,!0},p=e=>{if(!s)return;let{hit:t,mode:n,layout:r,node:i,startPos:a,startScale:o}=s,c=e.offsetX-s.startX,l=e.offsetY-s.startY,u=this.rendererDim===`3d`,d={x:0,y:1,z:2},f=e.shiftKey||this.shiftHeld,p=f?u?.5:10:null,m=f?.25:null,h=e=>p?Math.round(e/p)*p:e,g=e=>m?Math.max(m,Math.round(e/m)*m):e;if(n===`scale`){let n=Math.max(.05,1+(c-l)*.005),r=[...o];if(t.kind===`axis`)r[d[t.axis]]=ZF(g((o[d[t.axis]]??1)*n));else for(let e=0;e<r.length;e++)r[e]=ZF(g((o[e]??1)*n));i.scale=r,this.readout={x:e.offsetX,y:e.offsetY,text:`×${r.map(e=>ZF(e)).join(`, `)}`};return}let _=[...a];if(t.kind===`axis`){let e=r.axes.find(e=>e.axis===t.axis);if(!e)return;let n=HF(e,c,l);if(u)_[d[t.axis]]=ZF(h((a[d[t.axis]]??0)+n));else{let e=oI(i,t.axis===`x`?n:0,t.axis===`y`?n:0),r=t.axis===`x`?e.x:e.y;_[d[t.axis]]=Math.round(h((a[d[t.axis]]??0)+r))}}else if(u&&this.renderer3d){let{right:e,up:t}=this.renderer3d.cameraBasis(),n=this.orbit.dist*.0016;_[0]=ZF(h((a[0]??0)+(e.x*c-t.x*l)*n)),_[1]=ZF(h((a[1]??0)+(e.y*c-t.y*l)*n)),_[2]=ZF(h((a[2]??0)+(e.z*c-t.z*l)*n))}else if(this.renderer2d){let e=this.renderer2d.view(),t=oI(i,c/e.zoom,l/e.zoom);_[0]=Math.round(h((a[0]??0)+t.x)),_[1]=Math.round(h((a[1]??0)+t.y))}i.position=_,this.readout={x:e.offsetX,y:e.offsetY,text:`[${_.map(e=>ZF(e)).join(`, `)}]`}},m=()=>{if(!s)return;let{node:e,mode:t}=s,n=this.pathOf.get(e);if(n)if(t===`scale`){let t=e.scale??[];this.rendererDim===`3d`?this.cb.onNodeScaled3D(n,[t[0]??1,t[1]??1,t[2]??1]):this.cb.onNodeScaled(n,[t[0]??1,t[1]??1])}else{let t=e.position??[];this.rendererDim===`3d`?this.cb.onNodeMoved3D(n,[t[0]??0,t[1]??0,t[2]??0]):this.cb.onNodeMoved(n,[t[0]??0,t[1]??0])}s=null,this.gizmoActive=null};e.addEventListener(`pointerdown`,s=>{if(this.playing||f(s))return;if(this.rendererDim===`3d`){let t=this.gizmoHit(s.offsetX,s.offsetY);if(t){this.snapView(t.axis,t.sign);return}e.setPointerCapture(s.pointerId),s.button===1||s.button===2||s.shiftKey?a={x:s.offsetX,y:s.offsetY,target:[...this.orbit.target]}:(i={x:s.offsetX,y:s.offsetY,yaw:this.orbit.yaw,pitch:this.orbit.pitch},o={x:s.offsetX,y:s.offsetY,toggle:s.ctrlKey||s.metaKey});return}if(!this.renderer2d)return;if(e.setPointerCapture(s.pointerId),s.button===1||s.button===2||s.shiftKey){let e=this.renderer2d.view();n={startX:s.offsetX,startY:s.offsetY,cx:e.cx,cy:e.cy};return}if(this.paintHandler&&s.button===0){let e=this.renderer2d.worldFromScreen(s.offsetX,s.offsetY);this.paintHandler(e.x,e.y,!0),r=!0;return}let c=this.renderer2d.pick(s.offsetX,s.offsetY),l=c?this.pathOf.get(c)??null:null;if(this.cb.onPick(l,{toggle:s.ctrlKey||s.metaKey}),this.selectedPath=l,c&&l&&Array.isArray(c.position)){let e=c.position;t={node:c,startWorld:this.renderer2d.worldFromScreen(s.offsetX,s.offsetY),startPos:[e[0]??0,e[1]??0]}}}),e.addEventListener(`pointermove`,o=>{if(!this.playing){if(c){u(o);return}if(s){p(o);return}if(this.rendererDim===`3d`){if(!i&&!a?(this.hoveredGizmo=this.gizmoHandleAt(o.offsetX,o.offsetY),e.style.cursor=this.hoveredGizmo?`pointer`:`grab`):e.style.cursor=`grabbing`,i)this.orbit.yaw=i.yaw-(o.offsetX-i.x)*.006,this.orbit.pitch=Math.max(-1.5,Math.min(1.5,i.pitch+(o.offsetY-i.y)*.006)),this.syncOrbit();else if(a){let{right:e,up:t}=this.orbitVectors(),n=this.orbit.dist*.0016,r=(o.offsetX-a.x)*n,i=(o.offsetY-a.y)*n;this.orbit.target=[a.target[0]-e.x*r+t.x*i,a.target[1]-e.y*r+t.y*i,a.target[2]-e.z*r+t.z*i],this.syncOrbit()}return}if(this.renderer2d){if(e.style.cursor=`crosshair`,r&&this.paintHandler){let e=this.renderer2d.worldFromScreen(o.offsetX,o.offsetY);this.paintHandler(e.x,e.y,!1);return}if(n){let e=this.renderer2d.view();this.renderer2d.viewOverride={cx:n.cx-(o.offsetX-n.startX)/e.zoom,cy:n.cy-(o.offsetY-n.startY)/e.zoom,zoom:e.zoom};return}if(t){let e=this.renderer2d.worldFromScreen(o.offsetX,o.offsetY),n=oI(t.node,e.x-t.startWorld.x,e.y-t.startWorld.y),r=Math.round(t.startPos[0]+n.x),i=Math.round(t.startPos[1]+n.y);t.node.position=[r,i];return}this.hoveredNode=this.renderer2d.pick(o.offsetX,o.offsetY)}}});let h=e=>{if(r=!1,d(!0),m(),this.readout=null,o&&e&&this.renderer3d&&Math.hypot(e.offsetX-o.x,e.offsetY-o.y)<4){let e=this.renderer3d.pick(o.x,o.y),t=e?this.pathOf.get(e)??null:null;t&&(this.cb.onPick(t,{toggle:o.toggle}),this.selectedPath=t)}if(o=null,i=null,a=null,t){let e=this.pathOf.get(t.node),n=t.node.position;e&&(n[0]!==t.startPos[0]||n[1]!==t.startPos[1])&&this.cb.onNodeMoved(e,[n[0]??0,n[1]??0]),t=null}n=null};e.addEventListener(`pointerup`,h),e.addEventListener(`pointercancel`,h),e.addEventListener(`contextmenu`,e=>e.preventDefault()),e.addEventListener(`dblclick`,e=>{if(this.playing)return;let t=this.rendererDim===`3d`?this.renderer3d?.pick(e.offsetX,e.offsetY)??null:this.renderer2d?.pick(e.offsetX,e.offsetY)??null,n=t?this.pathOf.get(t)??null:null;n&&(this.cb.onPick(n,{toggle:e.ctrlKey||e.metaKey}),this.selectedPath=n)}),e.addEventListener(`wheel`,e=>{if(this.playing)return;e.preventDefault();let t=e.deltaY<0?1.1:1/1.1;if(this.rendererDim===`3d`){this.orbit.dist=Math.max(.3,Math.min(800,this.orbit.dist/t)),this.syncOrbit();return}if(!this.renderer2d)return;let n=this.liveSelected();if(e.altKey&&n&&Array.isArray(n.scale)){let e=n.scale,r=[Math.round((e[0]??1)*t*100)/100,Math.round((e[1]??1)*t*100)/100];n.scale=r;let i=this.pathOf.get(n);i&&this.cb.onNodeScaled(i,r);return}let r=this.renderer2d.view(),i=this.renderer2d.worldFromScreen(e.offsetX,e.offsetY),a=Math.min(8,Math.max(.1,r.zoom*t));this.renderer2d.viewOverride={cx:i.x-(e.offsetX-r.w/2)/a,cy:i.y-(e.offsetY-r.h/2)/a,zoom:a}},{passive:!1})}zoomToFit(){if(this.rendererDim===`3d`){let e=new Sa;for(let[t]of this.pathOf){let n=t._object3D;n&&(e.expandByObject(n),e.expandByPoint(n.getWorldPosition(nI)))}if(e.isEmpty())this.orbit.target=[0,1,0],this.orbit.dist=10;else{let t=e.getCenter(new H),n=e.getSize(new H);this.orbit.target=[t.x,t.y,t.z],this.orbit.dist=Math.max(2.5,n.length()*.85)}this.syncOrbit();return}if(!this.renderer2d)return;let e=this.editCanvas.clientWidth||960,t=this.editCanvas.clientHeight||540,n=1/0,r=1/0,i=-1/0,a=-1/0;for(let[e]of this.pathOf){let t=e.position;if(!Array.isArray(t))continue;let o=sI(e);n=Math.min(n,o.x),r=Math.min(r,o.y),i=Math.max(i,o.x),a=Math.max(a,o.y)}if(!Number.isFinite(n))return;let o=(n+i)/2,s=(r+a)/2,c=Math.max(i-n+200,200),l=Math.max(a-r+200,200),u=Math.min(2,Math.min(e/c,t/l));this.renderer2d.viewOverride={cx:o,cy:s,zoom:u}}async play(e){if(this.playing)return null;let t=structuredClone(e);uI(t.root),pI(t);let n;try{n=xt(structuredClone(t),{declareConnectionSignals:!0})}catch{delete t.connections;try{n=xt(structuredClone(t))}catch(e){return e instanceof Error?e.message:String(e)}}let r=new Ae;r.setScene(n),r.input.attachKeyboard(window),this.playCanvas.hidden=!1;let i=e.dimension??`2d`;try{if(i===`2d`){this.playRenderer=new bg({canvas:this.playCanvas,engine:r});let{enablePhysics2D:e}=await Dh(async()=>{let{enablePhysics2D:e}=await Promise.resolve().then(()=>Dg);return{enablePhysics2D:e}},void 0,import.meta.url),t=await e(r);t.debugDraw=this.showColliders}else{this.playRenderer=new qA({canvas:this.playCanvas,engine:r});let{enablePhysics3D:e}=await Dh(async()=>{let{enablePhysics3D:e}=await Promise.resolve().then(()=>rj);return{enablePhysics3D:e}},void 0,import.meta.url),t=await e(r);t.debugDraw=this.showColliders}}catch(e){return this.stop(),e instanceof Error?e.message:String(e)}return r.start(),this.playEngine=r,this.cb.onPlayStateChanged(!0),null}stop(){this.playEngine?.input.dispose(),this.playEngine?.stop(),this.playEngine=null,this.playRenderer?.dispose(),this.playRenderer=null,this.playCanvas.hidden=!0,this.cb.onPlayStateChanged(!1),this.lastAppliedKey=null,this.lastGood&&this.apply(this.lastGood)}},XF=`rgba(0, 255, 110, 0.95)`;function ZF(e){return Math.round(e*100)/100}var QF=new H(0,1,0),$F=new H,eI=new H,tI=new V,nI=new H,rI=new W,iI=new H,aI=new H;function oI(e,t,n){let r=e._object2D?.parent;return r?(rI.copy(r.matrixWorld).invert(),iI.set(t,-n,0).applyMatrix4(rI),aI.set(0,0,0).applyMatrix4(rI),{x:iI.x-aI.x,y:-(iI.y-aI.y)}):{x:t,y:n}}function sI(e){let t=e._object2D;if(t)return t.getWorldPosition(nI),{x:nI.x,y:-nI.y};let n=0,r=0,i=e;for(;i;)Array.isArray(i.position)&&(n+=i.position[0]??0,r+=i.position[1]??0),i=i.parent;return{x:n,y:r}}function cI(e){if(!e)return null;if(e.type===`Camera3D`){let t=e.props?.position??[0,2,8];return[t[0]??0,t[1]??2,t[2]??8]}for(let t of e.children??[]){let e=cI(t);if(e)return e}return null}function lI(e){if(!e)return null;if(e.type===`Camera2D`){let t=e.props?.position??[0,0];return[t[0]??0,t[1]??0]}for(let t of e.children??[]){let e=lI(t);if(e)return e}return null}function uI(e){if(typeof e!=`object`||!e)return;let t=e;delete t.script;for(let e of t.children??[])uI(e)}var dI=null;function fI(){if(dI)return dI;let e=document.createElement(`canvas`);e.width=16,e.height=16;let t=e.getContext(`2d`);for(let e=0;e<2;e++)for(let n=0;n<2;n++)t.fillStyle=(n+e)%2==0?`#c252c2`:`#2b2b3b`,t.fillRect(n*8,e*8,8,8);return dI=e.toDataURL(),dI}function pI(e){let t=e.assets;if(t)for(let e of Object.values(t))typeof e?.url==`string`&&!e.url.includes(`/`)&&!e.url.includes(`.`)&&(e.url=fI())}ct(),cg(),kk(),pj();var $=e=>{let t=document.querySelector(e);if(!t)throw Error(`missing ${e}`);return t};async function mI(){let e=await bj();$(`#engine-version`).textContent=`incanto@${e.version}`,dP($(`#popover`)),bM(),$(`#docs-btn`).addEventListener(`click`,()=>vM());let t=$(`#lang-btn`),n=[{code:`en`,label:`English`},{code:`ko`,label:`한국어`}],r=()=>{$(`#lang-current`).textContent=Oj()===`ko`?`한국어`:`EN`};r(),t.addEventListener(`click`,()=>{document.querySelector(`.lang-menu`)?.remove();let e=document.createElement(`div`);e.className=`context-menu floating lang-menu`;for(let{code:t,label:r}of n){let n=document.createElement(`button`);n.type=`button`,n.className=`menu-item`;let i=document.createElement(`span`);i.textContent=r;let a=document.createElement(`span`);a.textContent=Oj()===t?`✓`:``,a.className=`lang-check`,n.append(i,a),n.addEventListener(`click`,()=>{e.remove(),kj(t)}),e.appendChild(n)}document.body.appendChild(e);let r=t.getBoundingClientRect();e.style.left=`${r.left}px`,e.style.top=`${r.bottom+6}px`;let i=n=>{e.contains(n.target)||n.target===t||(e.remove(),document.removeEventListener(`pointerdown`,i,!0))};setTimeout(()=>document.addEventListener(`pointerdown`,i,!0),0)}),Aj(()=>{r(),xM(),i.select(i.selection)});let i=new sF({format:1,type:`scene`,name:``,root:null}),a=$(`#tree`),o=$(`#inspector`),s=$(`#save-btn`),c=$(`#undo-btn`),l=$(`#play-btn`),u=$(`#error-banner`),d=$(`#play-notice`),f=$(`#add-type`),p=$(`#picker`),m=$(`#picker-list`),h=$(`#scenes-btn`),g=e.input,_=e.output,v,y=!1,b=e=>{u.hidden=!1,u.textContent=e,dM.error(e)},x={on:!1,brush:`0`},S=e=>{let t=0,n=0,r=i.working.root,a=e=>{let r=e?.props?.position;Array.isArray(r)&&(t+=Number(r[0]??0),n+=Number(r[1]??0))};a(r);for(let t of e)r=r?.children?.[t],a(r);return{x:t,y:n}},C=!1,w=(e,t,n=!0)=>{n&&(C=!1);let r=i.selection,a=i.nodeAt(r);if(!r||a?.type!==`TileMap2D`)return;let{cx:o,cy:s}=mP(S(r),Number(a.props?.tileSize??32),e,t),c=a.props?.cells??[],l=hP(c,o,s,x.brush);!l||JSON.stringify(l)===JSON.stringify(c)||(i.mutate(()=>{a.props||={},a.props.cells=l},{path:r,key:`cells`,value:l},{coalesce:C}),C=!0)},T=()=>{let e=i.nodeAt(i.selection);x.on&&e?.type!==`TileMap2D`&&(x.on=!1),E.setPaintHandler(x.on?w:null)},E=new YF($(`#viewport`),$(`#overlay`),$(`#play-canvas`),{onPick:(e,t)=>i.select(e??null,t),onNodeMoved:(e,t)=>re(e,`position`,t,[0,0]),onNodeScaled:(e,t)=>re(e,`scale`,t,[1,1]),onNodeMoved3D:(e,t)=>re(e,`position`,t,[0,0,0]),onNodeScaled3D:(e,t)=>re(e,`scale`,t,[1,1,1]),onNodeRotated2D:(e,t)=>ne(e,`rotation`,t,0),onNodeRotated3D:(e,t)=>re(e,`rotation`,t,[0,0,0]),onModeChanged:e=>{for(let t of[`move`,`rotate`,`scale`])$(`#tool-${t}`).classList.toggle(`active`,t===e)},onPlayStateChanged:e=>{document.body.classList.toggle(`playing`,e),l.classList.toggle(`stop`,e),l.innerHTML=e?`<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12"/></svg> stop`:`<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg> play`,d.hidden=!e,e&&(d.textContent=`▶ simulating — physics + input live; game scripts run only in your real game. Esc or stop to return.`)},onError:b}),D=he().sort(),O=``,k=e=>{if(e===O)return;O=e,f.textContent=``;let t=e===`3d`?[`3D`,`3D Physics`,`Core`,`Network`,`2D`,`2D Physics`]:[`2D`,`2D Physics`,`Core`,`Network`,`3D`,`3D Physics`];for(let[e]of pM)t.includes(e)||t.push(e);for(let e of t){let t=pM.find(([t])=>t===e)?.[1];if(!t)continue;let n=document.createElement(`optgroup`);n.label=e;for(let e of D.filter(t)){let t=document.createElement(`option`);t.value=e,t.textContent=e,n.appendChild(t)}n.children.length>0&&f.appendChild(n)}f.value=e===`3d`?`MeshInstance3D`:`Sprite2D`};k(`2d`);let A=()=>{let e=i.selection??[];for(let t of f.querySelectorAll(`option`)){let n=structuredClone(i.working),r=n.root;if(!n.root)n.root={name:`__probe`,type:t.value};else{for(let t of e)r=r?.children?.[t];if(!r)continue;r.children||=[],r.children.push({name:`__probe`,type:t.value})}t.disabled=E.validate(n)!==null}};f.addEventListener(`mousedown`,A),f.addEventListener(`focus`,A);let ee=!1,te=()=>{if(!y)return;EF(a,i),Uj($(`#asset-tree`),i),o.textContent=``,Wj(o,i,j)||yP(o,i,{modelRefs:()=>gI(i,`model`),animationsForSelection:()=>i.selection?E.modelAnimationsAt(i.selection):[],bonesForSelection:e=>i.selection?E.boneNamesAt(i.selection,e):[],assetRefs:e=>_I(i,e),addAsset:(e,t)=>vI(i,e,t),confirm:j,paint:{active:()=>x.on,brush:()=>x.brush,toggle:()=>{x.on=!x.on,T(),te()},setBrush:e=>{x.brush=e,te()}}}),k(i.working.dimension??`2d`),$(`#hints`).hidden=(i.working.dimension??`2d`)===`3d`,$(`#hints-3d`).hidden=(i.working.dimension??`2d`)!==`3d`,E.setSelection(i.selection,i.extra),T();let e=i.pendingLivePatch;if(i.pendingLivePatch=null,!E.playing)if(e&&E.patchProp(i.working,e.path,e.key,e.value))u.hidden=!0;else{let e=E.apply(i.working);u.hidden=e===null,e!==null&&b(e)}s.disabled=!i.dirty||!i.working.root,s.title=i.working.root?``:`Add a root node before saving`,c.disabled=!i.canUndo,i.dirty!==ee&&(ee=i.dirty,dM.change(i.dirty))};i.onChange(te),i.validator=e=>E.validate(e),i.onError=b;let ne=(e,t,n,r)=>{let a=i.nodeAt(e);a&&i.mutate(()=>{a.props||={},n===r?(delete a.props[t],Object.keys(a.props).length===0&&delete a.props):a.props[t]=n},{path:e,key:t,value:n})},re=(e,t,n,r)=>{let a=i.nodeAt(e);a&&i.mutate(()=>{a.props||={},JSON.stringify(n)===JSON.stringify(r)?(delete a.props[t],Object.keys(a.props).length===0&&delete a.props):a.props[t]=n},{path:e,key:t,value:n})},ie=async(t,n,r)=>{E.playing&&E.stop();let a=await wj(t);v=t,g=n,_=r,y=!0,$(`#file-path`).textContent=t??n,$(`#file-chip`).title=`input: ${n}\noutput: ${r}`,p.hidden=!0,i.reset(a),e.mode===`project`&&dM.open(n,r)},ae=async()=>{let e=await xj();if(m.textContent=``,e.length===0){let e=document.createElement(`div`);e.className=`tree-row`,e.textContent=`no *.scene.json found — create one below`,m.appendChild(e)}for(let t of e){let e=document.createElement(`div`);e.className=`tree-row`,e.textContent=t.rel,e.addEventListener(`click`,()=>{ie(t.rel,t.abs,t.abs).catch(e=>b(e instanceof Error?e.message:String(e)))}),m.appendChild(e)}p.hidden=!1},oe=()=>{p.hidden=!0};if($(`#picker-close`).addEventListener(`click`,oe),p.addEventListener(`pointerdown`,e=>{e.target===p&&oe()}),$(`#picker-create`).addEventListener(`click`,()=>{(async()=>{let e=$(`#picker-path`).value.trim();if(e)try{let t=await Sj(e.endsWith(`.scene.json`)?e:`${e}.scene.json`);await ie(t.rel,t.abs,t.abs)}catch(e){b(e instanceof Error?e.message:String(e))}})()}),e.mode===`project`){h.hidden=!1,h.addEventListener(`click`,()=>void ae());let e=await xj(),t=e.length===1?e[0]:void 0;t?await ie(t.rel,t.abs,t.abs):await ae()}else await ie(void 0,e.input,e.output);$(`#add-btn`).addEventListener(`click`,()=>{let e=i.selection??[],t=f.value,n=i.insertNode({name:t,type:t},e);n&&i.select(n)});let se=$(`#generate`);aP(i),$(`#generate-btn`).addEventListener(`click`,()=>rP(i));let ce=$(`#confirm`),le=e=>{if(i.selection===null&&e.length===0){b(`The scene itself cannot be deleted — it IS the file.`);return}if(e.length===0){let e=i.working.root;if(!e)return;let t=hI(e);j(`This deletes the ROOT '${String(e.name??``)}'${t>0?` AND its ${t} descendant node${t===1?``:`s`}`:``} — the scene goes empty, and the next node you add becomes the new root.`,`delete root`,()=>i.deleteRoot());return}let t=e[0]?.slice(0,-1)??[],n=i.findRemovalReferences(e);if(n.length===0){let n=e.reduce((e,t)=>{let n=i.nodeAt(t);return e+(n?hI(n):0)},0);if(n>0){j(`This deletes ${e.length>1?`${e.length} nodes`:`'${String(i.nodeAt(e[0]??[])?.name??``)}'`} AND ${n} descendant node${n===1?``:`s`}.`,`delete ${e.length+n} nodes`,()=>{i.removeNodes(e)&&i.select(t)});return}i.removeNodes(e)&&i.select(t);return}$(`#confirm-text`).textContent=`${n.length} reference${n.length>1?`s`:``} still point at the node(s) you are deleting. Unlink them and delete, or cancel.`;let r=$(`#confirm-list`);r.textContent=``;for(let e of n){let t=document.createElement(`div`);t.textContent=`${e.kind===`uid`?`◆ uid`:`⇄ connection`} ${e.where}`,r.appendChild(t)}$(`#confirm-title`).textContent=`still referenced`,$(`#confirm-delete`).textContent=`unlink & delete`,ce.hidden=!1,ue={selections:e,parentOfFirst:t}},ue=null,de=null;function j(e,t,n){$(`#confirm-title`).textContent=`are you sure?`,$(`#confirm-text`).textContent=e,$(`#confirm-list`).textContent=``,$(`#confirm-delete`).textContent=t,de=n,ce.hidden=!1}function fe(){ce.hidden=!0,ue=null,de=null}$(`#confirm-close`).addEventListener(`click`,fe),$(`#confirm-cancel`).addEventListener(`click`,fe),ce.addEventListener(`pointerdown`,e=>{e.target===ce&&fe()}),$(`#confirm-delete`).addEventListener(`click`,()=>{if(de){de(),fe();return}ue&&i.removeNodesUnlinking(ue.selections)&&i.select(ue.parentOfFirst),fe()}),xF(le),$(`#asset-add-btn`).addEventListener(`click`,e=>{e.stopPropagation(),i.startAddingAsset()}),$(`#group-add-btn`).addEventListener(`click`,e=>{e.stopPropagation(),i.startAddingGroup()});for(let e of document.querySelectorAll(`.section-toggle`)){let t=e.dataset.section??``,n=document.querySelector(`[data-body="${t}"]`),r=`incanto-editor-section-${t}`,i=t=>{e.classList.toggle(`collapsed`,t),n&&(n.hidden=t),localStorage.setItem(r,t?`1`:``)};i(localStorage.getItem(r)===`1`),e.addEventListener(`click`,()=>i(!e.classList.contains(`collapsed`)))}$(`#delete-btn`).addEventListener(`click`,()=>{le(i.allSelections().filter(e=>e.length>0))}),l.addEventListener(`click`,()=>{if(E.playing){E.stop(),te();return}E.play(i.working).then(e=>{e&&b(e)})});for(let e of[`move`,`rotate`,`scale`])$(`#tool-${e}`).addEventListener(`click`,()=>E.setMode(e));E.setMode(`move`);let pe=$(`#tool-colliders`),M=`incanto-editor-show-colliders`,me=e=>{E.showColliders=e,pe.classList.toggle(`active`,e),localStorage.setItem(M,e?``:`0`)};me(localStorage.getItem(M)!==`0`),pe.addEventListener(`click`,()=>me(!E.showColliders));let ge=$(`#hints-dock`),_e=`incanto-editor-hints-open`;ge.classList.toggle(`open`,localStorage.getItem(_e)===`1`),$(`#hints-toggle`).addEventListener(`click`,()=>{let e=ge.classList.toggle(`open`);localStorage.setItem(_e,e?`1`:``)}),$(`#fit-btn`).addEventListener(`click`,()=>E.zoomToFit()),$(`#gameview-btn`).addEventListener(`click`,()=>E.gameView()),s.addEventListener(`click`,()=>{(async()=>{try{await Tj(i.working,v),i.markSaved(),dM.save(g,_,i.working)}catch(e){b(e instanceof Error?e.message:String(e))}})()}),c.addEventListener(`click`,()=>i.undo()),window.addEventListener(`keydown`,e=>{if(e.key===`Escape`&&E.cancelActiveDrag(),e.key===`Escape`&&!$(`#docs`).hidden){yM();return}if(e.key===`Escape`&&!ce.hidden){fe();return}if(e.key===`Escape`&&!se.hidden){iP();return}if(e.key===`Escape`&&!p.hidden){oe();return}if(e.key===`Escape`&&E.playing){E.stop(),te();return}if(E.playing)return;let t=e.target.matches(`input, textarea, select`);(e.metaKey||e.ctrlKey)&&e.key===`z`?(e.preventDefault(),i.undo()):(e.metaKey||e.ctrlKey)&&e.key===`s`?(e.preventDefault(),s.disabled||s.click()):!t&&e.code===`KeyF`?E.zoomToFit():!t&&(e.code===`Digit0`||e.code===`Numpad0`)?E.gameView():!t&&e.code===`KeyW`?E.setMode(`move`):!t&&e.code===`KeyE`?E.setMode(`rotate`):!t&&e.code===`KeyR`&&E.setMode(`scale`)}),te(),dM.ready(g,_,e.version)}function hI(e){let t=0;for(let n of e.children??[])t+=1+hI(n);return t}function gI(e,t){let n=e.working.assets;return n?Object.entries(n).filter(([,e])=>e?.type===t).map(([e])=>`$${e}`):[]}function _I(e,t){let n=e.working.assets;return n?Object.entries(n).filter(([,e])=>!t||e?.type!==void 0&&t.includes(e.type)).map(([e])=>`$${e}`):[]}function vI(e,t,n){let r=e.working.assets??{};for(let[e,t]of Object.entries(r))if(t?.url===n.url)return`$${e}`;let i=t;for(let e=2;i in r;e++)i=`${t}-${e}`;return e.mutate(()=>{e.working.assets||(e.working.assets={}),e.working.assets[i]=n}),`$${i}`}mI().catch(e=>{let t=document.querySelector(`#error-banner`);t&&(t.hidden=!1,t.textContent=e instanceof Error?e.message:String(e))});export{Dh as t};
|