flag-cloth 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -71,6 +71,7 @@ const flag = createFlagCloth({
71
71
  },
72
72
  interaction: {
73
73
  enabled: true,
74
+ touchAction: "pan-y",
74
75
  dragRadius: 1,
75
76
  dragStiffness: 0.9,
76
77
  },
@@ -265,13 +266,14 @@ Stiffness is converted to an iteration-independent correction so changing iterat
265
266
  | Option | Default | Meaning |
266
267
  | --- | --- | --- |
267
268
  | `enabled` | `true` | Enables mouse, pen, and touch dragging. |
269
+ | `touchAction` | `"pan-y"` | Preserves vertical page scrolling while horizontal touch gestures drag the cloth. Use `"none"` for unrestricted two-axis touch dragging. |
268
270
  | `dragRadius` | `1` | Grid-space radius of particles affected around the grabbed point. |
269
271
  | `dragStiffness` | `0.9` | Strength of the temporary positional constraint. |
270
272
  | `maxDragDistance` | `4` | Maximum distance from the original grab position; `0` is unlimited. |
271
273
  | `allowPinned` | `false` | Allows temporarily moving attached particles. |
272
274
  | `releaseImpulse` | `[0, 0, 0]` | Optional velocity impulse added on release. |
273
275
 
274
- Pointer selection uses the renderer's projected indexed triangles. The hit triangle's nearest barycentric vertex becomes the selected particle, and neighboring particles inside `dragRadius` receive weighted temporary constraints. The target moves on a camera-facing plane. Pointer capture keeps the drag active outside the canvas; release restores free motion while retaining the Verlet velocity naturally.
276
+ Pointer selection uses the renderer's projected indexed triangles. The hit triangle's nearest barycentric vertex becomes the selected particle, and neighboring particles inside `dragRadius` receive weighted temporary constraints. The target moves on a camera-facing plane. Pointer capture keeps the drag active outside the canvas; release restores free motion while retaining the Verlet velocity naturally. The default `touchAction: "pan-y"` lets mobile users scroll vertically through an embedded canvas; use `"pan-x"`, `"none"`, or `"auto"` when a different browser gesture policy fits the surrounding layout.
275
277
 
276
278
  ### Renderer and material
277
279
 
@@ -1,4 +1,5 @@
1
1
  type Vector3Tuple = readonly [number, number, number];
2
+ type InteractionTouchAction = "pan-y" | "pan-x" | "none" | "auto";
2
3
  type EdgeAttachment = "left" | "right" | "top" | "bottom";
3
4
  type CornerAttachment = "top-left" | "top-right" | "bottom-left" | "bottom-right";
4
5
  /** Integer coordinates in the simulation grid, where `[0, 0]` is the top-left particle. */
@@ -63,6 +64,12 @@ interface SimulationOptions {
63
64
  interface InteractionOptions {
64
65
  /** Enables Pointer Event dragging. @default true */
65
66
  enabled: boolean;
67
+ /**
68
+ * Browser gesture policy applied to the canvas. `pan-y` preserves vertical page scrolling
69
+ * while horizontal gestures drag the cloth. Use `none` for unrestricted two-axis touch dragging.
70
+ * @default "pan-y"
71
+ */
72
+ touchAction: InteractionTouchAction;
66
73
  /** Grid-space radius around the selected particle. @default 1 */
67
74
  dragRadius: number;
68
75
  /** Strength of the temporary drag constraint. @default 0.9 */
@@ -448,4 +455,4 @@ declare class FlagClothInstance {
448
455
  }
449
456
  declare function createFlagCloth(options: FlagClothOptions): FlagClothInstance;
450
457
 
451
- export { type AdvancedOptions as A, type CameraOptions as C, type DebugOptions as D, type EdgeAttachment as E, FlagClothInstance as F, type GridPoint as G, type InteractionOptions as I, type LightingOptions as L, type MutableFlagRendererOptions as M, type PartialEdgeAttachment as P, type RendererPreset as R, type SimulationOptions as S, type TextureSource as T, type Vector3Tuple as V, WebGLClothRenderer as W, type Attachment as a, type ClothMaterialOptions as b, ClothSimulation as c, type ClothSimulationConfig as d, type CornerAttachment as e, type FlagClothOptions as f, type FlagClothStats as g, type FlagClothUpdateOptions as h, type FlagRendererOptions as i, type FlagSegments as j, type PointAttachment as k, type VisibilityOptions as l, type WindOptions as m, createFlagCloth as n };
458
+ export { type AdvancedOptions as A, type CameraOptions as C, type DebugOptions as D, type EdgeAttachment as E, FlagClothInstance as F, type GridPoint as G, type InteractionOptions as I, type LightingOptions as L, type MutableFlagRendererOptions as M, type PartialEdgeAttachment as P, type RendererPreset as R, type SimulationOptions as S, type TextureSource as T, type Vector3Tuple as V, WebGLClothRenderer as W, type Attachment as a, type ClothMaterialOptions as b, ClothSimulation as c, type ClothSimulationConfig as d, type CornerAttachment as e, type FlagClothOptions as f, type FlagClothStats as g, type FlagClothUpdateOptions as h, type FlagRendererOptions as i, type FlagSegments as j, type InteractionTouchAction as k, type PointAttachment as l, type VisibilityOptions as m, type WindOptions as n, createFlagCloth as o };
@@ -75,10 +75,10 @@ void main() {
75
75
  shaded += vec3(highlight);
76
76
  outputColor = vec4(clamp(shaded, 0.0, 1.0), albedo.a);
77
77
  }
78
- `,N=class{constructor(t,e,s,i,n,o,l){r(this,"canvas",t);r(this,"context",e);r(this,"projectedPositions");r(this,"projectedDepths");r(this,"simulation");r(this,"rendererOptions");r(this,"material");r(this,"lighting");r(this,"camera");r(this,"textureSource",null);r(this,"vertexNormals");r(this,"textureCoordinates");r(this,"indices");r(this,"cssWidth",1);r(this,"cssHeight",1);r(this,"pixelRatio",1);r(this,"focalLength",1);r(this,"cameraX",0);r(this,"cameraY",0);r(this,"cameraZ",5);r(this,"forwardX",0);r(this,"forwardY",0);r(this,"forwardZ",-1);r(this,"rightX",1);r(this,"rightY",0);r(this,"rightZ",0);r(this,"upX",0);r(this,"upY",1);r(this,"upZ",0);r(this,"lightX",0);r(this,"lightY",0);r(this,"lightZ",1);r(this,"frameNumber",0);r(this,"drawCallsValue",0);r(this,"contextLost",false);r(this,"destroyed",false);r(this,"viewMatrix",new Float32Array(16));r(this,"projectionMatrix",new Float32Array(16));r(this,"viewProjectionMatrix",new Float32Array(16));r(this,"baseColor",new Float32Array([1,1,1,1]));r(this,"shadowColor",new Float32Array([0,0,0,.3]));r(this,"backgroundColor",new Float32Array([0,0,0,0]));r(this,"program",null);r(this,"uniforms",null);r(this,"vertexArray",null);r(this,"positionBuffer",null);r(this,"normalBuffer",null);r(this,"textureCoordinateBuffer",null);r(this,"indexBuffer",null);r(this,"texture",null);r(this,"onContextLost",t=>{t.preventDefault(),this.contextLost=true;});r(this,"onContextRestored",()=>{this.destroyed||(this.contextLost=false,this.initializeResources(),this.resize(this.cssWidth,this.cssHeight,this.pixelRatio));});this.simulation=s,this.rendererOptions=i,this.material=n,this.lighting=o,this.camera=l,this.projectedPositions=new Float32Array(s.particleCount*2),this.projectedDepths=new Float32Array(s.particleCount),this.vertexNormals=new Float32Array(s.particleCount*3),this.textureCoordinates=new Float32Array(s.particleCount*2),this.indices=new Uint32Array(s.segmentsX*s.segmentsY*6),this.rebuildTopology(),this.updateCameraBasis(),this.updateLightDirection(),this.updateColors(),this.canvas.addEventListener("webglcontextlost",this.onContextLost),this.canvas.addEventListener("webglcontextrestored",this.onContextRestored),this.initializeResources();}get width(){return this.cssWidth}get height(){return this.cssHeight}get drawCalls(){return this.drawCallsValue}setSimulation(t){this.simulation=t,this.projectedPositions=new Float32Array(t.particleCount*2),this.projectedDepths=new Float32Array(t.particleCount),this.vertexNormals=new Float32Array(t.particleCount*3),this.textureCoordinates=new Float32Array(t.particleCount*2),this.indices=new Uint32Array(t.segmentsX*t.segmentsY*6),this.rebuildTopology(),this.updateCameraBasis(),this.contextLost||this.uploadTopology();}setTexture(t){this.textureSource=t,this.contextLost||this.uploadTexture();}setOptions(t,e,s,i){let n=t.textureFiltering!==this.rendererOptions.textureFiltering;this.rendererOptions=t,this.material=e,this.lighting=s,this.camera=i,this.updateCameraBasis(),this.updateLightDirection(),this.updateColors(),n&&!this.contextLost&&this.applyTextureFiltering();}resize(t,e,s){this.cssWidth=Math.max(1,t),this.cssHeight=Math.max(1,e),this.pixelRatio=Math.max(.5,s);let i=Math.max(1,Math.round(this.cssWidth*this.pixelRatio)),n=Math.max(1,Math.round(this.cssHeight*this.pixelRatio));this.canvas.width!==i&&(this.canvas.width=i),this.canvas.height!==n&&(this.canvas.height=n),this.context.viewport(0,0,i,n),this.updateCameraBasis();}render(){let t=this.context,e=this.uniforms;if(this.destroyed||this.contextLost||!this.program||!e||!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.texture)return;t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.simulation.positions);let s=Math.max(1,Math.floor(this.rendererOptions.shadingUpdateInterval));this.frameNumber%s===0&&(this.updateVertexNormals(),t.bindBuffer(t.ARRAY_BUFFER,this.normalBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.vertexNormals)),this.frameNumber+=1;let i=this.backgroundColor;t.clearColor(i[0]??0,i[1]??0,i[2]??0,this.rendererOptions.transparent?0:i[3]??1),t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT),t.useProgram(this.program),t.bindVertexArray(this.vertexArray),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.texture),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.disable(t.CULL_FACE),this.syncShaderUniforms(e),this.drawCallsValue=0,this.rendererOptions.shadows&&this.drawShadow(e),t.enable(t.DEPTH_TEST),t.depthMask(true),t.uniform1i(e.shadowPass,0),t.uniform2f(e.screenOffset,0,0),t.drawElements(t.TRIANGLES,this.indices.length,t.UNSIGNED_INT,0),this.drawCallsValue+=1,t.bindVertexArray(null);}findParticleAt(t,e){this.projectParticles();let s=-1,i=Number.POSITIVE_INFINITY;for(let n=0;n<this.indices.length;n+=3){let o=this.indices[n]??0,l=this.indices[n+1]??0,h=this.indices[n+2]??0,c=o*2,d=l*2,m=h*2,x=this.projectedPositions[c]??Number.NaN,w=this.projectedPositions[c+1]??Number.NaN,b=this.projectedPositions[d]??Number.NaN,u=this.projectedPositions[d+1]??Number.NaN,y=this.projectedPositions[m]??Number.NaN,g=this.projectedPositions[m+1]??Number.NaN;if(!Number.isFinite(x+w+b+u+y+g))continue;let T=(u-g)*(x-y)+(y-b)*(w-g);if(Math.abs(T)<1e-8)continue;let f=((u-g)*(t-y)+(y-b)*(e-g))/T,v=((g-w)*(t-y)+(x-y)*(e-g))/T,p=1-f-v;if(f<-1e-3||v<-1e-3||p<-1e-3)continue;let C=f*(this.projectedDepths[o]??0)+v*(this.projectedDepths[l]??0)+p*(this.projectedDepths[h]??0);C>=i||(i=C,f>=v&&f>=p?s=o:s=v>=p?l:h);}return s}unprojectToPlane(t,e,s,i,n,o){let l=(t-this.cssWidth*.5)/this.focalLength,h=-(e-this.cssHeight*.5)/this.focalLength,c=this.forwardX+this.rightX*l+this.upX*h,d=this.forwardY+this.rightY*l+this.upY*h,m=this.forwardZ+this.rightZ*l+this.upZ*h,x=Math.hypot(c,d,m)||1;c/=x,d/=x,m/=x;let w=c*this.forwardX+d*this.forwardY+m*this.forwardZ;if(Math.abs(w)<1e-7)return false;let u=((s-this.cameraX)*this.forwardX+(i-this.cameraY)*this.forwardY+(n-this.cameraZ)*this.forwardZ)/w;return u<=0?false:(o[0]=this.cameraX+c*u,o[1]=this.cameraY+d*u,o[2]=this.cameraZ+m*u,true)}destroy(){this.destroyed||(this.destroyed=true,this.canvas.removeEventListener("webglcontextlost",this.onContextLost),this.canvas.removeEventListener("webglcontextrestored",this.onContextRestored),this.deleteResources(),this.context.isContextLost()||(this.context.clearColor(0,0,0,0),this.context.clear(this.context.COLOR_BUFFER_BIT|this.context.DEPTH_BUFFER_BIT)));}initializeResources(){let t=this.context,e=rt(t,t.VERTEX_SHADER,Dt),s=rt(t,t.FRAGMENT_SHADER,Mt),i=t.createProgram();if(!i)throw new Error("Unable to create the cloth shader program.");if(t.attachShader(i,e),t.attachShader(i,s),t.linkProgram(i),t.deleteShader(e),t.deleteShader(s),!t.getProgramParameter(i,t.LINK_STATUS)){let n=t.getProgramInfoLog(i)||"Unknown link error.";throw t.deleteProgram(i),new Error(`Unable to link the cloth shader: ${n}`)}if(this.program=i,this.uniforms={viewProjection:A(t,i,"uViewProjection"),screenOffset:A(t,i,"uScreenOffset"),texture:A(t,i,"uTexture"),hasTexture:A(t,i,"uHasTexture"),shadowPass:A(t,i,"uShadowPass"),baseColor:A(t,i,"uBaseColor"),shadowColor:A(t,i,"uShadowColor"),lightDirection:A(t,i,"uLightDirection"),cameraPosition:A(t,i,"uCameraPosition"),lightingEnabled:A(t,i,"uLightingEnabled"),lightIntensity:A(t,i,"uLightIntensity"),ambient:A(t,i,"uAmbient"),diffuse:A(t,i,"uDiffuse"),specular:A(t,i,"uSpecular"),shininess:A(t,i,"uShininess"),foldContrast:A(t,i,"uFoldContrast")},this.vertexArray=t.createVertexArray(),this.positionBuffer=t.createBuffer(),this.normalBuffer=t.createBuffer(),this.textureCoordinateBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),this.texture=t.createTexture(),!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.textureCoordinateBuffer||!this.indexBuffer||!this.texture)throw this.deleteResources(),new Error("Unable to allocate WebGL cloth resources.");t.useProgram(i),t.uniform1i(this.uniforms.texture,0),this.uploadTopology(),this.uploadTexture();}uploadTopology(){let t=this.context;!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.textureCoordinateBuffer||!this.indexBuffer||(this.updateVertexNormals(),t.bindVertexArray(this.vertexArray),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.simulation.positions,t.DYNAMIC_DRAW),t.enableVertexAttribArray(0),t.vertexAttribPointer(0,3,t.FLOAT,false,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.normalBuffer),t.bufferData(t.ARRAY_BUFFER,this.vertexNormals,t.DYNAMIC_DRAW),t.enableVertexAttribArray(1),t.vertexAttribPointer(1,3,t.FLOAT,false,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.textureCoordinateBuffer),t.bufferData(t.ARRAY_BUFFER,this.textureCoordinates,t.STATIC_DRAW),t.enableVertexAttribArray(2),t.vertexAttribPointer(2,2,t.FLOAT,false,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.indices,t.STATIC_DRAW),t.bindVertexArray(null));}uploadTexture(){let t=this.context;this.texture&&(t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,0),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,0),this.textureSource?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.textureSource):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,1,1,0,t.RGBA,t.UNSIGNED_BYTE,Ot),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),this.applyTextureFiltering());}applyTextureFiltering(){let t=this.context;this.texture&&(t.bindTexture(t.TEXTURE_2D,this.texture),this.rendererOptions.textureFiltering==="nearest"?(t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST)):(t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR_MIPMAP_LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.generateMipmap(t.TEXTURE_2D)));}rebuildTopology(){let t=0;for(let s=0;s<this.simulation.rows;s+=1)for(let i=0;i<this.simulation.columns;i+=1){let n=t*2;this.textureCoordinates[n]=i/this.simulation.segmentsX,this.textureCoordinates[n+1]=s/this.simulation.segmentsY,t+=1;}let e=0;for(let s=0;s<this.simulation.segmentsY;s+=1){let i=s*this.simulation.columns;for(let n=0;n<this.simulation.segmentsX;n+=1){let o=i+n,l=o+1,h=o+this.simulation.columns,c=h+1;this.indices[e]=o,this.indices[e+1]=h,this.indices[e+2]=l,this.indices[e+3]=l,this.indices[e+4]=h,this.indices[e+5]=c,e+=6;}}}updateVertexNormals(){let t=this.simulation.positions,e=this.vertexNormals;e.fill(0);for(let s=0;s<this.indices.length;s+=3){let i=(this.indices[s]??0)*3,n=(this.indices[s+1]??0)*3,o=(this.indices[s+2]??0)*3,l=(t[n]??0)-(t[i]??0),h=(t[n+1]??0)-(t[i+1]??0),c=(t[n+2]??0)-(t[i+2]??0),d=(t[o]??0)-(t[i]??0),m=(t[o+1]??0)-(t[i+1]??0),x=(t[o+2]??0)-(t[i+2]??0),w=h*x-c*m,b=c*d-l*x,u=l*m-h*d;k(e,i,w,b,u),k(e,n,w,b,u),k(e,o,w,b,u);}for(let s=0;s<this.simulation.particleCount;s+=1){let i=s*3,n=e[i]??0,o=e[i+1]??0,l=e[i+2]??1,h=Math.hypot(n,o,l)||1;e[i]=n/h,e[i+1]=o/h,e[i+2]=l/h;}}projectParticles(){let t=this.simulation.positions;for(let e=0;e<this.simulation.particleCount;e+=1){let s=e*3,i=(t[s]??0)-this.cameraX,n=(t[s+1]??0)-this.cameraY,o=(t[s+2]??0)-this.cameraZ,l=i*this.rightX+n*this.rightY+o*this.rightZ,h=i*this.upX+n*this.upY+o*this.upZ,c=i*this.forwardX+n*this.forwardY+o*this.forwardZ,d=e*2;if(c<=this.camera.near||c>=this.camera.far)this.projectedPositions[d]=Number.NaN,this.projectedPositions[d+1]=Number.NaN;else {let m=this.focalLength/c;this.projectedPositions[d]=this.cssWidth*.5+l*m,this.projectedPositions[d+1]=this.cssHeight*.5-h*m;}this.projectedDepths[e]=c;}}drawShadow(t){let e=this.context,s=this.shadowColor,i=I.length/2,n=Math.max(0,this.material.shadowBlur)*.36;e.disable(e.DEPTH_TEST),e.depthMask(false),e.uniform1i(t.shadowPass,1),e.uniform4f(t.shadowColor,s[0]??0,s[1]??0,s[2]??0,(s[3]??0)/i);for(let o=0;o<I.length;o+=2){let l=this.material.shadowOffsetX+(I[o]??0)*n,h=this.material.shadowOffsetY+(I[o+1]??0)*n;e.uniform2f(t.screenOffset,l*2/this.cssWidth,-h*2/this.cssHeight),e.drawElements(e.TRIANGLES,this.indices.length,e.UNSIGNED_INT,0),this.drawCallsValue+=1;}}syncShaderUniforms(t){let e=this.context,s=this.baseColor,i=this.shadowColor;e.uniformMatrix4fv(t.viewProjection,false,this.viewProjectionMatrix),e.uniform1i(t.hasTexture,this.textureSource?1:0),e.uniform4f(t.baseColor,s[0]??1,s[1]??1,s[2]??1,s[3]??1),e.uniform4f(t.shadowColor,i[0]??0,i[1]??0,i[2]??0,i[3]??0),e.uniform3f(t.lightDirection,this.lightX,this.lightY,this.lightZ),e.uniform3f(t.cameraPosition,this.cameraX,this.cameraY,this.cameraZ),e.uniform1i(t.lightingEnabled,this.lighting.enabled?1:0),e.uniform1f(t.lightIntensity,this.lighting.intensity),e.uniform1f(t.ambient,this.material.ambient),e.uniform1f(t.diffuse,this.material.diffuse),e.uniform1f(t.specular,this.rendererOptions.preset==="quality"?this.material.specular:0),e.uniform1f(t.shininess,this.material.shininess),e.uniform1f(t.foldContrast,this.material.foldContrast);}updateCameraBasis(){let t=this.camera.position;if(t)this.cameraX=t[0],this.cameraY=t[1],this.cameraZ=t[2];else {let d=Math.max(this.simulation.width,this.simulation.height)*.65/Math.tan(this.camera.fov*Math.PI/360);this.cameraX=0,this.cameraY=0,this.cameraZ=d;}let e=this.camera.lookAt[0]-this.cameraX,s=this.camera.lookAt[1]-this.cameraY,i=this.camera.lookAt[2]-this.cameraZ,n=Math.hypot(e,s,i)||1;e/=n,s/=n,i/=n,this.forwardX=e,this.forwardY=s,this.forwardZ=i;let o=-i,l=0,h=e,c=Math.hypot(o,l,h);c<1e-7&&(o=1,l=0,h=0,c=1),this.rightX=o/c,this.rightY=l/c,this.rightZ=h/c,this.upX=this.rightY*i-this.rightZ*s,this.upY=this.rightZ*e-this.rightX*i,this.upZ=this.rightX*s-this.rightY*e,this.focalLength=this.cssHeight/(2*Math.tan(this.camera.fov*Math.PI/360)),this.updateViewProjection();}updateViewProjection(){let t=this.viewMatrix;t[0]=this.rightX,t[1]=this.upX,t[2]=-this.forwardX,t[3]=0,t[4]=this.rightY,t[5]=this.upY,t[6]=-this.forwardY,t[7]=0,t[8]=this.rightZ,t[9]=this.upZ,t[10]=-this.forwardZ,t[11]=0,t[12]=-(this.rightX*this.cameraX+this.rightY*this.cameraY+this.rightZ*this.cameraZ),t[13]=-(this.upX*this.cameraX+this.upY*this.cameraY+this.upZ*this.cameraZ),t[14]=this.forwardX*this.cameraX+this.forwardY*this.cameraY+this.forwardZ*this.cameraZ,t[15]=1;let e=this.projectionMatrix;e.fill(0);let s=1/Math.tan(this.camera.fov*Math.PI/360),i=this.cssWidth/this.cssHeight,n=Math.max(1e-4,this.camera.near),o=Math.max(n+1e-4,this.camera.far);e[0]=s/i,e[5]=s,e[10]=(o+n)/(n-o),e[11]=-1,e[14]=2*o*n/(n-o),It(this.viewProjectionMatrix,e,t);}updateLightDirection(){let t=this.lighting.direction,e=Math.hypot(t[0],t[1],t[2])||1;this.lightX=t[0]/e,this.lightY=t[1]/e,this.lightZ=t[2]/e;}updateColors(){this.baseColor=q(this.material.baseColor,[1,1,1,1]),this.shadowColor=q(this.material.shadowColor,[0,0,0,.3]),this.backgroundColor=q(this.rendererOptions.backgroundColor,[0,0,0,0]);}deleteResources(){let t=this.context;this.texture&&t.deleteTexture(this.texture),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.textureCoordinateBuffer&&t.deleteBuffer(this.textureCoordinateBuffer),this.normalBuffer&&t.deleteBuffer(this.normalBuffer),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.vertexArray&&t.deleteVertexArray(this.vertexArray),this.program&&t.deleteProgram(this.program),this.texture=null,this.indexBuffer=null,this.textureCoordinateBuffer=null,this.normalBuffer=null,this.positionBuffer=null,this.vertexArray=null,this.uniforms=null,this.program=null;}};function rt(a,t,e){let s=a.createShader(t);if(!s)throw new Error("Unable to create a cloth shader.");if(a.shaderSource(s,e),a.compileShader(s),!a.getShaderParameter(s,a.COMPILE_STATUS)){let i=a.getShaderInfoLog(s)||"Unknown compilation error.";throw a.deleteShader(s),new Error(`Unable to compile the cloth shader: ${i}`)}return s}function A(a,t,e){let s=a.getUniformLocation(t,e);if(!s)throw new Error(`The cloth shader is missing uniform ${e}.`);return s}function k(a,t,e,s,i){a[t]=(a[t]??0)+e,a[t+1]=(a[t+1]??0)+s,a[t+2]=(a[t+2]??0)+i;}function It(a,t,e){for(let s=0;s<4;s+=1){let i=s*4,n=e[i]??0,o=e[i+1]??0,l=e[i+2]??0,h=e[i+3]??0;a[i]=(t[0]??0)*n+(t[4]??0)*o+(t[8]??0)*l+(t[12]??0)*h,a[i+1]=(t[1]??0)*n+(t[5]??0)*o+(t[9]??0)*l+(t[13]??0)*h,a[i+2]=(t[2]??0)*n+(t[6]??0)*o+(t[10]??0)*l+(t[14]??0)*h,a[i+3]=(t[3]??0)*n+(t[7]??0)*o+(t[11]??0)*l+(t[15]??0)*h;}}function q(a,t){let e=new Float32Array(t),s=a.trim().toLowerCase();if(s==="transparent")return new Float32Array([0,0,0,0]);if(s==="black")return new Float32Array([0,0,0,1]);if(s==="white")return new Float32Array([1,1,1,1]);if(s.startsWith("#")){let o=s.slice(1);if(o.length===3||o.length===4)return e[0]=Number.parseInt(o.charAt(0)+o.charAt(0),16)/255,e[1]=Number.parseInt(o.charAt(1)+o.charAt(1),16)/255,e[2]=Number.parseInt(o.charAt(2)+o.charAt(2),16)/255,e[3]=o.length===4?Number.parseInt(o.charAt(3)+o.charAt(3),16)/255:1,e;if(o.length===6||o.length===8)return e[0]=Number.parseInt(o.slice(0,2),16)/255,e[1]=Number.parseInt(o.slice(2,4),16)/255,e[2]=Number.parseInt(o.slice(4,6),16)/255,e[3]=o.length===8?Number.parseInt(o.slice(6,8),16)/255:1,e}let i=s.match(/^rgba?\(([^)]+)\)$/);if(!i?.[1])return e;let n=i[1].split(",");return n.length<3||(e[0]=$(n[0]??"0"),e[1]=$(n[1]??"0"),e[2]=$(n[2]??"0"),e[3]=n[3]===void 0?1:Math.min(1,Math.max(0,Number(n[3])))),e}function $(a){let t=a.trim(),e=Number.parseFloat(t);return Number.isFinite(e)?t.endsWith("%")?Math.min(1,Math.max(0,e/100)):Math.min(1,Math.max(0,e/255)):0}function nt(a,t,e,s){let i=a+1,n=t+1,o=a*n+t*i,l=a*t*2,h=Math.max(0,a-1)*n+Math.max(0,t-1)*i,c=o+l+h,d=new Uint32Array(c),m=new Uint32Array(c),x=new Float32Array(c),w=new Uint8Array(c),b=e/a,u=s/t,y=Math.hypot(b,u),g=0,T=(f,v,p,C)=>{d[g]=f,m[g]=v,x[g]=p,w[g]=C,g+=1;};for(let f=0;f<n;f+=1){let v=f*i;for(let p=0;p<a;p+=1)T(v+p,v+p+1,b,0);}for(let f=0;f<t;f+=1){let v=f*i;for(let p=0;p<i;p+=1)T(v+p,v+i+p,u,0);}for(let f=0;f<t;f+=1){let v=f*i;for(let p=0;p<a;p+=1){let C=v+p,L=C+i;T(C,L+1,y,1),T(C+1,L,y,1);}}for(let f=0;f<n;f+=1){let v=f*i;for(let p=0;p<a-1;p+=1)T(v+p,v+p+2,b*2,2);}for(let f=0;f<t-1;f+=1){let v=f*i;for(let p=0;p<i;p+=1)T(v+p,v+i*2+p,u*2,2);}return {first:d,second:m,restLength:x,kind:w,count:c}}function P(a,t,e){let s=Math.imul(a,374761393)+Math.imul(t,668265263)+Math.imul(e,2147483647);return s=Math.imul(s^s>>>13,1274126177),((s^s>>>16)>>>0)/4294967295}function K(a){return a*a*(3-2*a)}function S(a,t,e){return a+(t-a)*e}function J(a,t,e){let s=Math.floor(a),i=Math.floor(t),n=Math.floor(e),o=K(a-s),l=K(t-i),h=K(e-n),c=S(P(s,i,n),P(s+1,i,n),o),d=S(P(s,i+1,n),P(s+1,i+1,n),o),m=S(P(s,i,n+1),P(s+1,i,n+1),o),x=S(P(s,i+1,n+1),P(s+1,i+1,n+1),o);return S(S(c,d,l),S(m,x,l),h)}var U=class{constructor(t){r(this,"width");r(this,"height");r(this,"segmentsX");r(this,"segmentsY");r(this,"columns");r(this,"rows");r(this,"particleCount");r(this,"positions");r(this,"previousPositions");r(this,"initialPositions");r(this,"forces");r(this,"inverseMass");r(this,"pinned");r(this,"constraints");r(this,"simulation");r(this,"wind");r(this,"windDirectionX",1);r(this,"windDirectionY",0);r(this,"windDirectionZ",0);r(this,"elapsedTime",0);r(this,"dragWeights");r(this,"dragParticles",new Uint32Array(0));r(this,"dragOffsets",new Float32Array(0));r(this,"dragParticleCount",0);r(this,"dragTargetX",0);r(this,"dragTargetY",0);r(this,"dragTargetZ",0);r(this,"dragStiffness",0);r(this,"dragAllowsPinned",false);if(t.width<=0||t.height<=0)throw new RangeError("Cloth width and height must be greater than zero.");if(!Number.isInteger(t.segmentsX)||!Number.isInteger(t.segmentsY))throw new TypeError("Cloth segment counts must be integers.");if(t.segmentsX<1||t.segmentsY<1)throw new RangeError("Cloth segment counts must be at least one.");this.width=t.width,this.height=t.height,this.segmentsX=t.segmentsX,this.segmentsY=t.segmentsY,this.columns=t.segmentsX+1,this.rows=t.segmentsY+1,this.particleCount=this.columns*this.rows,this.positions=new Float32Array(this.particleCount*3),this.previousPositions=new Float32Array(this.particleCount*3),this.initialPositions=new Float32Array(this.particleCount*3),this.forces=new Float32Array(this.particleCount*3),this.inverseMass=new Float32Array(this.particleCount),this.pinned=new Uint8Array(this.particleCount),this.dragWeights=new Float32Array(this.particleCount),this.constraints=nt(t.segmentsX,t.segmentsY,t.width,t.height),this.simulation={...t.simulation},this.wind={...t.wind},this.initializeParticles(),this.setAttachment(t.attachment),this.updateWindDirection();}get constraintCount(){return this.constraints.count}get time(){return this.elapsedTime}particleIndex(t,e){return t<0||t>=this.columns||e<0||e>=this.rows?-1:e*this.columns+t}isPinned(t){return this.pinned[t]===1}addForce(t,e){if(t<0||t>=this.particleCount)return;let s=t*3;this.forces[s]=(this.forces[s]??0)+e[0],this.forces[s+1]=(this.forces[s+1]??0)+e[1],this.forces[s+2]=(this.forces[s+2]??0)+e[2];}setWind(t){this.wind={...this.wind,...t},t.direction&&this.updateWindDirection();}setSimulationOptions(t){this.simulation={...this.simulation,...t},t.mass!==void 0&&this.updateInverseMass();}setAttachment(t){this.pinned.fill(0);let e=(s,i)=>{let n=this.particleIndex(s,i);n>=0&&(this.pinned[n]=1);};if(t==="left")this.pinEdge("left",1,0);else if(t==="right")this.pinEdge("right",1,0);else if(t==="top")this.pinEdge("top",1,0);else if(t==="bottom")this.pinEdge("bottom",1,0);else if(t==="top-left")e(0,0);else if(t==="top-right")e(this.segmentsX,0);else if(t==="bottom-left")e(0,this.segmentsY);else if(t==="bottom-right")e(this.segmentsX,this.segmentsY);else if(typeof t=="object"&&"edge"in t)this.pinEdge(t.edge,t.every??1,t.offset??0);else if(typeof t=="object"&&"points"in t)for(let s=0;s<t.points.length;s+=1){let i=t.points[s];i&&e(Math.round(i[0]),Math.round(i[1]));}this.updateInverseMass(),this.enforcePins();}beginDrag(t,e,s,i){if(t<0||t>=this.particleCount||this.isPinned(t)&&!i)return false;this.clearDragWeights();let n=t%this.columns,o=Math.floor(t/this.columns),l=Math.max(0,e),h=Math.ceil(l),c=0;for(let u=o-h;u<=o+h;u+=1)for(let y=n-h;y<=n+h;y+=1){let g=this.particleIndex(y,u);if(g<0||this.isPinned(g)&&!i)continue;(Math.hypot(y-n,u-o)<=l||g===t)&&(c+=1);}this.dragParticles=new Uint32Array(c),this.dragOffsets=new Float32Array(c*3);let d=t*3,m=this.positions[d]??0,x=this.positions[d+1]??0,w=this.positions[d+2]??0,b=0;for(let u=o-h;u<=o+h;u+=1)for(let y=n-h;y<=n+h;y+=1){let g=this.particleIndex(y,u);if(g<0||this.isPinned(g)&&!i)continue;let T=Math.hypot(y-n,u-o);if(T>l&&g!==t)continue;let f=g*3,v=b*3;this.dragParticles[b]=g,this.dragOffsets[v]=(this.positions[f]??0)-m,this.dragOffsets[v+1]=(this.positions[f+1]??0)-x,this.dragOffsets[v+2]=(this.positions[f+2]??0)-w,this.dragWeights[g]=l===0?1:Math.max(.15,1-T/(l+1)),b+=1;}return this.dragParticleCount=c,this.dragTargetX=m,this.dragTargetY=x,this.dragTargetZ=w,this.dragStiffness=Math.min(1,Math.max(0,s)),this.dragAllowsPinned=i,true}setDragTarget(t,e,s){this.dragTargetX=t,this.dragTargetY=e,this.dragTargetZ=s;}endDrag(t=[0,0,0],e=1/60){for(let s=0;s<this.dragParticleCount;s+=1){let i=this.dragParticles[s];if(i===void 0)continue;let n=this.dragWeights[i]??0,o=i*3;this.previousPositions[o]=(this.previousPositions[o]??0)-t[0]*e*n,this.previousPositions[o+1]=(this.previousPositions[o+1]??0)-t[1]*e*n,this.previousPositions[o+2]=(this.previousPositions[o+2]??0)-t[2]*e*n;}this.clearDragWeights(),this.dragParticleCount=0;}step(t){if(!Number.isFinite(t)||t<=0)return;let e=Math.max(1,Math.floor(this.simulation.substeps)),s=t/e;for(let i=0;i<e;i+=1)this.applyWind(s),this.integrate(s),this.solveConstraints(),this.elapsedTime+=s;}reset(){this.positions.set(this.initialPositions),this.previousPositions.set(this.initialPositions),this.forces.fill(0),this.clearDragWeights(),this.dragParticleCount=0,this.elapsedTime=0,this.enforcePins();}initializeParticles(){let t=this.particleCount/Math.max(1e-6,this.simulation.mass),e=0;for(let s=0;s<this.rows;s+=1){let i=this.height*.5-s/this.segmentsY*this.height;for(let n=0;n<this.columns;n+=1){let o=e*3;this.positions[o]=-this.width*.5+n/this.segmentsX*this.width,this.positions[o+1]=i,this.positions[o+2]=0,this.inverseMass[e]=t,e+=1;}}this.previousPositions.set(this.positions),this.initialPositions.set(this.positions);}updateInverseMass(){let t=this.particleCount/Math.max(1e-6,this.simulation.mass);for(let e=0;e<this.particleCount;e+=1)this.inverseMass[e]=this.pinned[e]===1?0:t;}pinEdge(t,e,s){let i=Math.max(1,Math.floor(e)),n=Math.max(0,Math.floor(s));if(t==="left"||t==="right"){let o=t==="left"?0:this.segmentsX;for(let l=n;l<this.rows;l+=i)this.pinned[l*this.columns+o]=1;}else {let l=(t==="top"?0:this.segmentsY)*this.columns;for(let h=n;h<this.columns;h+=i)this.pinned[l+h]=1;}}integrate(t){let e=t*t,s=Math.pow(Math.min(1,Math.max(0,this.simulation.damping)),t*60),i=this.simulation.gravity;for(let n=0;n<this.particleCount;n+=1){let o=n*3,l=this.inverseMass[n]??0;if(l===0){this.forces[o]=0,this.forces[o+1]=0,this.forces[o+2]=0;continue}let h=this.positions[o]??0,c=this.positions[o+1]??0,d=this.positions[o+2]??0,m=(h-(this.previousPositions[o]??0))*s,x=(c-(this.previousPositions[o+1]??0))*s,w=(d-(this.previousPositions[o+2]??0))*s;this.previousPositions[o]=h,this.previousPositions[o+1]=c,this.previousPositions[o+2]=d,this.positions[o]=h+m+(i[0]+(this.forces[o]??0)*l)*e,this.positions[o+1]=c+x+(i[1]+(this.forces[o+1]??0)*l)*e,this.positions[o+2]=d+w+(i[2]+(this.forces[o+2]??0)*l)*e,this.forces[o]=0,this.forces[o+1]=0,this.forces[o+2]=0;}}solveConstraints(){let t=Math.max(1,Math.floor(this.simulation.constraintIterations)),e=this.iterationStiffness(this.simulation.structuralStiffness,t),s=this.iterationStiffness(this.simulation.shearStiffness,t),i=this.iterationStiffness(this.simulation.bendStiffness,t),n=Math.max(0,this.simulation.maxCorrection),o=this.constraints.first,l=this.constraints.second,h=this.constraints.restLength,c=this.constraints.kind;for(let d=0;d<t;d+=1){for(let m=0;m<this.constraints.count;m+=1){let x=o[m]??0,w=l[m]??0,b=x*3,u=w*3,y=(this.positions[u]??0)-(this.positions[b]??0),g=(this.positions[u+1]??0)-(this.positions[b+1]??0),T=(this.positions[u+2]??0)-(this.positions[b+2]??0),f=y*y+g*g+T*T;if(f<1e-12)continue;let v=Math.sqrt(f),p=v-(h[m]??0);n>0&&(p=Math.max(-n,Math.min(n,p)));let C=c[m]??0,L=C===1?s:C===2?i:e,R=this.inverseMass[x]??0,M=this.inverseMass[w]??0,F=R+M;if(F===0)continue;let E=p/v*L,O=E*(R/F),D=E*(M/F);this.positions[b]=(this.positions[b]??0)+y*O,this.positions[b+1]=(this.positions[b+1]??0)+g*O,this.positions[b+2]=(this.positions[b+2]??0)+T*O,this.positions[u]=(this.positions[u]??0)-y*D,this.positions[u+1]=(this.positions[u+1]??0)-g*D,this.positions[u+2]=(this.positions[u+2]??0)-T*D;}this.solveDrag(t),this.enforcePins();}}solveDrag(t){if(this.dragParticleCount===0)return;let e=this.iterationStiffness(this.dragStiffness,t);for(let s=0;s<this.dragParticleCount;s+=1){let i=this.dragParticles[s];if(i===void 0)continue;let n=i*3,o=s*3,l=e*(this.dragWeights[i]??0),h=this.dragTargetX+(this.dragOffsets[o]??0),c=this.dragTargetY+(this.dragOffsets[o+1]??0),d=this.dragTargetZ+(this.dragOffsets[o+2]??0);this.positions[n]=(this.positions[n]??0)+(h-(this.positions[n]??0))*l,this.positions[n+1]=(this.positions[n+1]??0)+(c-(this.positions[n+1]??0))*l,this.positions[n+2]=(this.positions[n+2]??0)+(d-(this.positions[n+2]??0))*l;}}enforcePins(){for(let t=0;t<this.particleCount;t+=1){if(this.pinned[t]!==1||this.dragAllowsPinned&&(this.dragWeights[t]??0)>0)continue;let e=t*3;this.positions[e]=this.initialPositions[e]??0,this.positions[e+1]=this.initialPositions[e+1]??0,this.positions[e+2]=this.initialPositions[e+2]??0,this.previousPositions[e]=this.initialPositions[e]??0,this.previousPositions[e+1]=this.initialPositions[e+1]??0,this.previousPositions[e+2]=this.initialPositions[e+2]??0;}}applyWind(t){if(this.wind.strength===0||this.wind.aerodynamicCoefficient===0)return;let e=this.positions,s=this.previousPositions,i=this.columns;for(let n=0;n<this.segmentsY;n+=1){let o=n*i;for(let l=0;l<this.segmentsX;l+=1){let h=o+l,c=h+1,d=h+i,m=d+1;this.applyTriangleWind(h,d,c,e,s,t),this.applyTriangleWind(c,d,m,e,s,t);}}}applyTriangleWind(t,e,s,i,n,o){let l=t*3,h=e*3,c=s*3,d=i[l]??0,m=i[l+1]??0,x=i[l+2]??0,w=(i[h]??0)-d,b=(i[h+1]??0)-m,u=(i[h+2]??0)-x,y=(i[c]??0)-d,g=(i[c+1]??0)-m,T=(i[c+2]??0)-x,f=b*T-u*g,v=u*y-w*T,p=w*g-b*y,C=Math.hypot(f,v,p);if(C<1e-10)return;let L=(d+(i[h]??0)+(i[c]??0))/3,R=(m+(i[h+1]??0)+(i[c+1]??0))/3,M=(x+(i[h+2]??0)+(i[c+2]??0))/3,F=this.elapsedTime*Math.max(0,this.wind.gustFrequency),E=Math.max(1e-4,this.wind.spatialScale),O=J(L*E,R*E,F)*2-1,D=J(R*E+17.1,M*E-9.2,F+5.4)*2-1,_=1+O*this.wind.turbulence,B=this.wind.strength*this.wind.turbulence*.2*D,yt=this.windDirectionX*this.wind.strength*_+B,wt=this.windDirectionY*this.wind.strength*_-B*.35,Tt=this.windDirectionZ*this.wind.strength*_+B*.5,Z=1/Math.max(1e-6,o),At=(d-(n[l]??0)+((i[h]??0)-(n[h]??0))+((i[c]??0)-(n[c]??0)))*(Z/3),Ct=(m-(n[l+1]??0)+((i[h+1]??0)-(n[h+1]??0))+((i[c+1]??0)-(n[c+1]??0)))*(Z/3),Pt=(x-(n[l+2]??0)+((i[h+2]??0)-(n[h+2]??0))+((i[c+2]??0)-(n[c+2]??0)))*(Z/3),G=1/C,tt=f*G,et=v*G,it=p*G,Et=yt-At,St=wt-Ct,Lt=Tt-Pt,st=Et*tt+St*et+Lt*it,V=st*Math.abs(st)*this.wind.aerodynamicCoefficient*(C*.5),H=tt*V/3,j=et*V/3,z=it*V/3;this.forces[l]=(this.forces[l]??0)+H,this.forces[l+1]=(this.forces[l+1]??0)+j,this.forces[l+2]=(this.forces[l+2]??0)+z,this.forces[h]=(this.forces[h]??0)+H,this.forces[h+1]=(this.forces[h+1]??0)+j,this.forces[h+2]=(this.forces[h+2]??0)+z,this.forces[c]=(this.forces[c]??0)+H,this.forces[c+1]=(this.forces[c+1]??0)+j,this.forces[c+2]=(this.forces[c+2]??0)+z;}updateWindDirection(){let t=this.wind.direction,e=Math.hypot(t[0],t[1],t[2]);if(e<1e-8){this.windDirectionX=0,this.windDirectionY=0,this.windDirectionZ=0;return}this.windDirectionX=t[0]/e,this.windDirectionY=t[1]/e,this.windDirectionZ=t[2]/e;}iterationStiffness(t,e){let s=Math.min(1,Math.max(0,t));return 1-Math.pow(1-s,1/e)}clearDragWeights(){for(let t=0;t<this.dragParticleCount;t+=1){let e=this.dragParticles[t];e!==void 0&&(this.dragWeights[e]=0);}this.dragAllowsPinned=false;}};var X=class{constructor(t,e,s=8){r(this,"fixedTimeStep",t);r(this,"maxFrameDelta",e);r(this,"maxStepsPerFrame",s);r(this,"accumulator",0);}configure(t,e){this.fixedTimeStep=t,this.maxFrameDelta=e,this.accumulator=Math.min(this.accumulator,t);}advance(t,e){if(!Number.isFinite(t)||t<=0)return 0;let s=Math.min(t,this.maxFrameDelta);this.accumulator+=s;let i=0;for(;this.accumulator>=this.fixedTimeStep&&i<this.maxStepsPerFrame;)e(this.fixedTimeStep),this.accumulator-=this.fixedTimeStep,i+=1;return i===this.maxStepsPerFrame&&(this.accumulator=Math.min(this.accumulator,this.fixedTimeStep)),i}reset(){this.accumulator=0;}};var ot={x:32,y:20},at={direction:[1,.08,.3],strength:7,turbulence:.35,gustFrequency:.5,spatialScale:.8,aerodynamicCoefficient:.35},ht={damping:.985,gravity:[0,0,0],fixedTimeStep:1/60,maxFrameDelta:.1,substeps:2,constraintIterations:6,structuralStiffness:1,shearStiffness:.9,bendStiffness:.4,maxCorrection:.25,mass:1},lt={enabled:true,dragRadius:1,dragStiffness:.9,maxDragDistance:4,allowPinned:false,releaseImpulse:[0,0,0]},ct={alpha:true,antialias:true,desynchronized:false,powerPreference:"high-performance",maxPixelRatio:1.5,preset:"quality",textureFiltering:"linear",transparent:true,backgroundColor:"transparent",shadows:true,shadingUpdateInterval:1},dt={quality:{maxPixelRatio:1.5,shadows:true,shadingUpdateInterval:1},performance:{maxPixelRatio:1,shadows:false,shadingUpdateInterval:2}},ut={baseColor:"#f2f4f3",ambient:.58,diffuse:.55,specular:.16,shininess:18,foldContrast:.42,shadowColor:"rgba(0, 0, 0, 0.3)",shadowBlur:18,shadowOffsetX:10,shadowOffsetY:12},mt={enabled:true,intensity:1,direction:[-0.4,.7,1]},ft={fov:40,near:.01,far:100,position:null,lookAt:[0,0,0]},pt={pauseWhenOffscreen:true,pauseWhenDocumentHidden:true},gt={enabled:false,updateInterval:500};var Y=class{constructor(t){r(this,"element");this.element=document.createElement("div"),this.element.setAttribute("data-flag-cloth-debug",""),this.element.style.cssText="position:absolute;left:8px;top:8px;z-index:10;padding:7px 9px;border-radius:5px;background:rgba(0,0,0,.72);color:#bfffd2;font:11px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;pointer-events:none;white-space:pre",this.element.textContent="flag-cloth",t.appendChild(this.element);}update(t){this.element.textContent=`FPS ${t.fps.toFixed(0)}
78
+ `,N=class{constructor(t,e,s,i,n,o,l){r(this,"canvas",t);r(this,"context",e);r(this,"projectedPositions");r(this,"projectedDepths");r(this,"simulation");r(this,"rendererOptions");r(this,"material");r(this,"lighting");r(this,"camera");r(this,"textureSource",null);r(this,"vertexNormals");r(this,"textureCoordinates");r(this,"indices");r(this,"cssWidth",1);r(this,"cssHeight",1);r(this,"pixelRatio",1);r(this,"focalLength",1);r(this,"cameraX",0);r(this,"cameraY",0);r(this,"cameraZ",5);r(this,"forwardX",0);r(this,"forwardY",0);r(this,"forwardZ",-1);r(this,"rightX",1);r(this,"rightY",0);r(this,"rightZ",0);r(this,"upX",0);r(this,"upY",1);r(this,"upZ",0);r(this,"lightX",0);r(this,"lightY",0);r(this,"lightZ",1);r(this,"frameNumber",0);r(this,"drawCallsValue",0);r(this,"contextLost",false);r(this,"destroyed",false);r(this,"viewMatrix",new Float32Array(16));r(this,"projectionMatrix",new Float32Array(16));r(this,"viewProjectionMatrix",new Float32Array(16));r(this,"baseColor",new Float32Array([1,1,1,1]));r(this,"shadowColor",new Float32Array([0,0,0,.3]));r(this,"backgroundColor",new Float32Array([0,0,0,0]));r(this,"program",null);r(this,"uniforms",null);r(this,"vertexArray",null);r(this,"positionBuffer",null);r(this,"normalBuffer",null);r(this,"textureCoordinateBuffer",null);r(this,"indexBuffer",null);r(this,"texture",null);r(this,"onContextLost",t=>{t.preventDefault(),this.contextLost=true;});r(this,"onContextRestored",()=>{this.destroyed||(this.contextLost=false,this.initializeResources(),this.resize(this.cssWidth,this.cssHeight,this.pixelRatio));});this.simulation=s,this.rendererOptions=i,this.material=n,this.lighting=o,this.camera=l,this.projectedPositions=new Float32Array(s.particleCount*2),this.projectedDepths=new Float32Array(s.particleCount),this.vertexNormals=new Float32Array(s.particleCount*3),this.textureCoordinates=new Float32Array(s.particleCount*2),this.indices=new Uint32Array(s.segmentsX*s.segmentsY*6),this.rebuildTopology(),this.updateCameraBasis(),this.updateLightDirection(),this.updateColors(),this.canvas.addEventListener("webglcontextlost",this.onContextLost),this.canvas.addEventListener("webglcontextrestored",this.onContextRestored),this.initializeResources();}get width(){return this.cssWidth}get height(){return this.cssHeight}get drawCalls(){return this.drawCallsValue}setSimulation(t){this.simulation=t,this.projectedPositions=new Float32Array(t.particleCount*2),this.projectedDepths=new Float32Array(t.particleCount),this.vertexNormals=new Float32Array(t.particleCount*3),this.textureCoordinates=new Float32Array(t.particleCount*2),this.indices=new Uint32Array(t.segmentsX*t.segmentsY*6),this.rebuildTopology(),this.updateCameraBasis(),this.contextLost||this.uploadTopology();}setTexture(t){this.textureSource=t,this.contextLost||this.uploadTexture();}setOptions(t,e,s,i){let n=t.textureFiltering!==this.rendererOptions.textureFiltering;this.rendererOptions=t,this.material=e,this.lighting=s,this.camera=i,this.updateCameraBasis(),this.updateLightDirection(),this.updateColors(),n&&!this.contextLost&&this.applyTextureFiltering();}resize(t,e,s){this.cssWidth=Math.max(1,t),this.cssHeight=Math.max(1,e),this.pixelRatio=Math.max(.5,s);let i=Math.max(1,Math.round(this.cssWidth*this.pixelRatio)),n=Math.max(1,Math.round(this.cssHeight*this.pixelRatio));this.canvas.width!==i&&(this.canvas.width=i),this.canvas.height!==n&&(this.canvas.height=n),this.context.viewport(0,0,i,n),this.updateCameraBasis();}render(){let t=this.context,e=this.uniforms;if(this.destroyed||this.contextLost||!this.program||!e||!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.texture)return;t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.simulation.positions);let s=Math.max(1,Math.floor(this.rendererOptions.shadingUpdateInterval));this.frameNumber%s===0&&(this.updateVertexNormals(),t.bindBuffer(t.ARRAY_BUFFER,this.normalBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.vertexNormals)),this.frameNumber+=1;let i=this.backgroundColor;t.clearColor(i[0]??0,i[1]??0,i[2]??0,this.rendererOptions.transparent?0:i[3]??1),t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT),t.useProgram(this.program),t.bindVertexArray(this.vertexArray),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.texture),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.disable(t.CULL_FACE),this.syncShaderUniforms(e),this.drawCallsValue=0,this.rendererOptions.shadows&&this.drawShadow(e),t.enable(t.DEPTH_TEST),t.depthMask(true),t.uniform1i(e.shadowPass,0),t.uniform2f(e.screenOffset,0,0),t.drawElements(t.TRIANGLES,this.indices.length,t.UNSIGNED_INT,0),this.drawCallsValue+=1,t.bindVertexArray(null);}findParticleAt(t,e){this.projectParticles();let s=-1,i=Number.POSITIVE_INFINITY;for(let n=0;n<this.indices.length;n+=3){let o=this.indices[n]??0,l=this.indices[n+1]??0,h=this.indices[n+2]??0,c=o*2,d=l*2,m=h*2,x=this.projectedPositions[c]??Number.NaN,w=this.projectedPositions[c+1]??Number.NaN,b=this.projectedPositions[d]??Number.NaN,u=this.projectedPositions[d+1]??Number.NaN,y=this.projectedPositions[m]??Number.NaN,g=this.projectedPositions[m+1]??Number.NaN;if(!Number.isFinite(x+w+b+u+y+g))continue;let T=(u-g)*(x-y)+(y-b)*(w-g);if(Math.abs(T)<1e-8)continue;let f=((u-g)*(t-y)+(y-b)*(e-g))/T,v=((g-w)*(t-y)+(x-y)*(e-g))/T,p=1-f-v;if(f<-1e-3||v<-1e-3||p<-1e-3)continue;let C=f*(this.projectedDepths[o]??0)+v*(this.projectedDepths[l]??0)+p*(this.projectedDepths[h]??0);C>=i||(i=C,f>=v&&f>=p?s=o:s=v>=p?l:h);}return s}unprojectToPlane(t,e,s,i,n,o){let l=(t-this.cssWidth*.5)/this.focalLength,h=-(e-this.cssHeight*.5)/this.focalLength,c=this.forwardX+this.rightX*l+this.upX*h,d=this.forwardY+this.rightY*l+this.upY*h,m=this.forwardZ+this.rightZ*l+this.upZ*h,x=Math.hypot(c,d,m)||1;c/=x,d/=x,m/=x;let w=c*this.forwardX+d*this.forwardY+m*this.forwardZ;if(Math.abs(w)<1e-7)return false;let u=((s-this.cameraX)*this.forwardX+(i-this.cameraY)*this.forwardY+(n-this.cameraZ)*this.forwardZ)/w;return u<=0?false:(o[0]=this.cameraX+c*u,o[1]=this.cameraY+d*u,o[2]=this.cameraZ+m*u,true)}destroy(){this.destroyed||(this.destroyed=true,this.canvas.removeEventListener("webglcontextlost",this.onContextLost),this.canvas.removeEventListener("webglcontextrestored",this.onContextRestored),this.deleteResources(),this.context.isContextLost()||(this.context.clearColor(0,0,0,0),this.context.clear(this.context.COLOR_BUFFER_BIT|this.context.DEPTH_BUFFER_BIT)));}initializeResources(){let t=this.context,e=rt(t,t.VERTEX_SHADER,Dt),s=rt(t,t.FRAGMENT_SHADER,Mt),i=t.createProgram();if(!i)throw new Error("Unable to create the cloth shader program.");if(t.attachShader(i,e),t.attachShader(i,s),t.linkProgram(i),t.deleteShader(e),t.deleteShader(s),!t.getProgramParameter(i,t.LINK_STATUS)){let n=t.getProgramInfoLog(i)||"Unknown link error.";throw t.deleteProgram(i),new Error(`Unable to link the cloth shader: ${n}`)}if(this.program=i,this.uniforms={viewProjection:A(t,i,"uViewProjection"),screenOffset:A(t,i,"uScreenOffset"),texture:A(t,i,"uTexture"),hasTexture:A(t,i,"uHasTexture"),shadowPass:A(t,i,"uShadowPass"),baseColor:A(t,i,"uBaseColor"),shadowColor:A(t,i,"uShadowColor"),lightDirection:A(t,i,"uLightDirection"),cameraPosition:A(t,i,"uCameraPosition"),lightingEnabled:A(t,i,"uLightingEnabled"),lightIntensity:A(t,i,"uLightIntensity"),ambient:A(t,i,"uAmbient"),diffuse:A(t,i,"uDiffuse"),specular:A(t,i,"uSpecular"),shininess:A(t,i,"uShininess"),foldContrast:A(t,i,"uFoldContrast")},this.vertexArray=t.createVertexArray(),this.positionBuffer=t.createBuffer(),this.normalBuffer=t.createBuffer(),this.textureCoordinateBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),this.texture=t.createTexture(),!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.textureCoordinateBuffer||!this.indexBuffer||!this.texture)throw this.deleteResources(),new Error("Unable to allocate WebGL cloth resources.");t.useProgram(i),t.uniform1i(this.uniforms.texture,0),this.uploadTopology(),this.uploadTexture();}uploadTopology(){let t=this.context;!this.vertexArray||!this.positionBuffer||!this.normalBuffer||!this.textureCoordinateBuffer||!this.indexBuffer||(this.updateVertexNormals(),t.bindVertexArray(this.vertexArray),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.simulation.positions,t.DYNAMIC_DRAW),t.enableVertexAttribArray(0),t.vertexAttribPointer(0,3,t.FLOAT,false,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.normalBuffer),t.bufferData(t.ARRAY_BUFFER,this.vertexNormals,t.DYNAMIC_DRAW),t.enableVertexAttribArray(1),t.vertexAttribPointer(1,3,t.FLOAT,false,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.textureCoordinateBuffer),t.bufferData(t.ARRAY_BUFFER,this.textureCoordinates,t.STATIC_DRAW),t.enableVertexAttribArray(2),t.vertexAttribPointer(2,2,t.FLOAT,false,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.indices,t.STATIC_DRAW),t.bindVertexArray(null));}uploadTexture(){let t=this.context;this.texture&&(t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,0),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,0),this.textureSource?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.textureSource):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,1,1,0,t.RGBA,t.UNSIGNED_BYTE,Ot),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),this.applyTextureFiltering());}applyTextureFiltering(){let t=this.context;this.texture&&(t.bindTexture(t.TEXTURE_2D,this.texture),this.rendererOptions.textureFiltering==="nearest"?(t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST)):(t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR_MIPMAP_LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.generateMipmap(t.TEXTURE_2D)));}rebuildTopology(){let t=0;for(let s=0;s<this.simulation.rows;s+=1)for(let i=0;i<this.simulation.columns;i+=1){let n=t*2;this.textureCoordinates[n]=i/this.simulation.segmentsX,this.textureCoordinates[n+1]=s/this.simulation.segmentsY,t+=1;}let e=0;for(let s=0;s<this.simulation.segmentsY;s+=1){let i=s*this.simulation.columns;for(let n=0;n<this.simulation.segmentsX;n+=1){let o=i+n,l=o+1,h=o+this.simulation.columns,c=h+1;this.indices[e]=o,this.indices[e+1]=h,this.indices[e+2]=l,this.indices[e+3]=l,this.indices[e+4]=h,this.indices[e+5]=c,e+=6;}}}updateVertexNormals(){let t=this.simulation.positions,e=this.vertexNormals;e.fill(0);for(let s=0;s<this.indices.length;s+=3){let i=(this.indices[s]??0)*3,n=(this.indices[s+1]??0)*3,o=(this.indices[s+2]??0)*3,l=(t[n]??0)-(t[i]??0),h=(t[n+1]??0)-(t[i+1]??0),c=(t[n+2]??0)-(t[i+2]??0),d=(t[o]??0)-(t[i]??0),m=(t[o+1]??0)-(t[i+1]??0),x=(t[o+2]??0)-(t[i+2]??0),w=h*x-c*m,b=c*d-l*x,u=l*m-h*d;k(e,i,w,b,u),k(e,n,w,b,u),k(e,o,w,b,u);}for(let s=0;s<this.simulation.particleCount;s+=1){let i=s*3,n=e[i]??0,o=e[i+1]??0,l=e[i+2]??1,h=Math.hypot(n,o,l)||1;e[i]=n/h,e[i+1]=o/h,e[i+2]=l/h;}}projectParticles(){let t=this.simulation.positions;for(let e=0;e<this.simulation.particleCount;e+=1){let s=e*3,i=(t[s]??0)-this.cameraX,n=(t[s+1]??0)-this.cameraY,o=(t[s+2]??0)-this.cameraZ,l=i*this.rightX+n*this.rightY+o*this.rightZ,h=i*this.upX+n*this.upY+o*this.upZ,c=i*this.forwardX+n*this.forwardY+o*this.forwardZ,d=e*2;if(c<=this.camera.near||c>=this.camera.far)this.projectedPositions[d]=Number.NaN,this.projectedPositions[d+1]=Number.NaN;else {let m=this.focalLength/c;this.projectedPositions[d]=this.cssWidth*.5+l*m,this.projectedPositions[d+1]=this.cssHeight*.5-h*m;}this.projectedDepths[e]=c;}}drawShadow(t){let e=this.context,s=this.shadowColor,i=I.length/2,n=Math.max(0,this.material.shadowBlur)*.36;e.disable(e.DEPTH_TEST),e.depthMask(false),e.uniform1i(t.shadowPass,1),e.uniform4f(t.shadowColor,s[0]??0,s[1]??0,s[2]??0,(s[3]??0)/i);for(let o=0;o<I.length;o+=2){let l=this.material.shadowOffsetX+(I[o]??0)*n,h=this.material.shadowOffsetY+(I[o+1]??0)*n;e.uniform2f(t.screenOffset,l*2/this.cssWidth,-h*2/this.cssHeight),e.drawElements(e.TRIANGLES,this.indices.length,e.UNSIGNED_INT,0),this.drawCallsValue+=1;}}syncShaderUniforms(t){let e=this.context,s=this.baseColor,i=this.shadowColor;e.uniformMatrix4fv(t.viewProjection,false,this.viewProjectionMatrix),e.uniform1i(t.hasTexture,this.textureSource?1:0),e.uniform4f(t.baseColor,s[0]??1,s[1]??1,s[2]??1,s[3]??1),e.uniform4f(t.shadowColor,i[0]??0,i[1]??0,i[2]??0,i[3]??0),e.uniform3f(t.lightDirection,this.lightX,this.lightY,this.lightZ),e.uniform3f(t.cameraPosition,this.cameraX,this.cameraY,this.cameraZ),e.uniform1i(t.lightingEnabled,this.lighting.enabled?1:0),e.uniform1f(t.lightIntensity,this.lighting.intensity),e.uniform1f(t.ambient,this.material.ambient),e.uniform1f(t.diffuse,this.material.diffuse),e.uniform1f(t.specular,this.rendererOptions.preset==="quality"?this.material.specular:0),e.uniform1f(t.shininess,this.material.shininess),e.uniform1f(t.foldContrast,this.material.foldContrast);}updateCameraBasis(){let t=this.camera.position;if(t)this.cameraX=t[0],this.cameraY=t[1],this.cameraZ=t[2];else {let d=Math.max(this.simulation.width,this.simulation.height)*.65/Math.tan(this.camera.fov*Math.PI/360);this.cameraX=0,this.cameraY=0,this.cameraZ=d;}let e=this.camera.lookAt[0]-this.cameraX,s=this.camera.lookAt[1]-this.cameraY,i=this.camera.lookAt[2]-this.cameraZ,n=Math.hypot(e,s,i)||1;e/=n,s/=n,i/=n,this.forwardX=e,this.forwardY=s,this.forwardZ=i;let o=-i,l=0,h=e,c=Math.hypot(o,l,h);c<1e-7&&(o=1,l=0,h=0,c=1),this.rightX=o/c,this.rightY=l/c,this.rightZ=h/c,this.upX=this.rightY*i-this.rightZ*s,this.upY=this.rightZ*e-this.rightX*i,this.upZ=this.rightX*s-this.rightY*e,this.focalLength=this.cssHeight/(2*Math.tan(this.camera.fov*Math.PI/360)),this.updateViewProjection();}updateViewProjection(){let t=this.viewMatrix;t[0]=this.rightX,t[1]=this.upX,t[2]=-this.forwardX,t[3]=0,t[4]=this.rightY,t[5]=this.upY,t[6]=-this.forwardY,t[7]=0,t[8]=this.rightZ,t[9]=this.upZ,t[10]=-this.forwardZ,t[11]=0,t[12]=-(this.rightX*this.cameraX+this.rightY*this.cameraY+this.rightZ*this.cameraZ),t[13]=-(this.upX*this.cameraX+this.upY*this.cameraY+this.upZ*this.cameraZ),t[14]=this.forwardX*this.cameraX+this.forwardY*this.cameraY+this.forwardZ*this.cameraZ,t[15]=1;let e=this.projectionMatrix;e.fill(0);let s=1/Math.tan(this.camera.fov*Math.PI/360),i=this.cssWidth/this.cssHeight,n=Math.max(1e-4,this.camera.near),o=Math.max(n+1e-4,this.camera.far);e[0]=s/i,e[5]=s,e[10]=(o+n)/(n-o),e[11]=-1,e[14]=2*o*n/(n-o),It(this.viewProjectionMatrix,e,t);}updateLightDirection(){let t=this.lighting.direction,e=Math.hypot(t[0],t[1],t[2])||1;this.lightX=t[0]/e,this.lightY=t[1]/e,this.lightZ=t[2]/e;}updateColors(){this.baseColor=q(this.material.baseColor,[1,1,1,1]),this.shadowColor=q(this.material.shadowColor,[0,0,0,.3]),this.backgroundColor=q(this.rendererOptions.backgroundColor,[0,0,0,0]);}deleteResources(){let t=this.context;this.texture&&t.deleteTexture(this.texture),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.textureCoordinateBuffer&&t.deleteBuffer(this.textureCoordinateBuffer),this.normalBuffer&&t.deleteBuffer(this.normalBuffer),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.vertexArray&&t.deleteVertexArray(this.vertexArray),this.program&&t.deleteProgram(this.program),this.texture=null,this.indexBuffer=null,this.textureCoordinateBuffer=null,this.normalBuffer=null,this.positionBuffer=null,this.vertexArray=null,this.uniforms=null,this.program=null;}};function rt(a,t,e){let s=a.createShader(t);if(!s)throw new Error("Unable to create a cloth shader.");if(a.shaderSource(s,e),a.compileShader(s),!a.getShaderParameter(s,a.COMPILE_STATUS)){let i=a.getShaderInfoLog(s)||"Unknown compilation error.";throw a.deleteShader(s),new Error(`Unable to compile the cloth shader: ${i}`)}return s}function A(a,t,e){let s=a.getUniformLocation(t,e);if(!s)throw new Error(`The cloth shader is missing uniform ${e}.`);return s}function k(a,t,e,s,i){a[t]=(a[t]??0)+e,a[t+1]=(a[t+1]??0)+s,a[t+2]=(a[t+2]??0)+i;}function It(a,t,e){for(let s=0;s<4;s+=1){let i=s*4,n=e[i]??0,o=e[i+1]??0,l=e[i+2]??0,h=e[i+3]??0;a[i]=(t[0]??0)*n+(t[4]??0)*o+(t[8]??0)*l+(t[12]??0)*h,a[i+1]=(t[1]??0)*n+(t[5]??0)*o+(t[9]??0)*l+(t[13]??0)*h,a[i+2]=(t[2]??0)*n+(t[6]??0)*o+(t[10]??0)*l+(t[14]??0)*h,a[i+3]=(t[3]??0)*n+(t[7]??0)*o+(t[11]??0)*l+(t[15]??0)*h;}}function q(a,t){let e=new Float32Array(t),s=a.trim().toLowerCase();if(s==="transparent")return new Float32Array([0,0,0,0]);if(s==="black")return new Float32Array([0,0,0,1]);if(s==="white")return new Float32Array([1,1,1,1]);if(s.startsWith("#")){let o=s.slice(1);if(o.length===3||o.length===4)return e[0]=Number.parseInt(o.charAt(0)+o.charAt(0),16)/255,e[1]=Number.parseInt(o.charAt(1)+o.charAt(1),16)/255,e[2]=Number.parseInt(o.charAt(2)+o.charAt(2),16)/255,e[3]=o.length===4?Number.parseInt(o.charAt(3)+o.charAt(3),16)/255:1,e;if(o.length===6||o.length===8)return e[0]=Number.parseInt(o.slice(0,2),16)/255,e[1]=Number.parseInt(o.slice(2,4),16)/255,e[2]=Number.parseInt(o.slice(4,6),16)/255,e[3]=o.length===8?Number.parseInt(o.slice(6,8),16)/255:1,e}let i=s.match(/^rgba?\(([^)]+)\)$/);if(!i?.[1])return e;let n=i[1].split(",");return n.length<3||(e[0]=$(n[0]??"0"),e[1]=$(n[1]??"0"),e[2]=$(n[2]??"0"),e[3]=n[3]===void 0?1:Math.min(1,Math.max(0,Number(n[3])))),e}function $(a){let t=a.trim(),e=Number.parseFloat(t);return Number.isFinite(e)?t.endsWith("%")?Math.min(1,Math.max(0,e/100)):Math.min(1,Math.max(0,e/255)):0}function nt(a,t,e,s){let i=a+1,n=t+1,o=a*n+t*i,l=a*t*2,h=Math.max(0,a-1)*n+Math.max(0,t-1)*i,c=o+l+h,d=new Uint32Array(c),m=new Uint32Array(c),x=new Float32Array(c),w=new Uint8Array(c),b=e/a,u=s/t,y=Math.hypot(b,u),g=0,T=(f,v,p,C)=>{d[g]=f,m[g]=v,x[g]=p,w[g]=C,g+=1;};for(let f=0;f<n;f+=1){let v=f*i;for(let p=0;p<a;p+=1)T(v+p,v+p+1,b,0);}for(let f=0;f<t;f+=1){let v=f*i;for(let p=0;p<i;p+=1)T(v+p,v+i+p,u,0);}for(let f=0;f<t;f+=1){let v=f*i;for(let p=0;p<a;p+=1){let C=v+p,L=C+i;T(C,L+1,y,1),T(C+1,L,y,1);}}for(let f=0;f<n;f+=1){let v=f*i;for(let p=0;p<a-1;p+=1)T(v+p,v+p+2,b*2,2);}for(let f=0;f<t-1;f+=1){let v=f*i;for(let p=0;p<i;p+=1)T(v+p,v+i*2+p,u*2,2);}return {first:d,second:m,restLength:x,kind:w,count:c}}function P(a,t,e){let s=Math.imul(a,374761393)+Math.imul(t,668265263)+Math.imul(e,2147483647);return s=Math.imul(s^s>>>13,1274126177),((s^s>>>16)>>>0)/4294967295}function K(a){return a*a*(3-2*a)}function S(a,t,e){return a+(t-a)*e}function J(a,t,e){let s=Math.floor(a),i=Math.floor(t),n=Math.floor(e),o=K(a-s),l=K(t-i),h=K(e-n),c=S(P(s,i,n),P(s+1,i,n),o),d=S(P(s,i+1,n),P(s+1,i+1,n),o),m=S(P(s,i,n+1),P(s+1,i,n+1),o),x=S(P(s,i+1,n+1),P(s+1,i+1,n+1),o);return S(S(c,d,l),S(m,x,l),h)}var U=class{constructor(t){r(this,"width");r(this,"height");r(this,"segmentsX");r(this,"segmentsY");r(this,"columns");r(this,"rows");r(this,"particleCount");r(this,"positions");r(this,"previousPositions");r(this,"initialPositions");r(this,"forces");r(this,"inverseMass");r(this,"pinned");r(this,"constraints");r(this,"simulation");r(this,"wind");r(this,"windDirectionX",1);r(this,"windDirectionY",0);r(this,"windDirectionZ",0);r(this,"elapsedTime",0);r(this,"dragWeights");r(this,"dragParticles",new Uint32Array(0));r(this,"dragOffsets",new Float32Array(0));r(this,"dragParticleCount",0);r(this,"dragTargetX",0);r(this,"dragTargetY",0);r(this,"dragTargetZ",0);r(this,"dragStiffness",0);r(this,"dragAllowsPinned",false);if(t.width<=0||t.height<=0)throw new RangeError("Cloth width and height must be greater than zero.");if(!Number.isInteger(t.segmentsX)||!Number.isInteger(t.segmentsY))throw new TypeError("Cloth segment counts must be integers.");if(t.segmentsX<1||t.segmentsY<1)throw new RangeError("Cloth segment counts must be at least one.");this.width=t.width,this.height=t.height,this.segmentsX=t.segmentsX,this.segmentsY=t.segmentsY,this.columns=t.segmentsX+1,this.rows=t.segmentsY+1,this.particleCount=this.columns*this.rows,this.positions=new Float32Array(this.particleCount*3),this.previousPositions=new Float32Array(this.particleCount*3),this.initialPositions=new Float32Array(this.particleCount*3),this.forces=new Float32Array(this.particleCount*3),this.inverseMass=new Float32Array(this.particleCount),this.pinned=new Uint8Array(this.particleCount),this.dragWeights=new Float32Array(this.particleCount),this.constraints=nt(t.segmentsX,t.segmentsY,t.width,t.height),this.simulation={...t.simulation},this.wind={...t.wind},this.initializeParticles(),this.setAttachment(t.attachment),this.updateWindDirection();}get constraintCount(){return this.constraints.count}get time(){return this.elapsedTime}particleIndex(t,e){return t<0||t>=this.columns||e<0||e>=this.rows?-1:e*this.columns+t}isPinned(t){return this.pinned[t]===1}addForce(t,e){if(t<0||t>=this.particleCount)return;let s=t*3;this.forces[s]=(this.forces[s]??0)+e[0],this.forces[s+1]=(this.forces[s+1]??0)+e[1],this.forces[s+2]=(this.forces[s+2]??0)+e[2];}setWind(t){this.wind={...this.wind,...t},t.direction&&this.updateWindDirection();}setSimulationOptions(t){this.simulation={...this.simulation,...t},t.mass!==void 0&&this.updateInverseMass();}setAttachment(t){this.pinned.fill(0);let e=(s,i)=>{let n=this.particleIndex(s,i);n>=0&&(this.pinned[n]=1);};if(t==="left")this.pinEdge("left",1,0);else if(t==="right")this.pinEdge("right",1,0);else if(t==="top")this.pinEdge("top",1,0);else if(t==="bottom")this.pinEdge("bottom",1,0);else if(t==="top-left")e(0,0);else if(t==="top-right")e(this.segmentsX,0);else if(t==="bottom-left")e(0,this.segmentsY);else if(t==="bottom-right")e(this.segmentsX,this.segmentsY);else if(typeof t=="object"&&"edge"in t)this.pinEdge(t.edge,t.every??1,t.offset??0);else if(typeof t=="object"&&"points"in t)for(let s=0;s<t.points.length;s+=1){let i=t.points[s];i&&e(Math.round(i[0]),Math.round(i[1]));}this.updateInverseMass(),this.enforcePins();}beginDrag(t,e,s,i){if(t<0||t>=this.particleCount||this.isPinned(t)&&!i)return false;this.clearDragWeights();let n=t%this.columns,o=Math.floor(t/this.columns),l=Math.max(0,e),h=Math.ceil(l),c=0;for(let u=o-h;u<=o+h;u+=1)for(let y=n-h;y<=n+h;y+=1){let g=this.particleIndex(y,u);if(g<0||this.isPinned(g)&&!i)continue;(Math.hypot(y-n,u-o)<=l||g===t)&&(c+=1);}this.dragParticles=new Uint32Array(c),this.dragOffsets=new Float32Array(c*3);let d=t*3,m=this.positions[d]??0,x=this.positions[d+1]??0,w=this.positions[d+2]??0,b=0;for(let u=o-h;u<=o+h;u+=1)for(let y=n-h;y<=n+h;y+=1){let g=this.particleIndex(y,u);if(g<0||this.isPinned(g)&&!i)continue;let T=Math.hypot(y-n,u-o);if(T>l&&g!==t)continue;let f=g*3,v=b*3;this.dragParticles[b]=g,this.dragOffsets[v]=(this.positions[f]??0)-m,this.dragOffsets[v+1]=(this.positions[f+1]??0)-x,this.dragOffsets[v+2]=(this.positions[f+2]??0)-w,this.dragWeights[g]=l===0?1:Math.max(.15,1-T/(l+1)),b+=1;}return this.dragParticleCount=c,this.dragTargetX=m,this.dragTargetY=x,this.dragTargetZ=w,this.dragStiffness=Math.min(1,Math.max(0,s)),this.dragAllowsPinned=i,true}setDragTarget(t,e,s){this.dragTargetX=t,this.dragTargetY=e,this.dragTargetZ=s;}endDrag(t=[0,0,0],e=1/60){for(let s=0;s<this.dragParticleCount;s+=1){let i=this.dragParticles[s];if(i===void 0)continue;let n=this.dragWeights[i]??0,o=i*3;this.previousPositions[o]=(this.previousPositions[o]??0)-t[0]*e*n,this.previousPositions[o+1]=(this.previousPositions[o+1]??0)-t[1]*e*n,this.previousPositions[o+2]=(this.previousPositions[o+2]??0)-t[2]*e*n;}this.clearDragWeights(),this.dragParticleCount=0;}step(t){if(!Number.isFinite(t)||t<=0)return;let e=Math.max(1,Math.floor(this.simulation.substeps)),s=t/e;for(let i=0;i<e;i+=1)this.applyWind(s),this.integrate(s),this.solveConstraints(),this.elapsedTime+=s;}reset(){this.positions.set(this.initialPositions),this.previousPositions.set(this.initialPositions),this.forces.fill(0),this.clearDragWeights(),this.dragParticleCount=0,this.elapsedTime=0,this.enforcePins();}initializeParticles(){let t=this.particleCount/Math.max(1e-6,this.simulation.mass),e=0;for(let s=0;s<this.rows;s+=1){let i=this.height*.5-s/this.segmentsY*this.height;for(let n=0;n<this.columns;n+=1){let o=e*3;this.positions[o]=-this.width*.5+n/this.segmentsX*this.width,this.positions[o+1]=i,this.positions[o+2]=0,this.inverseMass[e]=t,e+=1;}}this.previousPositions.set(this.positions),this.initialPositions.set(this.positions);}updateInverseMass(){let t=this.particleCount/Math.max(1e-6,this.simulation.mass);for(let e=0;e<this.particleCount;e+=1)this.inverseMass[e]=this.pinned[e]===1?0:t;}pinEdge(t,e,s){let i=Math.max(1,Math.floor(e)),n=Math.max(0,Math.floor(s));if(t==="left"||t==="right"){let o=t==="left"?0:this.segmentsX;for(let l=n;l<this.rows;l+=i)this.pinned[l*this.columns+o]=1;}else {let l=(t==="top"?0:this.segmentsY)*this.columns;for(let h=n;h<this.columns;h+=i)this.pinned[l+h]=1;}}integrate(t){let e=t*t,s=Math.pow(Math.min(1,Math.max(0,this.simulation.damping)),t*60),i=this.simulation.gravity;for(let n=0;n<this.particleCount;n+=1){let o=n*3,l=this.inverseMass[n]??0;if(l===0){this.forces[o]=0,this.forces[o+1]=0,this.forces[o+2]=0;continue}let h=this.positions[o]??0,c=this.positions[o+1]??0,d=this.positions[o+2]??0,m=(h-(this.previousPositions[o]??0))*s,x=(c-(this.previousPositions[o+1]??0))*s,w=(d-(this.previousPositions[o+2]??0))*s;this.previousPositions[o]=h,this.previousPositions[o+1]=c,this.previousPositions[o+2]=d,this.positions[o]=h+m+(i[0]+(this.forces[o]??0)*l)*e,this.positions[o+1]=c+x+(i[1]+(this.forces[o+1]??0)*l)*e,this.positions[o+2]=d+w+(i[2]+(this.forces[o+2]??0)*l)*e,this.forces[o]=0,this.forces[o+1]=0,this.forces[o+2]=0;}}solveConstraints(){let t=Math.max(1,Math.floor(this.simulation.constraintIterations)),e=this.iterationStiffness(this.simulation.structuralStiffness,t),s=this.iterationStiffness(this.simulation.shearStiffness,t),i=this.iterationStiffness(this.simulation.bendStiffness,t),n=Math.max(0,this.simulation.maxCorrection),o=this.constraints.first,l=this.constraints.second,h=this.constraints.restLength,c=this.constraints.kind;for(let d=0;d<t;d+=1){for(let m=0;m<this.constraints.count;m+=1){let x=o[m]??0,w=l[m]??0,b=x*3,u=w*3,y=(this.positions[u]??0)-(this.positions[b]??0),g=(this.positions[u+1]??0)-(this.positions[b+1]??0),T=(this.positions[u+2]??0)-(this.positions[b+2]??0),f=y*y+g*g+T*T;if(f<1e-12)continue;let v=Math.sqrt(f),p=v-(h[m]??0);n>0&&(p=Math.max(-n,Math.min(n,p)));let C=c[m]??0,L=C===1?s:C===2?i:e,R=this.inverseMass[x]??0,M=this.inverseMass[w]??0,F=R+M;if(F===0)continue;let E=p/v*L,O=E*(R/F),D=E*(M/F);this.positions[b]=(this.positions[b]??0)+y*O,this.positions[b+1]=(this.positions[b+1]??0)+g*O,this.positions[b+2]=(this.positions[b+2]??0)+T*O,this.positions[u]=(this.positions[u]??0)-y*D,this.positions[u+1]=(this.positions[u+1]??0)-g*D,this.positions[u+2]=(this.positions[u+2]??0)-T*D;}this.solveDrag(t),this.enforcePins();}}solveDrag(t){if(this.dragParticleCount===0)return;let e=this.iterationStiffness(this.dragStiffness,t);for(let s=0;s<this.dragParticleCount;s+=1){let i=this.dragParticles[s];if(i===void 0)continue;let n=i*3,o=s*3,l=e*(this.dragWeights[i]??0),h=this.dragTargetX+(this.dragOffsets[o]??0),c=this.dragTargetY+(this.dragOffsets[o+1]??0),d=this.dragTargetZ+(this.dragOffsets[o+2]??0);this.positions[n]=(this.positions[n]??0)+(h-(this.positions[n]??0))*l,this.positions[n+1]=(this.positions[n+1]??0)+(c-(this.positions[n+1]??0))*l,this.positions[n+2]=(this.positions[n+2]??0)+(d-(this.positions[n+2]??0))*l;}}enforcePins(){for(let t=0;t<this.particleCount;t+=1){if(this.pinned[t]!==1||this.dragAllowsPinned&&(this.dragWeights[t]??0)>0)continue;let e=t*3;this.positions[e]=this.initialPositions[e]??0,this.positions[e+1]=this.initialPositions[e+1]??0,this.positions[e+2]=this.initialPositions[e+2]??0,this.previousPositions[e]=this.initialPositions[e]??0,this.previousPositions[e+1]=this.initialPositions[e+1]??0,this.previousPositions[e+2]=this.initialPositions[e+2]??0;}}applyWind(t){if(this.wind.strength===0||this.wind.aerodynamicCoefficient===0)return;let e=this.positions,s=this.previousPositions,i=this.columns;for(let n=0;n<this.segmentsY;n+=1){let o=n*i;for(let l=0;l<this.segmentsX;l+=1){let h=o+l,c=h+1,d=h+i,m=d+1;this.applyTriangleWind(h,d,c,e,s,t),this.applyTriangleWind(c,d,m,e,s,t);}}}applyTriangleWind(t,e,s,i,n,o){let l=t*3,h=e*3,c=s*3,d=i[l]??0,m=i[l+1]??0,x=i[l+2]??0,w=(i[h]??0)-d,b=(i[h+1]??0)-m,u=(i[h+2]??0)-x,y=(i[c]??0)-d,g=(i[c+1]??0)-m,T=(i[c+2]??0)-x,f=b*T-u*g,v=u*y-w*T,p=w*g-b*y,C=Math.hypot(f,v,p);if(C<1e-10)return;let L=(d+(i[h]??0)+(i[c]??0))/3,R=(m+(i[h+1]??0)+(i[c+1]??0))/3,M=(x+(i[h+2]??0)+(i[c+2]??0))/3,F=this.elapsedTime*Math.max(0,this.wind.gustFrequency),E=Math.max(1e-4,this.wind.spatialScale),O=J(L*E,R*E,F)*2-1,D=J(R*E+17.1,M*E-9.2,F+5.4)*2-1,_=1+O*this.wind.turbulence,B=this.wind.strength*this.wind.turbulence*.2*D,yt=this.windDirectionX*this.wind.strength*_+B,wt=this.windDirectionY*this.wind.strength*_-B*.35,Tt=this.windDirectionZ*this.wind.strength*_+B*.5,Z=1/Math.max(1e-6,o),At=(d-(n[l]??0)+((i[h]??0)-(n[h]??0))+((i[c]??0)-(n[c]??0)))*(Z/3),Ct=(m-(n[l+1]??0)+((i[h+1]??0)-(n[h+1]??0))+((i[c+1]??0)-(n[c+1]??0)))*(Z/3),Pt=(x-(n[l+2]??0)+((i[h+2]??0)-(n[h+2]??0))+((i[c+2]??0)-(n[c+2]??0)))*(Z/3),G=1/C,tt=f*G,et=v*G,it=p*G,Et=yt-At,St=wt-Ct,Lt=Tt-Pt,st=Et*tt+St*et+Lt*it,V=st*Math.abs(st)*this.wind.aerodynamicCoefficient*(C*.5),H=tt*V/3,j=et*V/3,z=it*V/3;this.forces[l]=(this.forces[l]??0)+H,this.forces[l+1]=(this.forces[l+1]??0)+j,this.forces[l+2]=(this.forces[l+2]??0)+z,this.forces[h]=(this.forces[h]??0)+H,this.forces[h+1]=(this.forces[h+1]??0)+j,this.forces[h+2]=(this.forces[h+2]??0)+z,this.forces[c]=(this.forces[c]??0)+H,this.forces[c+1]=(this.forces[c+1]??0)+j,this.forces[c+2]=(this.forces[c+2]??0)+z;}updateWindDirection(){let t=this.wind.direction,e=Math.hypot(t[0],t[1],t[2]);if(e<1e-8){this.windDirectionX=0,this.windDirectionY=0,this.windDirectionZ=0;return}this.windDirectionX=t[0]/e,this.windDirectionY=t[1]/e,this.windDirectionZ=t[2]/e;}iterationStiffness(t,e){let s=Math.min(1,Math.max(0,t));return 1-Math.pow(1-s,1/e)}clearDragWeights(){for(let t=0;t<this.dragParticleCount;t+=1){let e=this.dragParticles[t];e!==void 0&&(this.dragWeights[e]=0);}this.dragAllowsPinned=false;}};var X=class{constructor(t,e,s=8){r(this,"fixedTimeStep",t);r(this,"maxFrameDelta",e);r(this,"maxStepsPerFrame",s);r(this,"accumulator",0);}configure(t,e){this.fixedTimeStep=t,this.maxFrameDelta=e,this.accumulator=Math.min(this.accumulator,t);}advance(t,e){if(!Number.isFinite(t)||t<=0)return 0;let s=Math.min(t,this.maxFrameDelta);this.accumulator+=s;let i=0;for(;this.accumulator>=this.fixedTimeStep&&i<this.maxStepsPerFrame;)e(this.fixedTimeStep),this.accumulator-=this.fixedTimeStep,i+=1;return i===this.maxStepsPerFrame&&(this.accumulator=Math.min(this.accumulator,this.fixedTimeStep)),i}reset(){this.accumulator=0;}};var ot={x:32,y:20},at={direction:[1,.08,.3],strength:7,turbulence:.35,gustFrequency:.5,spatialScale:.8,aerodynamicCoefficient:.35},ht={damping:.985,gravity:[0,0,0],fixedTimeStep:1/60,maxFrameDelta:.1,substeps:2,constraintIterations:6,structuralStiffness:1,shearStiffness:.9,bendStiffness:.4,maxCorrection:.25,mass:1},lt={enabled:true,touchAction:"pan-y",dragRadius:1,dragStiffness:.9,maxDragDistance:4,allowPinned:false,releaseImpulse:[0,0,0]},ct={alpha:true,antialias:true,desynchronized:false,powerPreference:"high-performance",maxPixelRatio:1.5,preset:"quality",textureFiltering:"linear",transparent:true,backgroundColor:"transparent",shadows:true,shadingUpdateInterval:1},dt={quality:{maxPixelRatio:1.5,shadows:true,shadingUpdateInterval:1},performance:{maxPixelRatio:1,shadows:false,shadingUpdateInterval:2}},ut={baseColor:"#f2f4f3",ambient:.58,diffuse:.55,specular:.16,shininess:18,foldContrast:.42,shadowColor:"rgba(0, 0, 0, 0.3)",shadowBlur:18,shadowOffsetX:10,shadowOffsetY:12},mt={enabled:true,intensity:1,direction:[-0.4,.7,1]},ft={fov:40,near:.01,far:100,position:null,lookAt:[0,0,0]},pt={pauseWhenOffscreen:true,pauseWhenDocumentHidden:true},gt={enabled:false,updateInterval:500};var Y=class{constructor(t){r(this,"element");this.element=document.createElement("div"),this.element.setAttribute("data-flag-cloth-debug",""),this.element.style.cssText="position:absolute;left:8px;top:8px;z-index:10;padding:7px 9px;border-radius:5px;background:rgba(0,0,0,.72);color:#bfffd2;font:11px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;pointer-events:none;white-space:pre",this.element.textContent="flag-cloth",t.appendChild(this.element);}update(t){this.element.textContent=`FPS ${t.fps.toFixed(0)}
79
79
  simulation ${t.simulationMs.toFixed(2)} ms
80
80
  render ${t.renderMs.toFixed(2)} ms
81
81
  particles ${t.particleCount}
82
82
  constraints ${t.constraintCount}
83
- draw calls ${t.drawCalls}`;}destroy(){this.element.remove();}};var W=class{constructor(t,e,s,i,n){r(this,"element",t);r(this,"renderer");r(this,"simulation");r(this,"options");r(this,"fixedTimeStep");r(this,"worldTarget",new Float32Array(3));r(this,"screenPoint",new Float32Array(2));r(this,"activePointerId",-1);r(this,"selectedParticle",-1);r(this,"planeX",0);r(this,"planeY",0);r(this,"planeZ",0);r(this,"grabOffsetX",0);r(this,"grabOffsetY",0);r(this,"grabOffsetZ",0);r(this,"startTargetX",0);r(this,"startTargetY",0);r(this,"startTargetZ",0);r(this,"destroyed",false);r(this,"originalTouchAction");r(this,"onPointerDown",t=>{if(!this.options.enabled||this.activePointerId>=0||t.pointerType==="mouse"&&t.button!==0)return;this.readPointerPosition(t);let e=this.screenPoint[0]??0,s=this.screenPoint[1]??0,i=this.renderer.findParticleAt(e,s);if(!this.simulation.beginDrag(i,this.options.dragRadius,this.options.dragStiffness,this.options.allowPinned))return;let n=i*3;this.selectedParticle=i,this.planeX=this.simulation.positions[n]??0,this.planeY=this.simulation.positions[n+1]??0,this.planeZ=this.simulation.positions[n+2]??0,this.renderer.unprojectToPlane(e,s,this.planeX,this.planeY,this.planeZ,this.worldTarget)?(this.grabOffsetX=this.planeX-(this.worldTarget[0]??0),this.grabOffsetY=this.planeY-(this.worldTarget[1]??0),this.grabOffsetZ=this.planeZ-(this.worldTarget[2]??0)):(this.grabOffsetX=0,this.grabOffsetY=0,this.grabOffsetZ=0),this.startTargetX=this.planeX,this.startTargetY=this.planeY,this.startTargetZ=this.planeZ,this.activePointerId=t.pointerId,this.element.setPointerCapture(t.pointerId),t.preventDefault();});r(this,"onPointerMove",t=>{if(t.pointerId!==this.activePointerId||this.selectedParticle<0||(this.readPointerPosition(t),!this.renderer.unprojectToPlane(this.screenPoint[0]??0,this.screenPoint[1]??0,this.planeX,this.planeY,this.planeZ,this.worldTarget)))return;let e=(this.worldTarget[0]??0)+this.grabOffsetX,s=(this.worldTarget[1]??0)+this.grabOffsetY,i=(this.worldTarget[2]??0)+this.grabOffsetZ,n=e-this.startTargetX,o=s-this.startTargetY,l=i-this.startTargetZ,h=Math.hypot(n,o,l),c=Math.max(0,this.options.maxDragDistance);if(c>0&&h>c){let d=c/h;e=this.startTargetX+n*d,s=this.startTargetY+o*d,i=this.startTargetZ+l*d;}this.simulation.setDragTarget(e,s,i),t.preventDefault();});r(this,"onPointerEnd",t=>{t.pointerId===this.activePointerId&&this.releaseDrag(this.options.releaseImpulse);});r(this,"onLostPointerCapture",t=>{t.pointerId===this.activePointerId&&this.releaseDrag(this.options.releaseImpulse);});this.renderer=e,this.simulation=s,this.options=i,this.fixedTimeStep=n,this.originalTouchAction=t.style.touchAction,this.syncTouchAction(),t.addEventListener("pointerdown",this.onPointerDown),t.addEventListener("pointermove",this.onPointerMove),t.addEventListener("pointerup",this.onPointerEnd),t.addEventListener("pointercancel",this.onPointerEnd),t.addEventListener("lostpointercapture",this.onLostPointerCapture);}setTargets(t,e){this.activePointerId>=0&&this.releaseDrag(),this.renderer=t,this.simulation=e;}setOptions(t,e){this.options=t,this.fixedTimeStep=e,!t.enabled&&this.activePointerId>=0&&this.releaseDrag(),this.syncTouchAction();}destroy(){this.destroyed||(this.releaseDrag(),this.element.removeEventListener("pointerdown",this.onPointerDown),this.element.removeEventListener("pointermove",this.onPointerMove),this.element.removeEventListener("pointerup",this.onPointerEnd),this.element.removeEventListener("pointercancel",this.onPointerEnd),this.element.removeEventListener("lostpointercapture",this.onLostPointerCapture),this.element.style.touchAction=this.originalTouchAction,this.destroyed=true);}readPointerPosition(t){let e=this.element.getBoundingClientRect();this.screenPoint[0]=(t.clientX-e.left)/Math.max(1,e.width)*this.renderer.width,this.screenPoint[1]=(t.clientY-e.top)/Math.max(1,e.height)*this.renderer.height;}releaseDrag(t=[0,0,0]){if(this.activePointerId<0)return;let e=this.activePointerId;this.activePointerId=-1,this.selectedParticle=-1,this.simulation.endDrag(t,this.fixedTimeStep),this.element.hasPointerCapture(e)&&this.element.releasePointerCapture(e);}syncTouchAction(){this.element.style.touchAction=this.options.enabled?"none":this.originalTouchAction;}};async function vt(a){if(a===null||typeof a!="string")return a;let t=new Image;return t.decoding="async",t.crossOrigin="anonymous",await new Promise((e,s)=>{t.addEventListener("load",()=>e(),{once:true}),t.addEventListener("error",()=>s(new Error(`Unable to load cloth texture: ${a}`)),{once:true}),t.src=a;}),t}var Q=class{constructor(t){r(this,"container");r(this,"canvas");r(this,"context");r(this,"renderer");r(this,"ready");r(this,"options");r(this,"simulation");r(this,"fixedTimeStep");r(this,"pointerController");r(this,"currentTexture",null);r(this,"ownsCanvas");r(this,"externalAnimationLoop");r(this,"canvasAppended",false);r(this,"resizeObserver",null);r(this,"intersectionObserver",null);r(this,"debugPanel",null);r(this,"textureRequest",0);r(this,"animationFrame",0);r(this,"lastFrameTime",0);r(this,"started",false);r(this,"userPaused",false);r(this,"documentHidden",false);r(this,"offscreen",false);r(this,"destroyed",false);r(this,"lastWidth",0);r(this,"lastHeight",0);r(this,"statsFrameCount",0);r(this,"statsWindowStarted",0);r(this,"lastDebugUpdate",0);r(this,"statsValue",{fps:0,simulationMs:0,renderMs:0,particleCount:0,constraintCount:0,drawCalls:0});r(this,"simulateStep",t=>{this.simulation.step(t);});r(this,"onAnimationFrame",t=>{if(this.animationFrame=0,!this.canAnimate())return;let e=this.lastFrameTime===0?0:(t-this.lastFrameTime)/1e3;this.lastFrameTime=t,this.update(e,true),this.requestAnimationFrameIfNeeded();});r(this,"onResizeObserved",()=>this.resize());r(this,"onIntersection",t=>{let e=t[t.length-1];e&&(this.offscreen=!e.isIntersecting,this.syncAnimationState());});r(this,"onVisibilityChange",()=>{this.documentHidden=document.visibilityState==="hidden",this.syncAnimationState();});if(!t.container)throw new TypeError("createFlagCloth requires a container element.");this.container=t.container,this.options=Xt(t),this.ownsCanvas=!t.advanced?.canvas&&!t.advanced?.context,this.externalAnimationLoop=t.advanced?.externalAnimationLoop??false;let e=t.advanced?.context?.canvas;if(e&&!(e instanceof HTMLCanvasElement))throw new TypeError("advanced.context must belong to an HTMLCanvasElement.");if(this.canvas=e??t.advanced?.canvas??document.createElement("canvas"),t.advanced?.canvas&&t.advanced.context&&t.advanced.context.canvas!==t.advanced.canvas)throw new TypeError("advanced.canvas and advanced.context must refer to the same canvas.");let s=t.advanced?.context??this.canvas.getContext("webgl2",{alpha:this.options.renderer.alpha,antialias:this.options.renderer.antialias,desynchronized:this.options.renderer.desynchronized,powerPreference:this.options.renderer.powerPreference,premultipliedAlpha:true,preserveDrawingBuffer:false});if(!s)throw new Error("A WebGL2 rendering context is required.");this.context=s,this.simulation=this.createSimulation(),this.renderer=new N(this.canvas,this.context,this.simulation,this.options.renderer,this.options.material,this.options.lighting,this.options.camera),this.canvas.style.display="block",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.setAttribute("aria-label","flag-cloth"),this.ownsCanvas&&(this.container.appendChild(this.canvas),this.canvasAppended=true),this.fixedTimeStep=new X(this.options.simulation.fixedTimeStep,this.options.simulation.maxFrameDelta),this.pointerController=new W(this.canvas,this.renderer,this.simulation,this.options.interaction,this.options.simulation.fixedTimeStep),this.statsValue.particleCount=this.simulation.particleCount,this.statsValue.constraintCount=this.simulation.constraintCount,this.setupResizeObserver(),this.setupVisibilityObservers(),this.syncDebugPanel(),this.resize(),this.ready=this.setTexture(t.texture),t.autoStart!==false&&this.start();}get stats(){return this.statsValue}get particleCount(){return this.simulation.particleCount}get constraintCount(){return this.simulation.constraintCount}start(){this.assertAlive(),this.started=true,this.userPaused=false,this.lastFrameTime=0,this.requestAnimationFrameIfNeeded();}pause(){this.destroyed||(this.userPaused=true,this.cancelAnimationFrame());}resume(){this.assertAlive(),this.started=true,this.userPaused=false,this.lastFrameTime=0,this.requestAnimationFrameIfNeeded();}update(t,e=true){if(this.destroyed||!this.canAnimate())return;let s=performance.now();this.fixedTimeStep.advance(t,this.simulateStep);let i=performance.now();this.statsValue.simulationMs=i-s,e&&this.render(),this.updateStats(i);}render(){if(this.destroyed)return;let t=performance.now();this.renderer.render(),this.statsValue.renderMs=performance.now()-t,this.statsValue.drawCalls=this.renderer.drawCalls;}resize(){if(this.destroyed)return;let t=Math.max(0,Math.floor(this.container.clientWidth)),e=Math.max(0,Math.floor(this.container.clientHeight));if(t===0||e===0||t===this.lastWidth&&e===this.lastHeight)return;this.lastWidth=t,this.lastHeight=e;let s=typeof window>"u"?1:window.devicePixelRatio;this.renderer.resize(t,e,Math.min(s,this.options.renderer.maxPixelRatio));}async setTexture(t){this.assertAlive();let e=++this.textureRequest,s=await vt(t);this.destroyed||e!==this.textureRequest||(this.currentTexture=s,this.renderer.setTexture(s));}setWind(t){this.assertAlive(),this.options.wind={...this.options.wind,...t},this.simulation.setWind(t);}async setOptions(t){this.assertAlive();let e=t.width!==void 0&&t.width!==this.options.width||t.height!==void 0&&t.height!==this.options.height||t.segments?.x!==void 0&&t.segments.x!==this.options.segments.x||t.segments?.y!==void 0&&t.segments.y!==this.options.segments.y;t.width!==void 0&&(this.options.width=t.width),t.height!==void 0&&(this.options.height=t.height),t.segments&&(this.options.segments={...this.options.segments,...t.segments}),t.attachment!==void 0&&(this.options.attachment=t.attachment),t.wind&&(this.options.wind={...this.options.wind,...t.wind}),t.simulation&&(this.options.simulation={...this.options.simulation,...t.simulation},this.fixedTimeStep.configure(this.options.simulation.fixedTimeStep,this.options.simulation.maxFrameDelta)),t.interaction&&(this.options.interaction={...this.options.interaction,...t.interaction}),t.renderer&&(this.options.renderer=bt(this.options.renderer,t.renderer)),t.material&&(this.options.material={...this.options.material,...t.material}),t.lighting&&(this.options.lighting={...this.options.lighting,...t.lighting}),t.camera&&(this.options.camera={...this.options.camera,...t.camera}),t.visibility&&(this.options.visibility={...this.options.visibility,...t.visibility}),t.debug!==void 0&&(this.options.debug=xt(t.debug,this.options.debug)),e?this.rebuildCloth():(t.attachment!==void 0&&this.simulation.setAttachment(this.options.attachment),t.wind&&this.simulation.setWind(t.wind),t.simulation&&this.simulation.setSimulationOptions(t.simulation)),this.renderer.setOptions(this.options.renderer,this.options.material,this.options.lighting,this.options.camera),(e||t.renderer||t.camera)&&(this.lastWidth=0,this.lastHeight=0,this.resize()),this.pointerController.setOptions(this.options.interaction,this.options.simulation.fixedTimeStep),t.visibility&&this.setupVisibilityObservers(),t.debug!==void 0&&this.syncDebugPanel(),t.texture!==void 0&&await this.setTexture(t.texture);}reset(){this.assertAlive(),this.fixedTimeStep.reset(),this.simulation.reset(),this.render();}destroy(){this.destroyed||(this.destroyed=true,this.started=false,this.textureRequest+=1,this.cancelAnimationFrame(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.intersectionObserver?.disconnect(),this.intersectionObserver=null,document.removeEventListener("visibilitychange",this.onVisibilityChange),this.pointerController.destroy(),this.debugPanel?.destroy(),this.debugPanel=null,this.currentTexture=null,this.renderer.destroy(),this.ownsCanvas&&this.canvasAppended&&this.canvas.remove());}createSimulation(){return new U({width:this.options.width,height:this.options.height,segmentsX:this.options.segments.x,segmentsY:this.options.segments.y,attachment:this.options.attachment,simulation:this.options.simulation,wind:this.options.wind})}rebuildCloth(){this.simulation=this.createSimulation(),this.renderer.setSimulation(this.simulation),this.renderer.setTexture(this.currentTexture),this.pointerController.setTargets(this.renderer,this.simulation),this.statsValue.particleCount=this.simulation.particleCount,this.statsValue.constraintCount=this.simulation.constraintCount,this.fixedTimeStep.reset();}setupResizeObserver(){this.resizeObserver?.disconnect(),!(typeof ResizeObserver>"u")&&(this.resizeObserver=new ResizeObserver(this.onResizeObserved),this.resizeObserver.observe(this.container));}setupVisibilityObservers(){this.intersectionObserver?.disconnect(),this.intersectionObserver=null,document.removeEventListener("visibilitychange",this.onVisibilityChange),this.offscreen=false,this.documentHidden=false,this.options.visibility.pauseWhenOffscreen&&typeof IntersectionObserver<"u"&&(this.intersectionObserver=new IntersectionObserver(this.onIntersection),this.intersectionObserver.observe(this.container)),this.options.visibility.pauseWhenDocumentHidden&&(this.documentHidden=document.visibilityState==="hidden",document.addEventListener("visibilitychange",this.onVisibilityChange)),this.syncAnimationState();}syncDebugPanel(){this.options.debug.enabled&&!this.debugPanel?this.debugPanel=new Y(this.container):!this.options.debug.enabled&&this.debugPanel&&(this.debugPanel.destroy(),this.debugPanel=null);}updateStats(t){this.statsWindowStarted===0&&(this.statsWindowStarted=t),this.statsFrameCount+=1;let e=t-this.statsWindowStarted;e>=500&&(this.statsValue.fps=this.statsFrameCount*1e3/e,this.statsFrameCount=0,this.statsWindowStarted=t),this.debugPanel&&t-this.lastDebugUpdate>=Math.max(100,this.options.debug.updateInterval)&&(this.debugPanel.update(this.statsValue),this.lastDebugUpdate=t);}syncAnimationState(){this.canAnimate()?(this.lastFrameTime=0,this.requestAnimationFrameIfNeeded()):this.cancelAnimationFrame();}canAnimate(){return this.started&&!this.userPaused&&!this.documentHidden&&!this.offscreen}requestAnimationFrameIfNeeded(){this.externalAnimationLoop||this.animationFrame!==0||!this.canAnimate()||typeof requestAnimationFrame>"u"||(this.animationFrame=requestAnimationFrame(this.onAnimationFrame));}cancelAnimationFrame(){this.animationFrame===0||typeof cancelAnimationFrame>"u"||(cancelAnimationFrame(this.animationFrame),this.animationFrame=0);}assertAlive(){if(this.destroyed)throw new Error("This FlagCloth instance has been destroyed.")}};function he(a){return new Q(a)}function Xt(a){return {width:a.width??3,height:a.height??2,segments:{...ot,...a.segments},attachment:a.attachment??"left",wind:{...at,...a.wind},simulation:{...ht,...a.simulation},interaction:{...lt,...a.interaction},renderer:bt(ct,a.renderer??{}),material:{...ut,...a.material},lighting:{...mt,...a.lighting},camera:{...ft,...a.camera},visibility:{...pt,...a.visibility},debug:xt(a.debug??false,gt)}}function bt(a,t){let e={...a,...t};if(t.preset!==void 0){let s=dt[t.preset];t.maxPixelRatio===void 0&&(e.maxPixelRatio=s.maxPixelRatio),t.shadingUpdateInterval===void 0&&(e.shadingUpdateInterval=s.shadingUpdateInterval),t.shadows===void 0&&(e.shadows=s.shadows);}return e.maxPixelRatio=Math.max(.5,e.maxPixelRatio),e}function xt(a,t){return typeof a=="boolean"?{...t,enabled:a}:{...t,...a}}export{N as a,U as b,X as c,Q as d,he as e};//# sourceMappingURL=chunk-E5IYGF33.js.map
84
- //# sourceMappingURL=chunk-E5IYGF33.js.map
83
+ draw calls ${t.drawCalls}`;}destroy(){this.element.remove();}};var W=class{constructor(t,e,s,i,n){r(this,"element",t);r(this,"renderer");r(this,"simulation");r(this,"options");r(this,"fixedTimeStep");r(this,"worldTarget",new Float32Array(3));r(this,"screenPoint",new Float32Array(2));r(this,"activePointerId",-1);r(this,"selectedParticle",-1);r(this,"planeX",0);r(this,"planeY",0);r(this,"planeZ",0);r(this,"grabOffsetX",0);r(this,"grabOffsetY",0);r(this,"grabOffsetZ",0);r(this,"startTargetX",0);r(this,"startTargetY",0);r(this,"startTargetZ",0);r(this,"destroyed",false);r(this,"originalTouchAction");r(this,"onPointerDown",t=>{if(!this.options.enabled||this.activePointerId>=0||t.pointerType==="mouse"&&t.button!==0)return;this.readPointerPosition(t);let e=this.screenPoint[0]??0,s=this.screenPoint[1]??0,i=this.renderer.findParticleAt(e,s);if(!this.simulation.beginDrag(i,this.options.dragRadius,this.options.dragStiffness,this.options.allowPinned))return;let n=i*3;this.selectedParticle=i,this.planeX=this.simulation.positions[n]??0,this.planeY=this.simulation.positions[n+1]??0,this.planeZ=this.simulation.positions[n+2]??0,this.renderer.unprojectToPlane(e,s,this.planeX,this.planeY,this.planeZ,this.worldTarget)?(this.grabOffsetX=this.planeX-(this.worldTarget[0]??0),this.grabOffsetY=this.planeY-(this.worldTarget[1]??0),this.grabOffsetZ=this.planeZ-(this.worldTarget[2]??0)):(this.grabOffsetX=0,this.grabOffsetY=0,this.grabOffsetZ=0),this.startTargetX=this.planeX,this.startTargetY=this.planeY,this.startTargetZ=this.planeZ,this.activePointerId=t.pointerId,this.element.setPointerCapture(t.pointerId),t.preventDefault();});r(this,"onPointerMove",t=>{if(t.pointerId!==this.activePointerId||this.selectedParticle<0||(this.readPointerPosition(t),!this.renderer.unprojectToPlane(this.screenPoint[0]??0,this.screenPoint[1]??0,this.planeX,this.planeY,this.planeZ,this.worldTarget)))return;let e=(this.worldTarget[0]??0)+this.grabOffsetX,s=(this.worldTarget[1]??0)+this.grabOffsetY,i=(this.worldTarget[2]??0)+this.grabOffsetZ,n=e-this.startTargetX,o=s-this.startTargetY,l=i-this.startTargetZ,h=Math.hypot(n,o,l),c=Math.max(0,this.options.maxDragDistance);if(c>0&&h>c){let d=c/h;e=this.startTargetX+n*d,s=this.startTargetY+o*d,i=this.startTargetZ+l*d;}this.simulation.setDragTarget(e,s,i),t.preventDefault();});r(this,"onPointerEnd",t=>{t.pointerId===this.activePointerId&&this.releaseDrag(this.options.releaseImpulse);});r(this,"onLostPointerCapture",t=>{t.pointerId===this.activePointerId&&this.releaseDrag(this.options.releaseImpulse);});this.renderer=e,this.simulation=s,this.options=i,this.fixedTimeStep=n,this.originalTouchAction=t.style.touchAction,this.syncTouchAction(),t.addEventListener("pointerdown",this.onPointerDown),t.addEventListener("pointermove",this.onPointerMove),t.addEventListener("pointerup",this.onPointerEnd),t.addEventListener("pointercancel",this.onPointerEnd),t.addEventListener("lostpointercapture",this.onLostPointerCapture);}setTargets(t,e){this.activePointerId>=0&&this.releaseDrag(),this.renderer=t,this.simulation=e;}setOptions(t,e){this.options=t,this.fixedTimeStep=e,!t.enabled&&this.activePointerId>=0&&this.releaseDrag(),this.syncTouchAction();}destroy(){this.destroyed||(this.releaseDrag(),this.element.removeEventListener("pointerdown",this.onPointerDown),this.element.removeEventListener("pointermove",this.onPointerMove),this.element.removeEventListener("pointerup",this.onPointerEnd),this.element.removeEventListener("pointercancel",this.onPointerEnd),this.element.removeEventListener("lostpointercapture",this.onLostPointerCapture),this.element.style.touchAction=this.originalTouchAction,this.destroyed=true);}readPointerPosition(t){let e=this.element.getBoundingClientRect();this.screenPoint[0]=(t.clientX-e.left)/Math.max(1,e.width)*this.renderer.width,this.screenPoint[1]=(t.clientY-e.top)/Math.max(1,e.height)*this.renderer.height;}releaseDrag(t=[0,0,0]){if(this.activePointerId<0)return;let e=this.activePointerId;this.activePointerId=-1,this.selectedParticle=-1,this.simulation.endDrag(t,this.fixedTimeStep),this.element.hasPointerCapture(e)&&this.element.releasePointerCapture(e);}syncTouchAction(){this.element.style.touchAction=this.options.enabled?this.options.touchAction:this.originalTouchAction;}};async function vt(a){if(a===null||typeof a!="string")return a;let t=new Image;return t.decoding="async",t.crossOrigin="anonymous",await new Promise((e,s)=>{t.addEventListener("load",()=>e(),{once:true}),t.addEventListener("error",()=>s(new Error(`Unable to load cloth texture: ${a}`)),{once:true}),t.src=a;}),t}var Q=class{constructor(t){r(this,"container");r(this,"canvas");r(this,"context");r(this,"renderer");r(this,"ready");r(this,"options");r(this,"simulation");r(this,"fixedTimeStep");r(this,"pointerController");r(this,"currentTexture",null);r(this,"ownsCanvas");r(this,"externalAnimationLoop");r(this,"canvasAppended",false);r(this,"resizeObserver",null);r(this,"intersectionObserver",null);r(this,"debugPanel",null);r(this,"textureRequest",0);r(this,"animationFrame",0);r(this,"lastFrameTime",0);r(this,"started",false);r(this,"userPaused",false);r(this,"documentHidden",false);r(this,"offscreen",false);r(this,"destroyed",false);r(this,"lastWidth",0);r(this,"lastHeight",0);r(this,"statsFrameCount",0);r(this,"statsWindowStarted",0);r(this,"lastDebugUpdate",0);r(this,"statsValue",{fps:0,simulationMs:0,renderMs:0,particleCount:0,constraintCount:0,drawCalls:0});r(this,"simulateStep",t=>{this.simulation.step(t);});r(this,"onAnimationFrame",t=>{if(this.animationFrame=0,!this.canAnimate())return;let e=this.lastFrameTime===0?0:(t-this.lastFrameTime)/1e3;this.lastFrameTime=t,this.update(e,true),this.requestAnimationFrameIfNeeded();});r(this,"onResizeObserved",()=>this.resize());r(this,"onIntersection",t=>{let e=t[t.length-1];e&&(this.offscreen=!e.isIntersecting,this.syncAnimationState());});r(this,"onVisibilityChange",()=>{this.documentHidden=document.visibilityState==="hidden",this.syncAnimationState();});if(!t.container)throw new TypeError("createFlagCloth requires a container element.");this.container=t.container,this.options=Xt(t),this.ownsCanvas=!t.advanced?.canvas&&!t.advanced?.context,this.externalAnimationLoop=t.advanced?.externalAnimationLoop??false;let e=t.advanced?.context?.canvas;if(e&&!(e instanceof HTMLCanvasElement))throw new TypeError("advanced.context must belong to an HTMLCanvasElement.");if(this.canvas=e??t.advanced?.canvas??document.createElement("canvas"),t.advanced?.canvas&&t.advanced.context&&t.advanced.context.canvas!==t.advanced.canvas)throw new TypeError("advanced.canvas and advanced.context must refer to the same canvas.");let s=t.advanced?.context??this.canvas.getContext("webgl2",{alpha:this.options.renderer.alpha,antialias:this.options.renderer.antialias,desynchronized:this.options.renderer.desynchronized,powerPreference:this.options.renderer.powerPreference,premultipliedAlpha:true,preserveDrawingBuffer:false});if(!s)throw new Error("A WebGL2 rendering context is required.");this.context=s,this.simulation=this.createSimulation(),this.renderer=new N(this.canvas,this.context,this.simulation,this.options.renderer,this.options.material,this.options.lighting,this.options.camera),this.canvas.style.display="block",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.setAttribute("aria-label","flag-cloth"),this.ownsCanvas&&(this.container.appendChild(this.canvas),this.canvasAppended=true),this.fixedTimeStep=new X(this.options.simulation.fixedTimeStep,this.options.simulation.maxFrameDelta),this.pointerController=new W(this.canvas,this.renderer,this.simulation,this.options.interaction,this.options.simulation.fixedTimeStep),this.statsValue.particleCount=this.simulation.particleCount,this.statsValue.constraintCount=this.simulation.constraintCount,this.setupResizeObserver(),this.setupVisibilityObservers(),this.syncDebugPanel(),this.resize(),this.ready=this.setTexture(t.texture),t.autoStart!==false&&this.start();}get stats(){return this.statsValue}get particleCount(){return this.simulation.particleCount}get constraintCount(){return this.simulation.constraintCount}start(){this.assertAlive(),this.started=true,this.userPaused=false,this.lastFrameTime=0,this.requestAnimationFrameIfNeeded();}pause(){this.destroyed||(this.userPaused=true,this.cancelAnimationFrame());}resume(){this.assertAlive(),this.started=true,this.userPaused=false,this.lastFrameTime=0,this.requestAnimationFrameIfNeeded();}update(t,e=true){if(this.destroyed||!this.canAnimate())return;let s=performance.now();this.fixedTimeStep.advance(t,this.simulateStep);let i=performance.now();this.statsValue.simulationMs=i-s,e&&this.render(),this.updateStats(i);}render(){if(this.destroyed)return;let t=performance.now();this.renderer.render(),this.statsValue.renderMs=performance.now()-t,this.statsValue.drawCalls=this.renderer.drawCalls;}resize(){if(this.destroyed)return;let t=Math.max(0,Math.floor(this.container.clientWidth)),e=Math.max(0,Math.floor(this.container.clientHeight));if(t===0||e===0||t===this.lastWidth&&e===this.lastHeight)return;this.lastWidth=t,this.lastHeight=e;let s=typeof window>"u"?1:window.devicePixelRatio;this.renderer.resize(t,e,Math.min(s,this.options.renderer.maxPixelRatio));}async setTexture(t){this.assertAlive();let e=++this.textureRequest,s=await vt(t);this.destroyed||e!==this.textureRequest||(this.currentTexture=s,this.renderer.setTexture(s));}setWind(t){this.assertAlive(),this.options.wind={...this.options.wind,...t},this.simulation.setWind(t);}async setOptions(t){this.assertAlive();let e=t.width!==void 0&&t.width!==this.options.width||t.height!==void 0&&t.height!==this.options.height||t.segments?.x!==void 0&&t.segments.x!==this.options.segments.x||t.segments?.y!==void 0&&t.segments.y!==this.options.segments.y;t.width!==void 0&&(this.options.width=t.width),t.height!==void 0&&(this.options.height=t.height),t.segments&&(this.options.segments={...this.options.segments,...t.segments}),t.attachment!==void 0&&(this.options.attachment=t.attachment),t.wind&&(this.options.wind={...this.options.wind,...t.wind}),t.simulation&&(this.options.simulation={...this.options.simulation,...t.simulation},this.fixedTimeStep.configure(this.options.simulation.fixedTimeStep,this.options.simulation.maxFrameDelta)),t.interaction&&(this.options.interaction={...this.options.interaction,...t.interaction}),t.renderer&&(this.options.renderer=bt(this.options.renderer,t.renderer)),t.material&&(this.options.material={...this.options.material,...t.material}),t.lighting&&(this.options.lighting={...this.options.lighting,...t.lighting}),t.camera&&(this.options.camera={...this.options.camera,...t.camera}),t.visibility&&(this.options.visibility={...this.options.visibility,...t.visibility}),t.debug!==void 0&&(this.options.debug=xt(t.debug,this.options.debug)),e?this.rebuildCloth():(t.attachment!==void 0&&this.simulation.setAttachment(this.options.attachment),t.wind&&this.simulation.setWind(t.wind),t.simulation&&this.simulation.setSimulationOptions(t.simulation)),this.renderer.setOptions(this.options.renderer,this.options.material,this.options.lighting,this.options.camera),(e||t.renderer||t.camera)&&(this.lastWidth=0,this.lastHeight=0,this.resize()),this.pointerController.setOptions(this.options.interaction,this.options.simulation.fixedTimeStep),t.visibility&&this.setupVisibilityObservers(),t.debug!==void 0&&this.syncDebugPanel(),t.texture!==void 0&&await this.setTexture(t.texture);}reset(){this.assertAlive(),this.fixedTimeStep.reset(),this.simulation.reset(),this.render();}destroy(){this.destroyed||(this.destroyed=true,this.started=false,this.textureRequest+=1,this.cancelAnimationFrame(),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.intersectionObserver?.disconnect(),this.intersectionObserver=null,document.removeEventListener("visibilitychange",this.onVisibilityChange),this.pointerController.destroy(),this.debugPanel?.destroy(),this.debugPanel=null,this.currentTexture=null,this.renderer.destroy(),this.ownsCanvas&&this.canvasAppended&&this.canvas.remove());}createSimulation(){return new U({width:this.options.width,height:this.options.height,segmentsX:this.options.segments.x,segmentsY:this.options.segments.y,attachment:this.options.attachment,simulation:this.options.simulation,wind:this.options.wind})}rebuildCloth(){this.simulation=this.createSimulation(),this.renderer.setSimulation(this.simulation),this.renderer.setTexture(this.currentTexture),this.pointerController.setTargets(this.renderer,this.simulation),this.statsValue.particleCount=this.simulation.particleCount,this.statsValue.constraintCount=this.simulation.constraintCount,this.fixedTimeStep.reset();}setupResizeObserver(){this.resizeObserver?.disconnect(),!(typeof ResizeObserver>"u")&&(this.resizeObserver=new ResizeObserver(this.onResizeObserved),this.resizeObserver.observe(this.container));}setupVisibilityObservers(){this.intersectionObserver?.disconnect(),this.intersectionObserver=null,document.removeEventListener("visibilitychange",this.onVisibilityChange),this.offscreen=false,this.documentHidden=false,this.options.visibility.pauseWhenOffscreen&&typeof IntersectionObserver<"u"&&(this.intersectionObserver=new IntersectionObserver(this.onIntersection),this.intersectionObserver.observe(this.container)),this.options.visibility.pauseWhenDocumentHidden&&(this.documentHidden=document.visibilityState==="hidden",document.addEventListener("visibilitychange",this.onVisibilityChange)),this.syncAnimationState();}syncDebugPanel(){this.options.debug.enabled&&!this.debugPanel?this.debugPanel=new Y(this.container):!this.options.debug.enabled&&this.debugPanel&&(this.debugPanel.destroy(),this.debugPanel=null);}updateStats(t){this.statsWindowStarted===0&&(this.statsWindowStarted=t),this.statsFrameCount+=1;let e=t-this.statsWindowStarted;e>=500&&(this.statsValue.fps=this.statsFrameCount*1e3/e,this.statsFrameCount=0,this.statsWindowStarted=t),this.debugPanel&&t-this.lastDebugUpdate>=Math.max(100,this.options.debug.updateInterval)&&(this.debugPanel.update(this.statsValue),this.lastDebugUpdate=t);}syncAnimationState(){this.canAnimate()?(this.lastFrameTime=0,this.requestAnimationFrameIfNeeded()):this.cancelAnimationFrame();}canAnimate(){return this.started&&!this.userPaused&&!this.documentHidden&&!this.offscreen}requestAnimationFrameIfNeeded(){this.externalAnimationLoop||this.animationFrame!==0||!this.canAnimate()||typeof requestAnimationFrame>"u"||(this.animationFrame=requestAnimationFrame(this.onAnimationFrame));}cancelAnimationFrame(){this.animationFrame===0||typeof cancelAnimationFrame>"u"||(cancelAnimationFrame(this.animationFrame),this.animationFrame=0);}assertAlive(){if(this.destroyed)throw new Error("This FlagCloth instance has been destroyed.")}};function he(a){return new Q(a)}function Xt(a){return {width:a.width??3,height:a.height??2,segments:{...ot,...a.segments},attachment:a.attachment??"left",wind:{...at,...a.wind},simulation:{...ht,...a.simulation},interaction:{...lt,...a.interaction},renderer:bt(ct,a.renderer??{}),material:{...ut,...a.material},lighting:{...mt,...a.lighting},camera:{...ft,...a.camera},visibility:{...pt,...a.visibility},debug:xt(a.debug??false,gt)}}function bt(a,t){let e={...a,...t};if(t.preset!==void 0){let s=dt[t.preset];t.maxPixelRatio===void 0&&(e.maxPixelRatio=s.maxPixelRatio),t.shadingUpdateInterval===void 0&&(e.shadingUpdateInterval=s.shadingUpdateInterval),t.shadows===void 0&&(e.shadows=s.shadows);}return e.maxPixelRatio=Math.max(.5,e.maxPixelRatio),e}function xt(a,t){return typeof a=="boolean"?{...t,enabled:a}:{...t,...a}}export{N as a,U as b,X as c,Q as d,he as e};//# sourceMappingURL=chunk-ECLR4Q2O.js.map
84
+ //# sourceMappingURL=chunk-ECLR4Q2O.js.map