@tonybfox/threejs-tools 1.0.6 → 1.0.8

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
@@ -2,14 +2,14 @@
2
2
 
3
3
  A collection of utilities and tools for Three.js development, organized as a monorepo with separate packages for different functionalities. The root `@tonybfox/threejs-tools` package now bundles every tool so you can install a single npm package while still importing submodules (for example `@tonybfox/threejs-tools/camera` or `@tonybfox/threejs-tools/terrain`).
4
4
 
5
- ## 📦 Packages
5
+ ## Packages
6
6
 
7
- - **[@tonybfox/threejs-camera](./packages/camera/)** - Camera utilities and controls
8
- - **[@tonybfox/threejs-grid](./packages/grid/)** - Infinite grid component
9
- - **[@tonybfox/threejs-measurements](./packages/measurements/)** - Measurement tools for 3D scenes
10
- - **[@tonybfox/threejs-asset-loader](./packages/asset-loader/)** - Universal asset loader with progress tracking and caching
7
+ - **[@tonybfox/threejs-camera](https://github.com/tonybfox/threejs-tools/blob/main/examples/packages/camera/)** - Camera utilities and controls
8
+ - **[@tonybfox/threejs-grid](https://github.com/tonybfox/threejs-tools/blob/main/examples/packages/grid/)** - Infinite grid component
9
+ - **[@tonybfox/threejs-measurements](https://github.com/tonybfox/threejs-tools/blob/main/examples/packages/measurements/)** - Measurement tools for 3D scenes
10
+ - **[@tonybfox/threejs-asset-loader](https://github.com/tonybfox/threejs-tools/blob/main/example/packages/asset-loader/)** - Universal asset loader with progress tracking and caching
11
11
 
12
- ## 🛠️ Prerequisites
12
+ ## Prerequisites
13
13
 
14
14
  Make sure you have the following installed on your system:
15
15
 
@@ -22,7 +22,7 @@ If you don't have pnpm installed, you can install it globally:
22
22
  npm install -g pnpm
23
23
  ```
24
24
 
25
- ## 🚀 Installation
25
+ ## Installation
26
26
 
27
27
  1. **Clone the repository:**
28
28
 
@@ -39,7 +39,7 @@ npm install -g pnpm
39
39
 
40
40
  This will install all dependencies for the root workspace and all packages.
41
41
 
42
- ## 🔨 Building
42
+ ## Building
43
43
 
44
44
  ### Build the publishable bundle
45
45
 
@@ -81,7 +81,7 @@ To clean all build outputs:
81
81
  pnpm clean
82
82
  ```
83
83
 
84
- ## 🎮 Running Examples
84
+ ## Running Examples
85
85
 
86
86
  The project includes interactive examples demonstrating each package's functionality.
87
87
 
@@ -113,9 +113,9 @@ pnpm build
113
113
  pnpm preview
114
114
  ```
115
115
 
116
- ## 📁 Examples Overview
116
+ ## Examples Overview
117
117
 
118
- ### 🔧 Grid Package Example
118
+ ### Grid Package Example
119
119
 
120
120
  - **Location:** `/examples/grid/`
121
121
  - **Features:**
@@ -125,7 +125,7 @@ pnpm preview
125
125
  - Grid positioning and rotation
126
126
  - **Controls:** Use the control panel to modify grid properties
127
127
 
128
- ### 📷 Camera Package Example
128
+ ### Camera Package Example
129
129
 
130
130
  - **Location:** `/examples/camera/`
131
131
  - **Features:**
@@ -136,7 +136,7 @@ pnpm preview
136
136
  - Real-time camera info display
137
137
  - **Controls:** Click buttons to change camera views and modes
138
138
 
139
- ### 📏 Measurements Package Example
139
+ ### Measurements Package Example
140
140
 
141
141
  - **Location:** `/examples/measurements/`
142
142
  - **Features:**
@@ -148,7 +148,7 @@ pnpm preview
148
148
  - Interactive labels
149
149
  - **Usage:** Select a tool and click in the 3D scene to measure
150
150
 
151
- ### 📦 Asset Loader Package Example
151
+ ### Asset Loader Package Example
152
152
 
153
153
  - **Location:** `/examples/asset-loader/`
154
154
  - **Features:**
@@ -160,7 +160,76 @@ pnpm preview
160
160
  - Event-driven architecture
161
161
  - **Usage:** Use the control panel to create placeholders and see the loading system in action
162
162
 
163
- ### 🎮 Interactive Features
163
+ ### Outline Package Example
164
+
165
+ - **Location:** `/examples/outline/`
166
+ - **Features:**
167
+ - Mesh mode with inverted hull + edge lines (no post-processing)
168
+ - Post-processing mode with ID buffer edge detection
169
+ - Auto-updating outlines for animated objects
170
+ - Smart exclusions for helpers and gizmos
171
+ - **Usage:** Toggle outline modes and settings to compare visual styles
172
+
173
+ ### Terrain Package Example
174
+
175
+ - **Location:** `/examples/terrain/`
176
+ - **Features:**
177
+ - Real elevation data terrain mesh generation
178
+ - Configurable resolution and elevation scaling
179
+ - Optional imagery overlay and demo mode
180
+ - Loading events for progress feedback
181
+ - **Usage:** Adjust location and terrain settings to update the mesh
182
+
183
+ ### Transform Controls Package Example
184
+
185
+ - **Location:** `/examples/transform-controls/`
186
+ - **Features:**
187
+ - Translate, rotate, and scale gizmo controls
188
+ - Axis and plane constraints
189
+ - World vs local space modes
190
+ - Snap support for precise transforms
191
+ - **Usage:** Manipulate objects with the gizmo and toggle modes
192
+
193
+ ### View Helper Package Example
194
+
195
+ - **Location:** `/examples/view-helper/`
196
+ - **Features:**
197
+ - Clickable axis gizmo for quick camera reorientation
198
+ - Configurable size, colors, and labels
199
+ - Smooth animated transitions
200
+ - **Usage:** Click axis labels to snap the camera to preset views
201
+
202
+ ### Sun Light Package Example
203
+
204
+ - **Location:** `/examples/sunlight/`
205
+ - **Features:**
206
+ - Real-time sun position from latitude, longitude, and date
207
+ - Weather presets for color and intensity
208
+ - Sunrise/sunset color transitions based on solar altitude
209
+ - Optional system clock sync for live daylight simulation
210
+ - Directional light helper and scene objects to show shadows
211
+ - **Usage:** Adjust the control panel to explore lighting scenarios or enable real-time mode
212
+
213
+ ### Compass Package Example
214
+
215
+ - **Location:** `/examples/compass/`
216
+ - **Features:**
217
+ - Stylized compass gizmo with heading, latitude, and longitude
218
+ - Declination slider with live heading updates
219
+ - Location presets plus manual coordinate entry
220
+ - Optional dynamic north resolver
221
+ - **Usage:** Move the compass or adjust coordinates to see live updates
222
+
223
+ ### Combined Scene Example
224
+
225
+ - **Location:** `/examples/combined-scene/`
226
+ - **Features:**
227
+ - Terrain, sun lighting, and compass overlay in one scene
228
+ - Optional Mapbox imagery overlay for terrain
229
+ - Interactive control panel for location and lighting
230
+ - **Usage:** Use the control panel to explore combined tool behavior
231
+
232
+ ### Interactive Features
164
233
 
165
234
  Each example includes:
166
235
 
@@ -170,7 +239,7 @@ Each example includes:
170
239
  - **Real-time Updates:** Live parameter adjustment
171
240
  - **Performance Monitoring:** Optional FPS and render statistics
172
241
 
173
- ### 🛠 Example Development
242
+ ### Example Development
174
243
 
175
244
  #### Shared Utilities
176
245
 
@@ -198,7 +267,7 @@ Examples use Vite for development with:
198
267
  - Three.js optimization
199
268
  - Workspace linking for package imports
200
269
 
201
- ## 📦 Publishing to npm
270
+ ## Publishing to npm
202
271
 
203
272
  Steps to publish the unified `threejs-tools` package:
204
273
 
@@ -211,7 +280,7 @@ The published package exposes:
211
280
  - `@tonybfox/threejs-tools` – combined exports (tree-shakeable)
212
281
  - `@tonybfox/threejs-tools/<tool>` – direct submodule imports for each tool (`camera`, `terrain`, `measurements`, etc.)
213
282
 
214
- ## 🏗️ Development Workflow
283
+ ## Development Workflow
215
284
 
216
285
  ### Working on packages
217
286
 
@@ -234,7 +303,7 @@ The examples use workspace references (`workspace:*`), so your local changes wil
234
303
  2. Add a `package.json` with the `@tonybfox/threejs-*` naming convention
235
304
  3. The workspace will automatically include it
236
305
 
237
- ## 📝 Code Formatting
306
+ ## Code Formatting
238
307
 
239
308
  This project uses Prettier for code formatting:
240
309
 
@@ -246,7 +315,7 @@ pnpm format
246
315
  pnpm format:check
247
316
  ```
248
317
 
249
- ## 🏛️ Project Structure
318
+ ## Project Structure
250
319
 
251
320
  ```
252
321
  threejs-tools/
@@ -265,7 +334,7 @@ threejs-tools/
265
334
  └── tsconfig.json # TypeScript configuration
266
335
  ```
267
336
 
268
- ## 🔧 Scripts Reference
337
+ ## Scripts Reference
269
338
 
270
339
  | Script | Description |
271
340
  | --------------------- | -------------------------------------- |
@@ -276,7 +345,7 @@ threejs-tools/
276
345
  | `pnpm format` | Format all files with Prettier |
277
346
  | `pnpm format:check` | Check code formatting |
278
347
 
279
- ## 🚨 Troubleshooting
348
+ ## Troubleshooting
280
349
 
281
350
  ### Common Issues
282
351
 
@@ -292,7 +361,7 @@ threejs-tools/
292
361
  - Monitor memory usage with large scenes
293
362
  - Use appropriate LOD for complex geometries
294
363
 
295
- ## 🤝 Contributing
364
+ ## Contributing
296
365
 
297
366
  1. Fork the repository
298
367
  2. Create your feature branch (`git checkout -b feature/amazing-feature`)
@@ -304,11 +373,11 @@ threejs-tools/
304
373
  8. Push to the branch (`git push origin feature/amazing-feature`)
305
374
  9. Open a Pull Request
306
375
 
307
- ## 📄 License
376
+ ## License
308
377
 
309
378
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
310
379
 
311
- ## 🐛 Issues & Support
380
+ ## Issues & Support
312
381
 
313
382
  If you encounter any issues or have questions:
314
383
 
@@ -318,4 +387,4 @@ If you encounter any issues or have questions:
318
387
 
319
388
  ---
320
389
 
321
- Made with ❤️ for the Three.js community
390
+ Made with love for the Three.js community
@@ -1,4 +1,4 @@
1
- "use strict";var H=Object.create;var u=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var D=(n,c)=>{for(var e in c)u(n,e,{get:c[e],enumerable:!0})},b=(n,c,e,t)=>{if(c&&typeof c=="object"||typeof c=="function")for(let a of O(c))!x.call(n,a)&&a!==e&&u(n,a,{get:()=>c[a],enumerable:!(t=M(c,a))||t.enumerable});return n};var B=(n,c,e)=>(e=n!=null?H(P(n)):{},b(c||!n||!n.__esModule?u(e,"default",{value:n,enumerable:!0}):e,n)),z=n=>b(u({},"__esModule",{value:!0}),n);var j={};D(j,{AssetLoader:()=>E});module.exports=z(j);var o=B(require("three")),y=require("three/examples/jsm/loaders/GLTFLoader.js"),v=require("three/examples/jsm/loaders/FBXLoader.js"),R=require("three/examples/jsm/loaders/OBJLoader.js"),L=require("three/examples/jsm/loaders/USDLoader.js"),T=require("three/examples/jsm/loaders/ColladaLoader.js"),g=require("three/examples/jsm/loaders/STLLoader.js"),C=require("three/examples/jsm/loaders/PLYLoader.js"),w=require("three/examples/jsm/loaders/3MFLoader.js"),E=class extends o.EventDispatcher{constructor(){super();this.cache=new Map;this.placeholder=null;this.loadedAsset=null;this.lowResAsset=null;this.errorColor=16729156;this.errorOpacity=.5;this.gltfLoader=new y.GLTFLoader,this.fbxLoader=new v.FBXLoader,this.objLoader=new R.OBJLoader,this.usdLoader=new L.USDLoader,this.colladaLoader=new T.ColladaLoader,this.stlLoader=new g.STLLoader,this.plyLoader=new C.PLYLoader,this.threeMFLoader=new w.ThreeMFLoader}createPlaceholder(e,t=5227511,a=.3){let[s,p,l]=e,h=new o.BoxGeometry(s,p,l),r=new o.ShaderMaterial({side:o.DoubleSide,depthWrite:!1,blending:o.AdditiveBlending,transparent:!0,uniforms:{color:{value:new o.Color(t)},opacity:{value:a},fillProgress:{value:0},time:{value:0},isError:{value:0},yMin:{value:-p/2},yMax:{value:p/2}},vertexShader:`
1
+ "use strict";var H=Object.create;var u=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var D=(n,c)=>{for(var e in c)u(n,e,{get:c[e],enumerable:!0})},b=(n,c,e,t)=>{if(c&&typeof c=="object"||typeof c=="function")for(let a of O(c))!x.call(n,a)&&a!==e&&u(n,a,{get:()=>c[a],enumerable:!(t=M(c,a))||t.enumerable});return n};var B=(n,c,e)=>(e=n!=null?H(P(n)):{},b(c||!n||!n.__esModule?u(e,"default",{value:n,enumerable:!0}):e,n)),z=n=>b(u({},"__esModule",{value:!0}),n);var F={};D(F,{AssetLoader:()=>E});module.exports=z(F);var o=B(require("three")),y=require("three/examples/jsm/loaders/GLTFLoader.js"),v=require("three/examples/jsm/loaders/FBXLoader.js"),R=require("three/examples/jsm/loaders/OBJLoader.js"),L=require("three/examples/jsm/loaders/USDLoader.js"),T=require("three/examples/jsm/loaders/ColladaLoader.js"),g=require("three/examples/jsm/loaders/STLLoader.js"),C=require("three/examples/jsm/loaders/PLYLoader.js"),w=require("three/examples/jsm/loaders/3MFLoader.js"),E=class extends o.EventDispatcher{constructor(){super();this.cache=new Map;this.placeholder=null;this.loadedAsset=null;this.lowResAsset=null;this.errorColor=16729156;this.errorOpacity=.5;this.gltfLoader=new y.GLTFLoader,this.fbxLoader=new v.FBXLoader,this.objLoader=new R.OBJLoader,this.usdLoader=new L.USDLoader,this.colladaLoader=new T.ColladaLoader,this.stlLoader=new g.STLLoader,this.plyLoader=new C.PLYLoader,this.threeMFLoader=new w.ThreeMFLoader}createPlaceholder(e,t=5227511,a=.3){let[s,h,l]=e,p=new o.BoxGeometry(s,h,l),r=new o.ShaderMaterial({side:o.DoubleSide,depthWrite:!1,blending:o.AdditiveBlending,transparent:!0,uniforms:{color:{value:new o.Color(t)},opacity:{value:a},fillProgress:{value:0},time:{value:0},isError:{value:0},yMin:{value:-h/2},yMax:{value:h/2}},vertexShader:`
2
2
  varying vec3 vPosition;
3
3
  void main() {
4
4
  vPosition = position;
@@ -41,4 +41,4 @@
41
41
  vec3 finalColor = color + edgeIntensity * 0.5;
42
42
  gl_FragColor = vec4(finalColor, alpha);
43
43
  }
44
- `}),i=new o.Mesh(h,r);return this.positionAssetAtBottomCenter(i),i}updatePlaceholder(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let t=this.placeholder.material;t.uniforms&&t.uniforms.fillProgress&&(t.uniforms.fillProgress.value=e)}}setPlaceholderError(){if(this.placeholder&&this.placeholder instanceof o.Mesh){let e=this.placeholder.material;e.uniforms&&(e.uniforms.color&&(e.uniforms.color.value=new o.Color(this.errorColor)),e.uniforms.opacity&&(e.uniforms.opacity.value=this.errorOpacity),e.uniforms.fillProgress&&(e.uniforms.fillProgress.value=0),e.uniforms.isError&&(e.uniforms.isError.value=1))}}updatePlaceholderAnimation(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let t=this.placeholder.material;t.uniforms&&t.uniforms.time&&(t.uniforms.time.value+=e)}}positionAssetAtBottomCenter(e){e.updateMatrixWorld(!0);let t=new o.Box3().setFromObject(e);if(t.isEmpty())return;let a=t.getCenter(new o.Vector3),s=new o.Vector3(a.x,t.min.y-.01,a.z);!Number.isFinite(s.x)||!Number.isFinite(s.y)||!Number.isFinite(s.z)||(e.position.sub(s),e.userData.bottomCenterOffset=s,e.updateMatrixWorld(!0))}ensureBottomCenterOffset(e){let t=e.userData.bottomCenterOffset;if(t instanceof o.Vector3)return t;if(t&&typeof t=="object"){let{x:a=0,y:s=0,z:p=0}=t,l=new o.Vector3(a??0,s??0,p??0);return e.userData.bottomCenterOffset=l,l}return null}normalizeBottomCenterData(e){let t=this.ensureBottomCenterOffset(e)!==null;return e.children.forEach(a=>this.normalizeBottomCenterData(a)),t}async load(e){let{type:t,url:a,size:s,lowResUrl:p,enableCaching:l=!0,disablePlaceholder:h=!1,placeholderColor:r=5227511,placeholderOpacity:i=.4,errorColor:m=16729156,errorOpacity:A=.5}=e;if(l&&this.cache.has(a)){let d=this.cache.get(a).clone(!0);return this.normalizeBottomCenterData(d)?d.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(d),this.loadedAsset=d,this.dispatchEvent({type:"loaded",asset:d}),d}this.errorColor=m,this.errorOpacity=A,s&&!h&&(this.placeholder=this.createPlaceholder(s,r,i),this.dispatchEvent({type:"placeholderCreated",placeholder:this.placeholder}));try{if(p){let f=await this.loadModel(t,p,!0);this.lowResAsset=f,this.dispatchEvent({type:"lowResLoaded",lowRes:f})}let d=await this.loadModel(t,a,!1);if(this.loadedAsset=d,l){let f=d.clone(!0);this.normalizeBottomCenterData(f)?f.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(f),this.cache.set(a,f)}return this.dispatchEvent({type:"loaded",asset:d}),d}catch(d){throw this.setPlaceholderError(),this.dispatchEvent({type:"error",error:d}),d}}loadModel(e,t,a){return new Promise((s,p)=>{let l=r=>{let i=-1;r.lengthComputable&&r.total>0&&r.loaded<=r.total&&(i=r.loaded/r.total*100),this.dispatchEvent({type:"progress",loaded:r.loaded,total:r.total,percentage:i}),!a&&i>=0&&this.updatePlaceholder(i/100)},h=r=>{p(r)};switch(e){case"gltf":this.gltfLoader.load(t,r=>{let i=r.scene;this.positionAssetAtBottomCenter(i),s(i)},l,h);break;case"fbx":this.fbxLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,h);break;case"obj":this.objLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,h);break;case"usd":case"usdz":this.usdLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,h);break;case"dae":this.colladaLoader.load(t,r=>{let i=r.scene;this.positionAssetAtBottomCenter(i),s(i)},l,h);break;case"stl":this.stlLoader.load(t,r=>{let i=new o.MeshStandardMaterial({color:8947848}),m=new o.Mesh(r,i);this.positionAssetAtBottomCenter(m),s(m)},l,h);break;case"ply":this.plyLoader.load(t,r=>{let i=new o.MeshStandardMaterial({vertexColors:!0}),m=new o.Mesh(r,i);this.positionAssetAtBottomCenter(m),s(m)},l,h);break;case"3mf":this.threeMFLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,h);break;default:p(new Error(`Unsupported asset type: ${e}`))}})}getPlaceholder(){return this.placeholder}getAsset(){return this.loadedAsset}getLowResAsset(){return this.lowResAsset}clearCache(){this.cache.clear()}removeFromCache(e){this.cache.delete(e)}getCacheSize(){return this.cache.size}};0&&(module.exports={AssetLoader});
44
+ `}),i=new o.Mesh(p,r);return this.positionAssetAtBottomCenter(i),i}updatePlaceholder(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let t=this.placeholder.material;t.uniforms&&t.uniforms.fillProgress&&(t.uniforms.fillProgress.value=e)}}setPlaceholderError(){if(this.placeholder&&this.placeholder instanceof o.Mesh){let e=this.placeholder.material;e.uniforms&&(e.uniforms.color&&(e.uniforms.color.value=new o.Color(this.errorColor)),e.uniforms.opacity&&(e.uniforms.opacity.value=this.errorOpacity),e.uniforms.fillProgress&&(e.uniforms.fillProgress.value=0),e.uniforms.isError&&(e.uniforms.isError.value=1))}}updatePlaceholderAnimation(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let t=this.placeholder.material;t.uniforms&&t.uniforms.time&&(t.uniforms.time.value+=e)}}positionAssetAtBottomCenter(e){e.updateMatrixWorld(!0);let t=new o.Box3().setFromObject(e);if(t.isEmpty())return;let a=t.getCenter(new o.Vector3),s=new o.Vector3(a.x,t.min.y-.01,a.z);!Number.isFinite(s.x)||!Number.isFinite(s.y)||!Number.isFinite(s.z)||(e.position.sub(s),e.userData.bottomCenterOffset=s,e.updateMatrixWorld(!0))}ensureBottomCenterOffset(e){let t=e.userData.bottomCenterOffset;if(t instanceof o.Vector3)return t;if(t&&typeof t=="object"){let{x:a=0,y:s=0,z:h=0}=t,l=new o.Vector3(a??0,s??0,h??0);return e.userData.bottomCenterOffset=l,l}return null}normalizeBottomCenterData(e){let t=this.ensureBottomCenterOffset(e)!==null;return e.children.forEach(a=>this.normalizeBottomCenterData(a)),t}async load(e){let{type:t,url:a,size:s,lowResUrl:h,enableCaching:l=!0,disablePlaceholder:p=!1,placeholderColor:r=5227511,placeholderOpacity:i=.4,errorColor:m=16729156,errorOpacity:A=.5}=e;if(l&&this.cache.has(a)){let d=this.cache.get(a).clone(!0);return this.normalizeBottomCenterData(d)?d.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(d),this.loadedAsset=d,this.dispatchEvent({type:"loaded",asset:d}),d}this.errorColor=m,this.errorOpacity=A,s&&!p&&(this.placeholder=this.createPlaceholder(s,r,i),this.dispatchEvent({type:"placeholderCreated",placeholder:this.placeholder}));try{if(h){let f=await this.loadModel(t,h,!0);this.lowResAsset=f,this.dispatchEvent({type:"lowResLoaded",lowRes:f})}let d=await this.loadModel(t,a,!1);if(this.loadedAsset=d,l){let f=d.clone(!0);this.normalizeBottomCenterData(f)?f.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(f),this.cache.set(a,f)}return this.dispatchEvent({type:"loaded",asset:d}),d}catch(d){throw this.setPlaceholderError(),this.dispatchEvent({type:"error",error:d}),d}}loadModel(e,t,a){return new Promise((s,h)=>{let l=r=>{let i=-1;r.lengthComputable&&r.total>0&&r.loaded<=r.total&&(i=r.loaded/r.total*100),this.dispatchEvent({type:"progress",loaded:r.loaded,total:r.total,percentage:i}),!a&&i>=0&&this.updatePlaceholder(i/100)},p=r=>{h(r)};switch(e){case"gltf":this.gltfLoader.load(t,r=>{let i=r.scene;this.positionAssetAtBottomCenter(i),s(i)},l,p);break;case"fbx":this.fbxLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,p);break;case"obj":this.objLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,p);break;case"usd":case"usdz":this.usdLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,p);break;case"dae":this.colladaLoader.load(t,r=>{if(!r){h(new Error(`Failed to load Collada asset: ${t}`));return}let i=r.scene;this.positionAssetAtBottomCenter(i),s(i)},l,p);break;case"stl":this.stlLoader.load(t,r=>{let i=new o.MeshStandardMaterial({color:8947848}),m=new o.Mesh(r,i);this.positionAssetAtBottomCenter(m),s(m)},l,p);break;case"ply":this.plyLoader.load(t,r=>{let i=new o.MeshStandardMaterial({vertexColors:!0}),m=new o.Mesh(r,i);this.positionAssetAtBottomCenter(m),s(m)},l,p);break;case"3mf":this.threeMFLoader.load(t,r=>{this.positionAssetAtBottomCenter(r),s(r)},l,p);break;default:h(new Error(`Unsupported asset type: ${e}`))}})}getPlaceholder(){return this.placeholder}getAsset(){return this.loadedAsset}getLowResAsset(){return this.lowResAsset}clearCache(){this.cache.clear()}removeFromCache(e){this.cache.delete(e)}getCacheSize(){return this.cache.size}};0&&(module.exports={AssetLoader});
@@ -1 +1 @@
1
- import{a}from"../chunk-B75TYEOO.mjs";export{a as AssetLoader};
1
+ import{a}from"../chunk-WVTKB6A6.mjs";export{a as AssetLoader};
@@ -1 +1 @@
1
- "use strict";var O=Object.create;var E=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var b=(i,s)=>{for(var e in s)E(i,e,{get:s[e],enumerable:!0})},R=(i,s,e,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of z(s))!L.call(i,r)&&r!==e&&E(i,r,{get:()=>s[r],enumerable:!(t=P(s,r))||t.enumerable});return i};var x=(i,s,e)=>(e=i!=null?O(V(i)):{},R(s||!i||!i.__esModule?E(e,"default",{value:i,enumerable:!0}):e,i)),w=i=>R(E({},"__esModule",{value:!0}),i);var B={};b(B,{DualCameraControls:()=>H});module.exports=w(B);var n=x(require("three")),v=x(require("camera-controls")),y=!1,m=new n.Vector3,u=new n.Vector3,k=new n.Vector2;function A(){y||(v.default.install({THREE:n}),y=!0)}function C(i,s,e){return i?Array.isArray(i)?(e.set(i[0],i[1],i[2]),e):(e.copy(i),e):(e.set(s[0],s[1],s[2]),e)}var H=class extends v.default{constructor(e,t={}){A();let{domElement:r=e.domElement}=t,a=g(e,r),o=t.perspective??{},h=t.orthographic??{},c=new n.PerspectiveCamera(o.fov??60,a,o.near??.1,o.far??2e3);c.position.copy(C(o.position,[12,12,12],new n.Vector3)),o.zoom!==void 0&&(c.zoom=o.zoom,c.updateProjectionMatrix());let p=Math.max(h.size??20,.001)*.5,f=p*a,d=new n.OrthographicCamera(-f,f,p,-p,h.near??.1,h.far??2e3);d.position.copy(C(h.position,[12,12,12],new n.Vector3)),h.zoom!==void 0&&(d.zoom=h.zoom,d.updateProjectionMatrix());let T=t.initialMode??"perspective",l=T==="orthographic"?d:c;super(l,r);this.updateClock=new n.Clock;this.externalCamera=null;let M=C(t.initialTarget,[0,0,0],new n.Vector3);this.setLookAt(l.position.x,l.position.y,l.position.z,M.x,M.y,M.z,!1),this.renderer=e,this.domElementRef=r,this.perspectiveCamera=c,this.orthographicCamera=d,this.activeMode=T,this.minOrthoHalfHeight=p,this.updateInputBindingsForMode(T)}get mode(){return this.activeMode}get activeCamera(){return this.camera}switchToPerspective(e=!1){if(this.activeMode==="perspective"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),a=g(this.renderer,this.domElementRef);this.perspectiveCamera.aspect=a,this.perspectiveCamera.position.copy(r),this.perspectiveCamera.quaternion.copy(this.camera.quaternion),this.perspectiveCamera.up.copy(this.camera.up),this.perspectiveCamera.updateProjectionMatrix(),this.camera=this.perspectiveCamera,this.activeMode="perspective",this.updateInputBindingsForMode("perspective"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"orthographic",camera:this.perspectiveCamera})}switchToOrthographic(e=!1){if(this.activeMode==="orthographic"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),a=g(this.renderer,this.domElementRef);this.updateOrthographicFrustum(r,t,a),this.orthographicCamera.position.copy(r),this.orthographicCamera.quaternion.copy(this.camera.quaternion),this.orthographicCamera.up.copy(this.camera.up),this.orthographicCamera.updateProjectionMatrix(),this.camera=this.orthographicCamera,this.activeMode="orthographic",this.updateInputBindingsForMode("orthographic"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"perspective",camera:this.orthographicCamera})}toggleCameraMode(e=!1){this.activeMode==="perspective"?this.switchToOrthographic(e):this.switchToPerspective(e)}get isUsingExternalCamera(){return this.externalCamera!==null}setCamera(e,t,r=!1){let a=this.camera;this.externalCamera=e;let o=g(this.renderer,this.domElementRef);if(e.type==="PerspectiveCamera")e.aspect=o,e.updateProjectionMatrix();else if(e.type==="OrthographicCamera"){let p=e,d=(p.top-p.bottom)*.5*o;p.left=-d,p.right=d,p.updateProjectionMatrix()}this.camera=e;let h=e.type==="PerspectiveCamera"?"perspective":"orthographic";this.activeMode=h,this.updateInputBindingsForMode(h);let c=C(t,[0,0,0],m);this.setLookAt(e.position.x,e.position.y,e.position.z,c.x,c.y,c.z,r),this.dispatchEvent({type:"externalcamerachange",camera:e,previousCamera:a})}clearExternalCamera(e=!1){if(!this.externalCamera)return;let t=this.getTarget(m),r=this.getPosition(u);this.externalCamera=null;let a=this.activeMode==="orthographic"?this.orthographicCamera:this.perspectiveCamera;a.position.copy(r),a.quaternion.copy(this.camera.quaternion),a.up.copy(this.camera.up);let o=g(this.renderer,this.domElementRef);this.activeMode==="orthographic"?this.updateOrthographicFrustum(r,t,o):(this.perspectiveCamera.aspect=o,this.perspectiveCamera.updateProjectionMatrix()),this.camera=a,this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:this.activeMode,camera:a})}handleResize(e,t){let r=t===0?1:e/t;this.perspectiveCamera.aspect=r,this.perspectiveCamera.updateProjectionMatrix();let a=this.getTarget(m),o=this.getPosition(u);this.updateOrthographicFrustum(o,a,r),this.activeMode==="orthographic"&&(this.camera=this.orthographicCamera,this.setLookAt(o.x,o.y,o.z,a.x,a.y,a.z,!1))}moveCamera(e,t,r=!0){return C(e,[0,0,0],m),C(t,[0,0,0],u),this.setLookAt(m.x,m.y,m.z,u.x,u.y,u.z,r)}updateDelta(){let e=this.updateClock.getDelta();return super.update(e)}updateInputBindingsForMode(e){let{ACTION:t}=v.default;e==="orthographic"?(this.mouseButtons.left=t.TRUCK,this.mouseButtons.right=t.ROTATE,this.mouseButtons.wheel=t.ZOOM,this.touches.one=t.TOUCH_TRUCK,this.touches.two=t.TOUCH_ZOOM_TRUCK):(this.mouseButtons.left=t.ROTATE,this.mouseButtons.right=t.TRUCK,this.mouseButtons.wheel=t.DOLLY,this.touches.one=t.TOUCH_ROTATE,this.touches.two=t.TOUCH_DOLLY_TRUCK)}updateOrthographicFrustum(e,t,r){let a=Math.max(e.distanceTo(t),.001),o=this.perspectiveCamera.fov,h=Math.max(a*Math.tan(n.MathUtils.degToRad(o*.5)),this.minOrthoHalfHeight),c=h*r;this.orthographicCamera.left=-c,this.orthographicCamera.right=c,this.orthographicCamera.top=h,this.orthographicCamera.bottom=-h,this.orthographicCamera.updateProjectionMatrix()}};function g(i,s){let e=i.getSize(k);if(e.y>0)return e.x/e.y;let{clientWidth:t,clientHeight:r}=s;return r>0?t/r:1}0&&(module.exports={DualCameraControls});
1
+ "use strict";var O=Object.create;var l=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var b=(i,a)=>{for(var e in a)l(i,e,{get:a[e],enumerable:!0})},R=(i,a,e,t)=>{if(a&&typeof a=="object"||typeof a=="function")for(let r of z(a))!L.call(i,r)&&r!==e&&l(i,r,{get:()=>a[r],enumerable:!(t=P(a,r))||t.enumerable});return i};var x=(i,a,e)=>(e=i!=null?O(V(i)):{},R(a||!i||!i.__esModule?l(e,"default",{value:i,enumerable:!0}):e,i)),w=i=>R(l({},"__esModule",{value:!0}),i);var U={};b(U,{DualCameraControls:()=>H});module.exports=w(U);var n=x(require("three")),v=x(require("camera-controls")),y=!1,m=new n.Vector3,u=new n.Vector3,k=new n.Vector2;function A(){y||(v.default.install({THREE:n}),y=!0)}function C(i,a,e){return i?Array.isArray(i)?(e.set(i[0],i[1],i[2]),e):(e.copy(i),e):(e.set(a[0],a[1],a[2]),e)}var H=class extends v.default{constructor(e,t={}){A();let{domElement:r=e.domElement}=t,o=g(e,r),s=t.perspective??{},h=t.orthographic??{},c=new n.PerspectiveCamera(s.fov??60,o,s.near??.1,s.far??2e3);c.position.copy(C(s.position,[12,12,12],new n.Vector3)),s.zoom!==void 0&&(c.zoom=s.zoom,c.updateProjectionMatrix());let p=Math.max(h.size??20,.001)*.5,T=p*o,d=new n.OrthographicCamera(-T,T,p,-p,h.near??.1,h.far??2e3);d.position.copy(C(h.position,[12,12,12],new n.Vector3)),h.zoom!==void 0&&(d.zoom=h.zoom,d.updateProjectionMatrix());let f=t.initialMode??"perspective",E=f==="orthographic"?d:c;super(E,r);this.updateTimer=B();this.externalCamera=null;let M=C(t.initialTarget,[0,0,0],new n.Vector3);this.setLookAt(E.position.x,E.position.y,E.position.z,M.x,M.y,M.z,!1),this.renderer=e,this.domElementRef=r,this.perspectiveCamera=c,this.orthographicCamera=d,this.activeMode=f,this.minOrthoHalfHeight=p,this.updateInputBindingsForMode(f)}get mode(){return this.activeMode}get activeCamera(){return this.camera}switchToPerspective(e=!1){if(this.activeMode==="perspective"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),o=g(this.renderer,this.domElementRef);this.perspectiveCamera.aspect=o,this.perspectiveCamera.position.copy(r),this.perspectiveCamera.quaternion.copy(this.camera.quaternion),this.perspectiveCamera.up.copy(this.camera.up),this.perspectiveCamera.updateProjectionMatrix(),this.camera=this.perspectiveCamera,this.activeMode="perspective",this.updateInputBindingsForMode("perspective"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"orthographic",camera:this.perspectiveCamera})}switchToOrthographic(e=!1){if(this.activeMode==="orthographic"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),o=g(this.renderer,this.domElementRef);this.updateOrthographicFrustum(r,t,o),this.orthographicCamera.position.copy(r),this.orthographicCamera.quaternion.copy(this.camera.quaternion),this.orthographicCamera.up.copy(this.camera.up),this.orthographicCamera.updateProjectionMatrix(),this.camera=this.orthographicCamera,this.activeMode="orthographic",this.updateInputBindingsForMode("orthographic"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"perspective",camera:this.orthographicCamera})}toggleCameraMode(e=!1){this.activeMode==="perspective"?this.switchToOrthographic(e):this.switchToPerspective(e)}get isUsingExternalCamera(){return this.externalCamera!==null}setCamera(e,t,r=!1){let o=this.camera;this.externalCamera=e;let s=g(this.renderer,this.domElementRef);if(e.type==="PerspectiveCamera")e.aspect=s,e.updateProjectionMatrix();else if(e.type==="OrthographicCamera"){let p=e,d=(p.top-p.bottom)*.5*s;p.left=-d,p.right=d,p.updateProjectionMatrix()}this.camera=e;let h=e.type==="PerspectiveCamera"?"perspective":"orthographic";this.activeMode=h,this.updateInputBindingsForMode(h);let c=C(t,[0,0,0],m);this.setLookAt(e.position.x,e.position.y,e.position.z,c.x,c.y,c.z,r),this.dispatchEvent({type:"externalcamerachange",camera:e,previousCamera:o})}clearExternalCamera(e=!1){if(!this.externalCamera)return;let t=this.getTarget(m),r=this.getPosition(u);this.externalCamera=null;let o=this.activeMode==="orthographic"?this.orthographicCamera:this.perspectiveCamera;o.position.copy(r),o.quaternion.copy(this.camera.quaternion),o.up.copy(this.camera.up);let s=g(this.renderer,this.domElementRef);this.activeMode==="orthographic"?this.updateOrthographicFrustum(r,t,s):(this.perspectiveCamera.aspect=s,this.perspectiveCamera.updateProjectionMatrix()),this.camera=o,this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:this.activeMode,camera:o})}handleResize(e,t){let r=t===0?1:e/t;this.perspectiveCamera.aspect=r,this.perspectiveCamera.updateProjectionMatrix();let o=this.getTarget(m),s=this.getPosition(u);this.updateOrthographicFrustum(s,o,r),this.activeMode==="orthographic"&&(this.camera=this.orthographicCamera,this.setLookAt(s.x,s.y,s.z,o.x,o.y,o.z,!1))}moveCamera(e,t,r=!0){return C(e,[0,0,0],m),C(t,[0,0,0],u),this.setLookAt(m.x,m.y,m.z,u.x,u.y,u.z,r)}updateDelta(e){this.updateTimer.update?.(e);let t=this.updateTimer.getDelta();return super.update(t)}updateInputBindingsForMode(e){let{ACTION:t}=v.default;e==="orthographic"?(this.mouseButtons.left=t.TRUCK,this.mouseButtons.right=t.ROTATE,this.mouseButtons.wheel=t.ZOOM,this.touches.one=t.TOUCH_TRUCK,this.touches.two=t.TOUCH_ZOOM_TRUCK):(this.mouseButtons.left=t.ROTATE,this.mouseButtons.right=t.TRUCK,this.mouseButtons.wheel=t.DOLLY,this.touches.one=t.TOUCH_ROTATE,this.touches.two=t.TOUCH_DOLLY_TRUCK)}updateOrthographicFrustum(e,t,r){let o=Math.max(e.distanceTo(t),.001),s=this.perspectiveCamera.fov,h=Math.max(o*Math.tan(n.MathUtils.degToRad(s*.5)),this.minOrthoHalfHeight),c=h*r;this.orthographicCamera.left=-c,this.orthographicCamera.right=c,this.orthographicCamera.top=h,this.orthographicCamera.bottom=-h,this.orthographicCamera.updateProjectionMatrix()}};function B(){let i=n.Timer;if(i){let a=new i;return a.reset(),a}return new n.Clock}function g(i,a){let e=i.getSize(k);if(e.y>0)return e.x/e.y;let{clientWidth:t,clientHeight:r}=a;return r>0?t/r:1}0&&(module.exports={DualCameraControls});
@@ -48,7 +48,7 @@ declare class DualCameraControls extends CameraControls {
48
48
  private readonly domElementRef;
49
49
  private activeMode;
50
50
  private readonly minOrthoHalfHeight;
51
- private readonly updateClock;
51
+ private readonly updateTimer;
52
52
  private externalCamera;
53
53
  constructor(renderer: THREE.WebGLRenderer, options?: DualCameraControlsOptions);
54
54
  get mode(): CameraMode;
@@ -95,7 +95,7 @@ declare class DualCameraControls extends CameraControls {
95
95
  * Updates the controls using an internally managed clock.
96
96
  * Useful when you don't want to pass delta time each frame.
97
97
  */
98
- updateDelta(): ReturnType<CameraControls['update']>;
98
+ updateDelta(timestamp?: number): ReturnType<CameraControls['update']>;
99
99
  private updateInputBindingsForMode;
100
100
  private updateOrthographicFrustum;
101
101
  }
@@ -48,7 +48,7 @@ declare class DualCameraControls extends CameraControls {
48
48
  private readonly domElementRef;
49
49
  private activeMode;
50
50
  private readonly minOrthoHalfHeight;
51
- private readonly updateClock;
51
+ private readonly updateTimer;
52
52
  private externalCamera;
53
53
  constructor(renderer: THREE.WebGLRenderer, options?: DualCameraControlsOptions);
54
54
  get mode(): CameraMode;
@@ -95,7 +95,7 @@ declare class DualCameraControls extends CameraControls {
95
95
  * Updates the controls using an internally managed clock.
96
96
  * Useful when you don't want to pass delta time each frame.
97
97
  */
98
- updateDelta(): ReturnType<CameraControls['update']>;
98
+ updateDelta(timestamp?: number): ReturnType<CameraControls['update']>;
99
99
  private updateInputBindingsForMode;
100
100
  private updateOrthographicFrustum;
101
101
  }
@@ -1 +1 @@
1
- import{a}from"../chunk-OJFYE56U.mjs";export{a as DualCameraControls};
1
+ import{a}from"../chunk-MJRTSO3X.mjs";export{a as DualCameraControls};
@@ -0,0 +1 @@
1
+ import*as e from"three";var p={x:"#ed4358",y:"#82cc19",z:"#3185eb"},E=class extends e.EventDispatcher{constructor(t,s,i={}){super();this.viewport=new e.Vector4;this.animating=!1;this.targetPosition=new e.Vector3;this.targetQuaternion=new e.Quaternion;this.q1=new e.Quaternion;this.q2=new e.Quaternion;this.dummy=new e.Object3D;this.radius=0;this.turnRate=2*Math.PI;this.tempVecA=new e.Vector3;this.interactiveObjects=[];this.raycaster=new e.Raycaster;this.mouse=new e.Vector2;this.controls=i.controls,this.camera=this.controls?.camera??t,this.domElement=s||document.body;let a=i.center??(this.controls?this.controls.getTarget(new e.Vector3):new e.Vector3);this.options={container:i.container||document.body,size:i.size||128,position:i.position||"bottom-right",offset:i.offset||{x:20,y:20},center:a.clone(),labels:{x:i.labels?.x||"x",y:i.labels?.y||"y",z:i.labels?.z||"z",...i.labels}},this.center=this.options.center.clone(),this.scene=new e.Scene,this.scene.background=null,this.orthoCamera=new e.OrthographicCamera(-2,2,2,-2,0,4),this.orthoCamera.position.set(0,0,2),this.createAxes(),this.createSprites(),this.setupEventListeners()}syncActiveCamera(){return this.controls&&(this.camera=this.controls.camera),this.camera}getCameraPosition(t){return this.controls?this.controls.getPosition(t):t.copy(this.camera.position)}createAxes(){let t=new e.CylinderGeometry(.04,.04,.8,5).rotateZ(-Math.PI/2).translate(.4,0,0),s=new e.MeshBasicMaterial({color:p.x,toneMapped:!1}),i=new e.MeshBasicMaterial({color:p.y,toneMapped:!1}),a=new e.MeshBasicMaterial({color:p.z,toneMapped:!1});this.axes={x:new e.Mesh(t.clone(),s),y:new e.Mesh(t.clone(),i),z:new e.Mesh(t.clone(),a)},this.axes.y.rotation.z=Math.PI/2,this.axes.z.rotation.y=-Math.PI/2,this.scene.add(this.axes.x),this.scene.add(this.axes.y),this.scene.add(this.axes.z)}createSprites(){let t=this.createSprite(p.x,this.options.labels.x),s=this.createSprite(p.y,this.options.labels.y),i=this.createSprite(p.z,this.options.labels.z),a=this.createSprite(p.x),n=this.createSprite(p.y),r=this.createSprite(p.z);this.sprites={posX:t,posY:s,posZ:i,negX:a,negY:n,negZ:r},this.sprites.posX.position.set(1,0,0),this.sprites.posY.position.set(0,1,0),this.sprites.posZ.position.set(0,0,1),this.sprites.negX.position.set(-1,0,0),this.sprites.negY.position.set(0,-1,0),this.sprites.negZ.position.set(0,0,-1),this.sprites.negX.material.opacity=.2,this.sprites.negY.material.opacity=.2,this.sprites.negZ.material.opacity=.2,this.sprites.posX.userData.type="posX",this.sprites.posY.userData.type="posY",this.sprites.posZ.userData.type="posZ",this.sprites.negX.userData.type="negX",this.sprites.negY.userData.type="negY",this.sprites.negZ.userData.type="negZ",Object.values(this.sprites).forEach(o=>{this.scene.add(o),this.interactiveObjects.push(o)})}createSprite(t,s){let i=window.devicePixelRatio||1,a=128*i,n=28*i,r=document.createElement("canvas");r.width=a,r.height=a;let o=r.getContext("2d");o.imageSmoothingEnabled=!0,o.imageSmoothingQuality="high",o.scale(i,i);let c=a/(2*i),l=n/i;o.beginPath(),o.arc(c,c,l,0,2*Math.PI),o.closePath(),o.fillStyle=t,o.fill(),s&&(o.font="bold 48px Arial, sans-serif",o.textAlign="center",o.textBaseline="middle",o.fillStyle="#ffffff",o.strokeStyle="#000000",o.lineWidth=2,o.strokeText(s,c,c),o.fillText(s,c,c));let h=new e.CanvasTexture(r);return h.colorSpace=e.SRGBColorSpace,h.generateMipmaps=!1,h.minFilter=e.LinearFilter,h.magFilter=e.LinearFilter,new e.Sprite(new e.SpriteMaterial({map:h,toneMapped:!1,alphaTest:.1}))}setupEventListeners(){this.pointerDownHandler=t=>{this.handleClick(t)},this.domElement.addEventListener("pointerdown",this.pointerDownHandler)}render(t){this.renderer=t;let s=this.syncActiveCamera();this.scene.quaternion.copy(s.quaternion).invert(),this.scene.updateMatrixWorld();let i=this.options.size,a=t.domElement.width/t.getPixelRatio(),n=t.domElement.height/t.getPixelRatio(),r,o;switch(this.options.position){case"top-left":r=this.options.offset.x,o=n-i-this.options.offset.y;break;case"top-right":r=a-i-this.options.offset.x,o=n-i-this.options.offset.y;break;case"bottom-left":r=this.options.offset.x,o=this.options.offset.y;break;case"bottom-right":default:r=a-i-this.options.offset.x,o=this.options.offset.y;break}t.getViewport(this.viewport);let c=new e.Vector4;t.getScissor(c);let l=t.getScissorTest(),h=t.getRenderTarget(),m=t.getActiveCubeFace(),u=t.getActiveMipmapLevel(),d=t.autoClear;t.setRenderTarget(null),t.setViewport(r,o,i,i),t.autoClear=!1,t.setScissorTest(!0),t.setScissor(r,o,i,i),t.clearDepth(),t.render(this.scene,this.orthoCamera),t.setRenderTarget(h,m,u),t.setViewport(this.viewport.x,this.viewport.y,this.viewport.z,this.viewport.w),t.setScissor(c),t.setScissorTest(l),t.autoClear=d}handleClick(t){if(this.animating||!this.renderer)return!1;this.syncActiveCamera();let s=this.domElement.getBoundingClientRect(),i=this.options.size,a,n;switch(this.options.position){case"top-left":a=s.left+this.options.offset.x,n=s.top+this.options.offset.y;break;case"top-right":a=s.left+s.width-i-this.options.offset.x,n=s.top+this.options.offset.y;break;case"bottom-left":a=s.left+this.options.offset.x,n=s.top+s.height-i-this.options.offset.y;break;case"bottom-right":default:a=s.left+s.width-i-this.options.offset.x,n=s.top+s.height-i-this.options.offset.y;break}if(this.mouse.x=(t.clientX-a)/i*2-1,this.mouse.y=-((t.clientY-n)/i)*2+1,this.mouse.x<-1||this.mouse.x>1||this.mouse.y<-1||this.mouse.y>1)return!1;this.raycaster.setFromCamera(this.mouse,this.orthoCamera);let r=this.raycaster.intersectObjects(this.interactiveObjects);if(r.length>0){let c=r[0].object;return this.prepareAnimationData(c,this.center),this.controls?this.startControlsAnimation(this.center):(this.animating=!0,this.dispatchEvent({type:"animationStart"})),!0}return!1}prepareAnimationData(t,s){switch(t.userData.type){case"posX":this.targetPosition.set(1,0,0),this.targetQuaternion.setFromEuler(new e.Euler(0,Math.PI*.5,0));break;case"posY":this.targetPosition.set(0,1,0),this.targetQuaternion.setFromEuler(new e.Euler(-Math.PI*.5,0,0));break;case"posZ":this.targetPosition.set(0,0,1),this.targetQuaternion.setFromEuler(new e.Euler);break;case"negX":this.targetPosition.set(-1,0,0),this.targetQuaternion.setFromEuler(new e.Euler(0,-Math.PI*.5,0));break;case"negY":this.targetPosition.set(0,-1,0),this.targetQuaternion.setFromEuler(new e.Euler(Math.PI*.5,0,0));break;case"negZ":this.targetPosition.set(0,0,-1),this.targetQuaternion.setFromEuler(new e.Euler(0,Math.PI,0));break;default:console.error("ViewHelper: Invalid axis.");return}let i=this.getCameraPosition(this.tempVecA);this.radius=i.distanceTo(s),this.targetPosition.multiplyScalar(this.radius).add(s),this.dummy.position.copy(s),this.dummy.lookAt(i),this.q1.copy(this.dummy.quaternion),this.dummy.lookAt(this.targetPosition),this.q2.copy(this.dummy.quaternion)}startControlsAnimation(t){let s=this.controls;if(!s)return;s.enabled=!1,s.stop?.(),this.animating=!0,this.dispatchEvent({type:"animationStart"});let i=()=>{s.setLookAt(this.targetPosition.x,this.targetPosition.y,this.targetPosition.z,t.x,t.y,t.z,!0),setTimeout(()=>{s.enabled=!0},100)};try{Promise.resolve(i()).catch(a=>{console.warn("ViewHelper: Unable to set camera look-at.",a)}).finally(()=>{this.animating=!1,this.dispatchEvent({type:"animationEnd"})})}catch(a){console.warn("ViewHelper: Unable to set camera look-at.",a),this.animating=!1,this.dispatchEvent({type:"animationEnd"})}}update(t){if(this.syncActiveCamera(),this.controls||!this.animating)return;let s=t*this.turnRate;this.q1.rotateTowards(this.q2,s),this.camera.position.set(0,0,1).applyQuaternion(this.q1).multiplyScalar(this.radius).add(this.center),this.camera.quaternion.rotateTowards(this.targetQuaternion,s),this.q1.angleTo(this.q2)===0&&(this.animating=!1,this.dispatchEvent({type:"animationEnd"}))}setLabels(t,s,i){t!==void 0&&(this.options.labels.x=t),s!==void 0&&(this.options.labels.y=s),i!==void 0&&(this.options.labels.z=i),this.updateLabels()}updateLabels(){this.sprites.posX.material.map?.dispose(),this.sprites.posY.material.map?.dispose(),this.sprites.posZ.material.map?.dispose(),this.sprites.posX.material.dispose(),this.sprites.posY.material.dispose(),this.sprites.posZ.material.dispose();let t=this.createSprite(p.x,this.options.labels.x),s=this.createSprite(p.y,this.options.labels.y),i=this.createSprite(p.z,this.options.labels.z);this.sprites.posX.material=t.material,this.sprites.posY.material=s.material,this.sprites.posZ.material=i.material}dispose(){this.axes.x.geometry.dispose(),this.axes.y.geometry.dispose(),this.axes.z.geometry.dispose(),this.axes.x.material.dispose(),this.axes.y.material.dispose(),this.axes.z.material.dispose(),Object.values(this.sprites).forEach(t=>{t.material.map?.dispose(),t.material.dispose()}),this.pointerDownHandler&&this.domElement.removeEventListener("pointerdown",this.pointerDownHandler)}};export{E as a};
@@ -0,0 +1 @@
1
+ import*as o from"three";import f from"camera-controls";var M=!1,m=new o.Vector3,u=new o.Vector3,R=new o.Vector2;function x(){M||(f.install({THREE:o}),M=!0)}function C(n,p,e){return n?Array.isArray(n)?(e.set(n[0],n[1],n[2]),e):(e.copy(n),e):(e.set(p[0],p[1],p[2]),e)}var H=class extends f{constructor(e,t={}){x();let{domElement:r=e.domElement}=t,i=g(e,r),a=t.perspective??{},s=t.orthographic??{},h=new o.PerspectiveCamera(a.fov??60,i,a.near??.1,a.far??2e3);h.position.copy(C(a.position,[12,12,12],new o.Vector3)),a.zoom!==void 0&&(h.zoom=a.zoom,h.updateProjectionMatrix());let c=Math.max(s.size??20,.001)*.5,l=c*i,d=new o.OrthographicCamera(-l,l,c,-c,s.near??.1,s.far??2e3);d.position.copy(C(s.position,[12,12,12],new o.Vector3)),s.zoom!==void 0&&(d.zoom=s.zoom,d.updateProjectionMatrix());let v=t.initialMode??"perspective",E=v==="orthographic"?d:h;super(E,r);this.updateTimer=y();this.externalCamera=null;let T=C(t.initialTarget,[0,0,0],new o.Vector3);this.setLookAt(E.position.x,E.position.y,E.position.z,T.x,T.y,T.z,!1),this.renderer=e,this.domElementRef=r,this.perspectiveCamera=h,this.orthographicCamera=d,this.activeMode=v,this.minOrthoHalfHeight=c,this.updateInputBindingsForMode(v)}get mode(){return this.activeMode}get activeCamera(){return this.camera}switchToPerspective(e=!1){if(this.activeMode==="perspective"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),i=g(this.renderer,this.domElementRef);this.perspectiveCamera.aspect=i,this.perspectiveCamera.position.copy(r),this.perspectiveCamera.quaternion.copy(this.camera.quaternion),this.perspectiveCamera.up.copy(this.camera.up),this.perspectiveCamera.updateProjectionMatrix(),this.camera=this.perspectiveCamera,this.activeMode="perspective",this.updateInputBindingsForMode("perspective"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"orthographic",camera:this.perspectiveCamera})}switchToOrthographic(e=!1){if(this.activeMode==="orthographic"&&!this.externalCamera)return;this.externalCamera=null;let t=this.getTarget(m),r=this.getPosition(u),i=g(this.renderer,this.domElementRef);this.updateOrthographicFrustum(r,t,i),this.orthographicCamera.position.copy(r),this.orthographicCamera.quaternion.copy(this.camera.quaternion),this.orthographicCamera.up.copy(this.camera.up),this.orthographicCamera.updateProjectionMatrix(),this.camera=this.orthographicCamera,this.activeMode="orthographic",this.updateInputBindingsForMode("orthographic"),this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:"perspective",camera:this.orthographicCamera})}toggleCameraMode(e=!1){this.activeMode==="perspective"?this.switchToOrthographic(e):this.switchToPerspective(e)}get isUsingExternalCamera(){return this.externalCamera!==null}setCamera(e,t,r=!1){let i=this.camera;this.externalCamera=e;let a=g(this.renderer,this.domElementRef);if(e.type==="PerspectiveCamera")e.aspect=a,e.updateProjectionMatrix();else if(e.type==="OrthographicCamera"){let c=e,d=(c.top-c.bottom)*.5*a;c.left=-d,c.right=d,c.updateProjectionMatrix()}this.camera=e;let s=e.type==="PerspectiveCamera"?"perspective":"orthographic";this.activeMode=s,this.updateInputBindingsForMode(s);let h=C(t,[0,0,0],m);this.setLookAt(e.position.x,e.position.y,e.position.z,h.x,h.y,h.z,r),this.dispatchEvent({type:"externalcamerachange",camera:e,previousCamera:i})}clearExternalCamera(e=!1){if(!this.externalCamera)return;let t=this.getTarget(m),r=this.getPosition(u);this.externalCamera=null;let i=this.activeMode==="orthographic"?this.orthographicCamera:this.perspectiveCamera;i.position.copy(r),i.quaternion.copy(this.camera.quaternion),i.up.copy(this.camera.up);let a=g(this.renderer,this.domElementRef);this.activeMode==="orthographic"?this.updateOrthographicFrustum(r,t,a):(this.perspectiveCamera.aspect=a,this.perspectiveCamera.updateProjectionMatrix()),this.camera=i,this.setLookAt(r.x,r.y,r.z,t.x,t.y,t.z,e),this.dispatchEvent({type:"modechange",mode:this.activeMode,previousMode:this.activeMode,camera:i})}handleResize(e,t){let r=t===0?1:e/t;this.perspectiveCamera.aspect=r,this.perspectiveCamera.updateProjectionMatrix();let i=this.getTarget(m),a=this.getPosition(u);this.updateOrthographicFrustum(a,i,r),this.activeMode==="orthographic"&&(this.camera=this.orthographicCamera,this.setLookAt(a.x,a.y,a.z,i.x,i.y,i.z,!1))}moveCamera(e,t,r=!0){return C(e,[0,0,0],m),C(t,[0,0,0],u),this.setLookAt(m.x,m.y,m.z,u.x,u.y,u.z,r)}updateDelta(e){this.updateTimer.update?.(e);let t=this.updateTimer.getDelta();return super.update(t)}updateInputBindingsForMode(e){let{ACTION:t}=f;e==="orthographic"?(this.mouseButtons.left=t.TRUCK,this.mouseButtons.right=t.ROTATE,this.mouseButtons.wheel=t.ZOOM,this.touches.one=t.TOUCH_TRUCK,this.touches.two=t.TOUCH_ZOOM_TRUCK):(this.mouseButtons.left=t.ROTATE,this.mouseButtons.right=t.TRUCK,this.mouseButtons.wheel=t.DOLLY,this.touches.one=t.TOUCH_ROTATE,this.touches.two=t.TOUCH_DOLLY_TRUCK)}updateOrthographicFrustum(e,t,r){let i=Math.max(e.distanceTo(t),.001),a=this.perspectiveCamera.fov,s=Math.max(i*Math.tan(o.MathUtils.degToRad(a*.5)),this.minOrthoHalfHeight),h=s*r;this.orthographicCamera.left=-h,this.orthographicCamera.right=h,this.orthographicCamera.top=s,this.orthographicCamera.bottom=-s,this.orthographicCamera.updateProjectionMatrix()}};function y(){let n=o.Timer;if(n){let p=new n;return p.reset(),p}return new o.Clock}function g(n,p){let e=n.getSize(R);if(e.y>0)return e.x/e.y;let{clientWidth:t,clientHeight:r}=p;return r>0?t/r:1}export{H as a};
@@ -0,0 +1 @@
1
+ import*as a from"three";import{CSS2DObject as m}from"three/examples/jsm/renderers/CSS2DRenderer.js";var u=(i=>(i.VERTEX="vertex",i.FACE="face",i.EDGE="edge",i.DISABLED="disabled",i))(u||{});var h=class extends a.EventDispatcher{constructor(e,t,i={}){super();this.measurements=[];this.raycaster=new a.Raycaster;this.isInteractive=!1;this.domElement=null;this.controls=null;this.defaultTargets=[];this.activeTargets=[];this.currentMeasurement=null;this.activeInteractionOptions=null;this.pendingMeasurementOptions=null;this.previewLine=null;this.previewLabel=null;this.snapMarker=null;this.originalCursor="";this.cursorHidden=!1;this.defaultOptions={lineColor:16711680,labelColor:"#ffffff",lineWidth:2,fontSize:16,fontFamily:"Arial, sans-serif",snapMode:"vertex",snapEnabled:!0,snapDistance:.05,targets:[],isDynamic:!1};this.previewColor=65535;this.markerColor=65280;this.markerSize=.08;this.markerVisible=!0;this.isEditMode=!1;this.editingMeasurement=null;this.editingPoint=null;this.startEditSprite=null;this.endEditSprite=null;this.editSpriteMaterial=null;this.isDragging=!1;this.onMouseClick=e=>{if(!this.isInteractive)return;let t=this.getSnapResult(e);t&&(this.currentMeasurement?this.completeMeasurement(t):this.startMeasurement(t))};this.onMouseMove=e=>{if(!this.isInteractive)return;let t=this.getSnapResult(e);if(!t){this.hideSnapMarker(),this.showCursor();return}this.currentMeasurement?(this.updateSnapMarker(t.point,!0),this.hideCursor(),this.updatePreview(t.point)):(this.updateSnapMarker(t.point,!0),this.hideCursor())};this.onKeyDown=e=>{this.isInteractive&&e.key==="Escape"&&this.cancelCurrentMeasurement()};this.onEditMouseDown=e=>{if(!this.isEditMode||!this.domElement)return;let t=new a.Vector2,i=this.domElement.getBoundingClientRect();t.x=(e.clientX-i.left)/i.width*2-1,t.y=-((e.clientY-i.top)/i.height)*2+1,this.raycaster.setFromCamera(t,this.camera);let n=[this.startEditSprite,this.endEditSprite].filter(r=>r!==null),s=this.raycaster.intersectObjects(n);if(s.length>0){let r=s[0].object;this.editingPoint=r.userData.editPoint,this.isDragging=!0,this.disableControls(),this.editingPoint==="start"&&this.startEditSprite?this.startEditSprite.visible=!1:this.editingPoint==="end"&&this.endEditSprite&&(this.endEditSprite.visible=!1),this.createSnapMarker(),this.snapMarker&&(this.snapMarker.position.copy(r.position),this.snapMarker.visible=!0),this.hideCursor()}};this.onEditMouseMove=e=>{if(!this.isEditMode||!this.isDragging||!this.editingMeasurement)return;let t=this.getSnapResult(e);t&&(this.snapMarker&&(this.snapMarker.position.copy(t.point),this.snapMarker.visible=this.markerVisible),this.editingPoint==="start"?this.updateMeasurementPreview(t.point,this.editingMeasurement.end.position):this.editingPoint==="end"&&this.updateMeasurementPreview(this.editingMeasurement.start.position,t.point))};this.onEditMouseUp=e=>{if(!this.isEditMode||!this.isDragging||!this.editingMeasurement||!this.editingPoint)return;let t=this.getSnapResult(e);if(!t){this.cancelEdit();return}let i=this.editingPoint==="start"?this.editingMeasurement.start:this.editingMeasurement.end;if(i.position.copy(t.point),this.editingMeasurement.options.isDynamic&&t.object){let l=t.object.worldToLocal(t.point.clone());i.anchor={object:t.object,localPosition:l}}else i.anchor=void 0;let s=this.editingMeasurement.start.position.distanceTo(this.editingMeasurement.end.position);this.editingMeasurement.distance=s;let r=[this.editingMeasurement.start.position,this.editingMeasurement.end.position];this.editingMeasurement.line.geometry.setFromPoints(r),this.editingMeasurement.line.geometry.attributes.position.needsUpdate=!0;let o=this.editingMeasurement.start.position.clone().add(this.editingMeasurement.end.position).multiplyScalar(.5);this.editingMeasurement.label.position.copy(o),this.updateLabelText(this.editingMeasurement.label.element,s),this.startEditSprite&&(this.startEditSprite.position.copy(this.editingMeasurement.start.position),this.startEditSprite.visible=!0),this.endEditSprite&&(this.endEditSprite.position.copy(this.editingMeasurement.end.position),this.endEditSprite.visible=!0),this.removeSnapMarker(),this.showCursor(),this.enableControls(),this.dispatchEvent({type:"measurementUpdated",measurement:this.editingMeasurement}),this.isDragging=!1,this.editingPoint=null};this.scene=e,this.camera=t;let{domElement:n,controls:s}=i;n&&(this.domElement=n),s&&(this.controls=s),this.previewMaterial=new a.LineDashedMaterial({color:this.previewColor,linewidth:this.defaultOptions.lineWidth,dashSize:.1,gapSize:.05}),this.markerMaterial=new a.SpriteMaterial({map:this.createCrosshairTexture(),color:this.markerColor,transparent:!0,opacity:.8,sizeAttenuation:!1,depthTest:!1}),this.editSpriteMaterial=new a.SpriteMaterial({map:this.createDotTexture(),color:16755200,transparent:!0,opacity:.9,sizeAttenuation:!1,depthTest:!1}),this.raycaster.params.Line.threshold=.01,this.raycaster.params.Points.threshold=.01}createCrosshairTexture(){let t=document.createElement("canvas");t.width=64,t.height=64;let i=t.getContext("2d"),n=64/2,s=64/2,r=20,o=6;i.clearRect(0,0,64,64),i.strokeStyle="#ffffff",i.lineWidth=3,i.lineCap="round",i.beginPath(),i.moveTo(n-r,s),i.lineTo(n-o,s),i.moveTo(n+o,s),i.lineTo(n+r,s),i.moveTo(n,s-r),i.lineTo(n,s-o),i.moveTo(n,s+o),i.lineTo(n,s+r),i.stroke(),i.strokeStyle="#000000",i.lineWidth=5,i.globalCompositeOperation="destination-over",i.beginPath(),i.moveTo(n-r,s),i.lineTo(n-o,s),i.moveTo(n+o,s),i.lineTo(n+r,s),i.moveTo(n,s-r),i.lineTo(n,s-o),i.moveTo(n,s+o),i.lineTo(n,s+r),i.stroke();let l=new a.CanvasTexture(t);return l.needsUpdate=!0,l}createDotTexture(){let t=document.createElement("canvas");t.width=64,t.height=64;let i=t.getContext("2d"),n=64/2,s=64/2,r=12;i.clearRect(0,0,64,64),i.fillStyle="#ffffff",i.beginPath(),i.arc(n,s,r,0,Math.PI*2),i.fill(),i.strokeStyle="#000000",i.lineWidth=3,i.beginPath(),i.arc(n,s,r,0,Math.PI*2),i.stroke();let o=new a.CanvasTexture(t);return o.needsUpdate=!0,o}createMeasurementPoint(e,t,i){if(!t)return{position:e.clone()};let n=i?.clone()??t.worldToLocal(e.clone());return{position:t.localToWorld(n.clone()),anchor:{object:t,localPosition:n}}}updateMeasurementPoint(e){if(!e.anchor)return!1;let t=e.anchor.localPosition.clone();return e.anchor.object.localToWorld(t),e.position.equals(t)?!1:(e.position.copy(t),!0)}addMeasurement(e,t,i={}){let n=!!(i.startObject||i.endObject),s=this.resolveMeasurementOptions(i,i.isDynamic??n),r=this.createMeasurementPoint(e,i.startObject,i.startLocalPosition),o=this.createMeasurementPoint(t,i.endObject,i.endLocalPosition);return this.addMeasurementFromPoints(r,o,s,{id:i.id})}resolveMeasurementOptions(e={},t){let i;e.targets&&e.targets.length>0?i=e.targets:this.defaultOptions.targets.length>0?i=this.defaultOptions.targets:this.defaultTargets.length>0&&(i=this.defaultTargets);let n=i&&i.length>0?i:this.getAllMeshes(),s=e.isDynamic??t??this.defaultOptions.isDynamic;return{lineColor:e.lineColor??this.defaultOptions.lineColor,labelColor:e.labelColor??this.defaultOptions.labelColor,lineWidth:e.lineWidth??this.defaultOptions.lineWidth,fontSize:e.fontSize??this.defaultOptions.fontSize,fontFamily:e.fontFamily??this.defaultOptions.fontFamily,snapMode:e.snapMode??this.defaultOptions.snapMode,snapEnabled:e.snapEnabled??this.defaultOptions.snapEnabled,snapDistance:e.snapDistance??this.defaultOptions.snapDistance,targets:n,isDynamic:s}}getActiveMeasurementOptions(){return this.isEditMode&&this.editingMeasurement?this.editingMeasurement.options:this.activeInteractionOptions}addDynamicMeasurement(e,t,i=new a.Vector3,n=new a.Vector3){let s=e.localToWorld(i.clone()),r=t.localToWorld(n.clone());return this.addMeasurement(s,r,{startObject:e,endObject:t,startLocalPosition:i,endLocalPosition:n})}addMeasurementToObject(e,t,i=new a.Vector3){let n=t.localToWorld(i.clone());return this.addMeasurement(e,n,{endObject:t,endLocalPosition:i})}addMeasurementFromPoints(e,t,i,n){let s=n?.id||this.generateId(),r=e.position.distanceTo(t.position),o=new a.BufferGeometry().setFromPoints([e.position,t.position]),l=new a.Line(o,new a.LineBasicMaterial({color:i.lineColor,linewidth:i.lineWidth})),c=this.createLabel(r,i),p=e.position.clone().add(t.position).multiplyScalar(.5);c.position.copy(p);let d={id:s,start:e,end:t,line:l,label:c,distance:r,options:{...i,targets:[...i.targets]}};return this.scene.add(l),this.scene.add(c),this.measurements.push(d),this.dispatchEvent({type:"measurementCreated",measurement:d}),d}updateDynamicMeasurements(){let e=!1;for(let t of this.measurements){if(!t.options.isDynamic)continue;let i=!1;if(this.updateMeasurementPoint(t.start)&&(i=!0),this.updateMeasurementPoint(t.end)&&(i=!0),i){let n=t.start.position.distanceTo(t.end.position);t.distance=n;let s=[t.start.position,t.end.position];t.line.geometry.setFromPoints(s),t.line.geometry.attributes.position.needsUpdate=!0;let r=t.start.position.clone().add(t.end.position).multiplyScalar(.5);t.label.position.copy(r),this.updateLabelText(t.label.element,n),e=!0}}return e}setDynamicMode(e){this.setDefaultMeasurementOptions({isDynamic:e})}getDynamicMode(){return this.defaultOptions.isDynamic}enterEditMode(e,t){this.exitEditMode();let i;if(typeof e=="string"?i=this.measurements.find(s=>s.id===e):i=this.measurements[e],!i){console.warn("Measurement not found:",e);return}if(!this.domElement){console.warn("DOM element not set. Call setDomElement() or enableInteraction() first.");return}this.isEditMode=!0,this.editingMeasurement=i;let n=t&&t.length>0?t:i.options.targets.length>0?i.options.targets:this.getAllMeshes();this.activeTargets=n,t&&t.length>0&&(i.options.targets=[...t]),this.createEditSprites(),this.domElement.addEventListener("mousedown",this.onEditMouseDown),this.domElement.addEventListener("mousemove",this.onEditMouseMove),this.domElement.addEventListener("mouseup",this.onEditMouseUp),this.domElement.style.cursor="pointer",this.dispatchEvent({type:"editModeEntered",measurement:i})}exitEditMode(){if(!this.isEditMode)return;let e=this.editingMeasurement;this.removeEditSprites(),this.domElement&&(this.domElement.removeEventListener("mousedown",this.onEditMouseDown),this.domElement.removeEventListener("mousemove",this.onEditMouseMove),this.domElement.removeEventListener("mouseup",this.onEditMouseUp),this.domElement.style.cursor=this.isInteractive?"crosshair":"default"),this.isEditMode=!1,this.editingMeasurement=null,this.editingPoint=null,this.isDragging=!1,this.activeTargets=[],e&&this.dispatchEvent({type:"editModeExited",measurement:e})}setDomElement(e){this.domElement=e}setControls(e){this.controls=e}setTargetObjects(e){this.defaultTargets=e.length>0?e:this.getAllMeshes(),this.defaultOptions.targets=[...this.defaultTargets]}setDefaultMeasurementOptions(e){e.lineColor!==void 0&&(this.defaultOptions.lineColor=e.lineColor),e.labelColor!==void 0&&(this.defaultOptions.labelColor=e.labelColor),e.lineWidth!==void 0&&(this.defaultOptions.lineWidth=e.lineWidth),e.fontSize!==void 0&&(this.defaultOptions.fontSize=e.fontSize),e.fontFamily!==void 0&&(this.defaultOptions.fontFamily=e.fontFamily),e.snapMode!==void 0&&(this.defaultOptions.snapMode=e.snapMode),e.snapEnabled!==void 0&&(this.defaultOptions.snapEnabled=e.snapEnabled),e.snapDistance!==void 0&&(this.defaultOptions.snapDistance=e.snapDistance),e.targets!==void 0&&(this.defaultTargets=e.targets,this.defaultOptions.targets=[...e.targets],this.activeInteractionOptions&&(this.activeInteractionOptions.targets=[...e.targets],this.activeTargets=e.targets)),e.isDynamic!==void 0&&(this.defaultOptions.isDynamic=e.isDynamic,this.activeInteractionOptions&&(this.activeInteractionOptions.isDynamic=e.isDynamic)),this.activeInteractionOptions&&(e.lineColor!==void 0&&(this.activeInteractionOptions.lineColor=e.lineColor),e.labelColor!==void 0&&(this.activeInteractionOptions.labelColor=e.labelColor),e.lineWidth!==void 0&&(this.activeInteractionOptions.lineWidth=e.lineWidth),e.fontSize!==void 0&&(this.activeInteractionOptions.fontSize=e.fontSize),e.fontFamily!==void 0&&(this.activeInteractionOptions.fontFamily=e.fontFamily),e.snapMode!==void 0&&(this.activeInteractionOptions.snapMode=e.snapMode),e.snapEnabled!==void 0&&(this.activeInteractionOptions.snapEnabled=e.snapEnabled),e.snapDistance!==void 0&&(this.activeInteractionOptions.snapDistance=e.snapDistance))}disableControls(){this.controls&&(this.controls.enabled=!1)}enableControls(){this.controls&&(this.controls.enabled=!0)}enableInteraction(e={}){this.isInteractive&&this.disableInteraction();let t=this.resolveMeasurementOptions(e);this.activeInteractionOptions={...t,targets:[...t.targets]},this.activeTargets=this.activeInteractionOptions.targets.length>0?this.activeInteractionOptions.targets:this.getAllMeshes(),this.isInteractive=!0,this.domElement&&(this.domElement.addEventListener("click",this.onMouseClick),this.domElement.addEventListener("mousemove",this.onMouseMove),this.domElement.addEventListener("keydown",this.onKeyDown),this.domElement.style.cursor="crosshair"),this.createSnapMarker(),this.dispatchEvent({type:"started"})}disableInteraction(){!this.isInteractive||!this.domElement||(this.exitEditMode(),this.domElement.removeEventListener("click",this.onMouseClick),this.domElement.removeEventListener("mousemove",this.onMouseMove),this.domElement.removeEventListener("keydown",this.onKeyDown),this.showCursor(),this.domElement.style.cursor="default",this.cancelCurrentMeasurement(),this.removeSnapMarker(),this.isInteractive=!1,this.activeInteractionOptions=null,this.activeTargets=[],this.dispatchEvent({type:"ended"}))}undoLast(){if(this.measurements.length===0)return;let e=this.measurements.pop();this.removeMeasurementFromScene(e),this.dispatchEvent({type:"measurementRemoved",measurement:e})}removeMeasurement(e){let t=this.measurements.indexOf(e);t!==-1&&(this.measurements.splice(t,1),this.removeMeasurementFromScene(e),this.dispatchEvent({type:"measurementRemoved",measurement:e}))}clearAll(){let e=this.measurements.length;this.measurements.forEach(t=>{this.removeMeasurementFromScene(t)}),this.measurements=[],this.dispatchEvent({type:"measurementsCleared",count:e})}getMeasurements(){return[...this.measurements]}serializeMeasurementPoint(e){return{position:e.position.toArray(),anchorObjectId:e.anchor?.object.uuid,anchorLocalPosition:e.anchor?e.anchor.localPosition.toArray():void 0}}serialize(){return this.measurements.map(e=>({id:e.id,start:this.serializeMeasurementPoint(e.start),end:this.serializeMeasurementPoint(e.end),distance:e.distance,options:{snapMode:e.options.snapMode,snapEnabled:e.options.snapEnabled,snapDistance:e.options.snapDistance,lineColor:e.options.lineColor,labelColor:e.options.labelColor,lineWidth:e.options.lineWidth,fontSize:e.options.fontSize,fontFamily:e.options.fontFamily,isDynamic:e.options.isDynamic,targetObjectIds:e.options.targets.map(t=>t.uuid)}}))}deserialize(e){this.clearAll(),e.forEach(t=>{let i=new a.Vector3().fromArray(t.start.position),n=new a.Vector3().fromArray(t.end.position),s=t.start.anchorObjectId?this.scene.getObjectByProperty("uuid",t.start.anchorObjectId):null,r=t.end.anchorObjectId?this.scene.getObjectByProperty("uuid",t.end.anchorObjectId):null,o=t.options.targetObjectIds&&t.options.targetObjectIds.length>0?t.options.targetObjectIds.map(l=>this.scene.getObjectByProperty("uuid",l)).filter(l=>l!==void 0):void 0;this.addMeasurement(i,n,{id:t.id,targets:o&&o.length>0?o:void 0,snapMode:t.options.snapMode,snapEnabled:t.options.snapEnabled,snapDistance:t.options.snapDistance,lineColor:t.options.lineColor,labelColor:t.options.labelColor,lineWidth:t.options.lineWidth,fontSize:t.options.fontSize,fontFamily:t.options.fontFamily,isDynamic:t.options.isDynamic,startObject:s||void 0,startLocalPosition:t.start.anchorLocalPosition?new a.Vector3().fromArray(t.start.anchorLocalPosition):void 0,endObject:r||void 0,endLocalPosition:t.end.anchorLocalPosition?new a.Vector3().fromArray(t.end.anchorLocalPosition):void 0})})}dispose(){this.exitEditMode(),this.disableInteraction(),this.clearAll(),this.previewMaterial.dispose(),this.markerMaterial.map&&this.markerMaterial.map.dispose(),this.markerMaterial.dispose(),this.editSpriteMaterial&&(this.editSpriteMaterial.map&&this.editSpriteMaterial.map.dispose(),this.editSpriteMaterial.dispose())}hideCursor(){!this.domElement||this.cursorHidden||(this.originalCursor=this.domElement.style.cursor,this.domElement.style.cursor="none",this.cursorHidden=!0)}showCursor(){!this.domElement||!this.cursorHidden||(this.domElement.style.cursor=this.originalCursor||"crosshair",this.cursorHidden=!1)}createSnapMarker(){this.markerVisible&&(this.snapMarker&&this.scene.remove(this.snapMarker),this.snapMarker=new a.Sprite(this.markerMaterial),this.snapMarker.scale.setScalar(this.markerSize),this.snapMarker.visible=!1,this.snapMarker.renderOrder=999,this.snapMarker.material.depthTest=!1,this.scene.add(this.snapMarker))}updateSnapMarker(e,t=!0){!this.snapMarker||!this.markerVisible||(this.snapMarker.position.copy(e),this.snapMarker.visible=t)}hideSnapMarker(){this.snapMarker&&(this.snapMarker.visible=!1)}removeSnapMarker(){this.snapMarker&&(this.scene.remove(this.snapMarker),this.snapMarker=null)}startMeasurement(e){let t=this.generateId(),i=e.point,n=this.activeInteractionOptions??this.defaultOptions,s={...n,targets:[...n.targets]};this.pendingMeasurementOptions=s,this.hideSnapMarker();let r=new a.BufferGeometry().setFromPoints([i,i]);this.previewLine=new a.Line(r,this.previewMaterial),this.previewLine.computeLineDistances(),this.scene.add(this.previewLine),this.previewLabel=this.createLabel(0,s),this.previewLabel.position.copy(i),this.scene.add(this.previewLabel);let o=s.isDynamic&&e.object?this.createMeasurementPoint(i,e.object):this.createMeasurementPoint(i);this.currentMeasurement={id:t,start:o}}updatePreview(e){if(!this.currentMeasurement||!this.previewLine||!this.previewLabel)return;let t=this.currentMeasurement.start,i=t.position.distanceTo(e),n=new a.BufferGeometry().setFromPoints([t.position,e]);this.previewLine.geometry.dispose(),this.previewLine.geometry=n,this.previewLine.computeLineDistances();let s=t.position.clone().add(e).multiplyScalar(.5);this.previewLabel.position.copy(s),this.updateLabelText(this.previewLabel.element,i),this.dispatchEvent({type:"previewUpdated",start:t.position,current:e,distance:i})}completeMeasurement(e){if(!this.currentMeasurement)return;let t=this.currentMeasurement.start,i=e.point,n=this.pendingMeasurementOptions??this.activeInteractionOptions??this.defaultOptions;this.disableInteraction(),this.cleanupPreview();let s={...n,targets:[...n.targets]},r=s.isDynamic&&e.object?this.createMeasurementPoint(i,e.object):this.createMeasurementPoint(i);this.addMeasurementFromPoints(t,r,s),this.currentMeasurement=null,this.pendingMeasurementOptions=null,this.createSnapMarker()}cancelCurrentMeasurement(){this.cleanupPreview(),this.currentMeasurement=null,this.pendingMeasurementOptions=null,this.createSnapMarker()}cleanupPreview(){this.previewLine&&(this.scene.remove(this.previewLine),this.previewLine.geometry.dispose(),this.previewLine=null),this.previewLabel&&(this.scene.remove(this.previewLabel),this.previewLabel.element.parentNode&&this.previewLabel.element.parentNode.removeChild(this.previewLabel.element),this.previewLabel=null)}getSnapResult(e){let t=new a.Vector2,i=this.domElement.getBoundingClientRect();t.x=(e.clientX-i.left)/i.width*2-1,t.y=-((e.clientY-i.top)/i.height)*2+1;let n=this.getActiveMeasurementOptions()??this.defaultOptions,s=this.activeTargets.length>0?this.activeTargets:n.targets.length>0?n.targets:this.getAllMeshes();this.raycaster.setFromCamera(t,this.camera);let r=this.raycaster.intersectObjects(s,!0);if(r.length===0)return null;let o=r[0],l=o.point.clone(),c=!1,p="disabled";if(n.snapEnabled){let d=this.performSnapping(o,n);l=d.point,c=d.snapped,p=d.snapMode}return{point:l,originalPoint:o.point,snapped:c,snapMode:p,object:o.object}}performSnapping(e,t){let i=e.point,n=i.clone(),s=!1,r="disabled";if(t.snapMode==="vertex"){let o=this.snapToVertex(e,t.snapDistance);o&&(n=o,s=!0,r="vertex")}else t.snapMode==="face"&&(s=!0,r="face");return{point:n,originalPoint:i,snapped:s,snapMode:r,object:e.object}}snapToVertex(e,t){let i=e.object.geometry;if(!i.attributes.position)return null;let n=i.attributes.position,s=e.object.matrixWorld,r=new a.Vector3,o=1/0,l=!1;for(let c=0;c<n.count;c++){let p=new a.Vector3;p.fromBufferAttribute(n,c),p.applyMatrix4(s);let d=p.distanceTo(e.point);d<t&&d<o&&(o=d,r.copy(p),l=!0)}return l?r:null}createLabel(e,t){let i=document.createElement("div");i.className="measurement-label",Object.assign(i.style,{color:t.labelColor,fontSize:`${t.fontSize}px`,fontFamily:t.fontFamily,fontWeight:"bold",background:"rgba(0, 0, 0, 0.9)",padding:"8px 12px",borderRadius:"8px",border:"2px solid rgba(255, 255, 255, 0.3)",whiteSpace:"nowrap",userSelect:"none",pointerEvents:"auto",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.5)",textShadow:"1px 1px 2px rgba(0, 0, 0, 0.8)",zIndex:"1000",cursor:"pointer"}),this.updateLabelText(i,e);let n=new m(i);return i.addEventListener("dblclick",s=>{s.stopPropagation();let r=this.measurements.find(o=>o.label===n);r&&this.enterEditMode(r.id)}),n}updateLabelText(e,t){let i=`${t.toFixed(2)}m`;e.textContent=i}removeMeasurementFromScene(e){this.scene.remove(e.line),this.scene.remove(e.label),e.line.geometry.dispose(),e.line.material instanceof a.Material&&e.line.material.dispose(),e.label.element.parentNode&&e.label.element.parentNode.removeChild(e.label.element)}getAllMeshes(){let e=[];return this.scene.traverse(t=>{t instanceof a.Mesh&&e.push(t)}),e}generateId(){return`measurement_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}createEditSprites(){if(!this.editingMeasurement||!this.editSpriteMaterial)return;let e=this.editingMeasurement;this.startEditSprite=new a.Sprite(this.editSpriteMaterial.clone()),this.startEditSprite.position.copy(e.start.position),this.startEditSprite.scale.set(this.markerSize,this.markerSize,1),this.startEditSprite.userData.editPoint="start",this.scene.add(this.startEditSprite),this.endEditSprite=new a.Sprite(this.editSpriteMaterial.clone()),this.endEditSprite.position.copy(e.end.position),this.endEditSprite.scale.set(this.markerSize,this.markerSize,1),this.endEditSprite.userData.editPoint="end",this.scene.add(this.endEditSprite)}removeEditSprites(){this.startEditSprite&&(this.scene.remove(this.startEditSprite),this.startEditSprite.material instanceof a.Material&&this.startEditSprite.material.dispose(),this.startEditSprite=null),this.endEditSprite&&(this.scene.remove(this.endEditSprite),this.endEditSprite.material instanceof a.Material&&this.endEditSprite.material.dispose(),this.endEditSprite=null)}cancelEdit(){this.isDragging=!1,this.editingPoint=null,this.enableControls(),this.startEditSprite&&(this.startEditSprite.visible=!0),this.endEditSprite&&(this.endEditSprite.visible=!0),this.removeSnapMarker(),this.showCursor()}updateMeasurementPreview(e,t){if(!this.editingMeasurement)return;let i=e.distanceTo(t),n=[e,t];this.editingMeasurement.line.geometry.setFromPoints(n),this.editingMeasurement.line.geometry.attributes.position.needsUpdate=!0;let s=e.clone().add(t).multiplyScalar(.5);this.editingMeasurement.label.position.copy(s),this.updateLabelText(this.editingMeasurement.label.element,i)}};export{u as a,h as b};
@@ -1,4 +1,4 @@
1
- import*as o from"three";import{GLTFLoader as u}from"three/examples/jsm/loaders/GLTFLoader.js";import{FBXLoader as E}from"three/examples/jsm/loaders/FBXLoader.js";import{OBJLoader as b}from"three/examples/jsm/loaders/OBJLoader.js";import{USDLoader as y}from"three/examples/jsm/loaders/USDLoader.js";import{ColladaLoader as v}from"three/examples/jsm/loaders/ColladaLoader.js";import{STLLoader as R}from"three/examples/jsm/loaders/STLLoader.js";import{PLYLoader as L}from"three/examples/jsm/loaders/PLYLoader.js";import{ThreeMFLoader as T}from"three/examples/jsm/loaders/3MFLoader.js";var f=class extends o.EventDispatcher{constructor(){super();this.cache=new Map;this.placeholder=null;this.loadedAsset=null;this.lowResAsset=null;this.errorColor=16729156;this.errorOpacity=.5;this.gltfLoader=new u,this.fbxLoader=new E,this.objLoader=new b,this.usdLoader=new y,this.colladaLoader=new v,this.stlLoader=new R,this.plyLoader=new L,this.threeMFLoader=new T}createPlaceholder(e,r=5227511,l=.3){let[a,c,i]=e,d=new o.BoxGeometry(a,c,i),t=new o.ShaderMaterial({side:o.DoubleSide,depthWrite:!1,blending:o.AdditiveBlending,transparent:!0,uniforms:{color:{value:new o.Color(r)},opacity:{value:l},fillProgress:{value:0},time:{value:0},isError:{value:0},yMin:{value:-c/2},yMax:{value:c/2}},vertexShader:`
1
+ import*as o from"three";import{GLTFLoader as u}from"three/examples/jsm/loaders/GLTFLoader.js";import{FBXLoader as E}from"three/examples/jsm/loaders/FBXLoader.js";import{OBJLoader as b}from"three/examples/jsm/loaders/OBJLoader.js";import{USDLoader as y}from"three/examples/jsm/loaders/USDLoader.js";import{ColladaLoader as v}from"three/examples/jsm/loaders/ColladaLoader.js";import{STLLoader as R}from"three/examples/jsm/loaders/STLLoader.js";import{PLYLoader as L}from"three/examples/jsm/loaders/PLYLoader.js";import{ThreeMFLoader as T}from"three/examples/jsm/loaders/3MFLoader.js";var f=class extends o.EventDispatcher{constructor(){super();this.cache=new Map;this.placeholder=null;this.loadedAsset=null;this.lowResAsset=null;this.errorColor=16729156;this.errorOpacity=.5;this.gltfLoader=new u,this.fbxLoader=new E,this.objLoader=new b,this.usdLoader=new y,this.colladaLoader=new v,this.stlLoader=new R,this.plyLoader=new L,this.threeMFLoader=new T}createPlaceholder(t,r=5227511,l=.3){let[a,d,i]=t,c=new o.BoxGeometry(a,d,i),e=new o.ShaderMaterial({side:o.DoubleSide,depthWrite:!1,blending:o.AdditiveBlending,transparent:!0,uniforms:{color:{value:new o.Color(r)},opacity:{value:l},fillProgress:{value:0},time:{value:0},isError:{value:0},yMin:{value:-d/2},yMax:{value:d/2}},vertexShader:`
2
2
  varying vec3 vPosition;
3
3
  void main() {
4
4
  vPosition = position;
@@ -41,4 +41,4 @@ import*as o from"three";import{GLTFLoader as u}from"three/examples/jsm/loaders/G
41
41
  vec3 finalColor = color + edgeIntensity * 0.5;
42
42
  gl_FragColor = vec4(finalColor, alpha);
43
43
  }
44
- `}),s=new o.Mesh(d,t);return this.positionAssetAtBottomCenter(s),s}updatePlaceholder(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let r=this.placeholder.material;r.uniforms&&r.uniforms.fillProgress&&(r.uniforms.fillProgress.value=e)}}setPlaceholderError(){if(this.placeholder&&this.placeholder instanceof o.Mesh){let e=this.placeholder.material;e.uniforms&&(e.uniforms.color&&(e.uniforms.color.value=new o.Color(this.errorColor)),e.uniforms.opacity&&(e.uniforms.opacity.value=this.errorOpacity),e.uniforms.fillProgress&&(e.uniforms.fillProgress.value=0),e.uniforms.isError&&(e.uniforms.isError.value=1))}}updatePlaceholderAnimation(e){if(this.placeholder&&this.placeholder instanceof o.Mesh){let r=this.placeholder.material;r.uniforms&&r.uniforms.time&&(r.uniforms.time.value+=e)}}positionAssetAtBottomCenter(e){e.updateMatrixWorld(!0);let r=new o.Box3().setFromObject(e);if(r.isEmpty())return;let l=r.getCenter(new o.Vector3),a=new o.Vector3(l.x,r.min.y-.01,l.z);!Number.isFinite(a.x)||!Number.isFinite(a.y)||!Number.isFinite(a.z)||(e.position.sub(a),e.userData.bottomCenterOffset=a,e.updateMatrixWorld(!0))}ensureBottomCenterOffset(e){let r=e.userData.bottomCenterOffset;if(r instanceof o.Vector3)return r;if(r&&typeof r=="object"){let{x:l=0,y:a=0,z:c=0}=r,i=new o.Vector3(l??0,a??0,c??0);return e.userData.bottomCenterOffset=i,i}return null}normalizeBottomCenterData(e){let r=this.ensureBottomCenterOffset(e)!==null;return e.children.forEach(l=>this.normalizeBottomCenterData(l)),r}async load(e){let{type:r,url:l,size:a,lowResUrl:c,enableCaching:i=!0,disablePlaceholder:d=!1,placeholderColor:t=5227511,placeholderOpacity:s=.4,errorColor:p=16729156,errorOpacity:m=.5}=e;if(i&&this.cache.has(l)){let n=this.cache.get(l).clone(!0);return this.normalizeBottomCenterData(n)?n.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(n),this.loadedAsset=n,this.dispatchEvent({type:"loaded",asset:n}),n}this.errorColor=p,this.errorOpacity=m,a&&!d&&(this.placeholder=this.createPlaceholder(a,t,s),this.dispatchEvent({type:"placeholderCreated",placeholder:this.placeholder}));try{if(c){let h=await this.loadModel(r,c,!0);this.lowResAsset=h,this.dispatchEvent({type:"lowResLoaded",lowRes:h})}let n=await this.loadModel(r,l,!1);if(this.loadedAsset=n,i){let h=n.clone(!0);this.normalizeBottomCenterData(h)?h.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(h),this.cache.set(l,h)}return this.dispatchEvent({type:"loaded",asset:n}),n}catch(n){throw this.setPlaceholderError(),this.dispatchEvent({type:"error",error:n}),n}}loadModel(e,r,l){return new Promise((a,c)=>{let i=t=>{let s=-1;t.lengthComputable&&t.total>0&&t.loaded<=t.total&&(s=t.loaded/t.total*100),this.dispatchEvent({type:"progress",loaded:t.loaded,total:t.total,percentage:s}),!l&&s>=0&&this.updatePlaceholder(s/100)},d=t=>{c(t)};switch(e){case"gltf":this.gltfLoader.load(r,t=>{let s=t.scene;this.positionAssetAtBottomCenter(s),a(s)},i,d);break;case"fbx":this.fbxLoader.load(r,t=>{this.positionAssetAtBottomCenter(t),a(t)},i,d);break;case"obj":this.objLoader.load(r,t=>{this.positionAssetAtBottomCenter(t),a(t)},i,d);break;case"usd":case"usdz":this.usdLoader.load(r,t=>{this.positionAssetAtBottomCenter(t),a(t)},i,d);break;case"dae":this.colladaLoader.load(r,t=>{let s=t.scene;this.positionAssetAtBottomCenter(s),a(s)},i,d);break;case"stl":this.stlLoader.load(r,t=>{let s=new o.MeshStandardMaterial({color:8947848}),p=new o.Mesh(t,s);this.positionAssetAtBottomCenter(p),a(p)},i,d);break;case"ply":this.plyLoader.load(r,t=>{let s=new o.MeshStandardMaterial({vertexColors:!0}),p=new o.Mesh(t,s);this.positionAssetAtBottomCenter(p),a(p)},i,d);break;case"3mf":this.threeMFLoader.load(r,t=>{this.positionAssetAtBottomCenter(t),a(t)},i,d);break;default:c(new Error(`Unsupported asset type: ${e}`))}})}getPlaceholder(){return this.placeholder}getAsset(){return this.loadedAsset}getLowResAsset(){return this.lowResAsset}clearCache(){this.cache.clear()}removeFromCache(e){this.cache.delete(e)}getCacheSize(){return this.cache.size}};export{f as a};
44
+ `}),s=new o.Mesh(c,e);return this.positionAssetAtBottomCenter(s),s}updatePlaceholder(t){if(this.placeholder&&this.placeholder instanceof o.Mesh){let r=this.placeholder.material;r.uniforms&&r.uniforms.fillProgress&&(r.uniforms.fillProgress.value=t)}}setPlaceholderError(){if(this.placeholder&&this.placeholder instanceof o.Mesh){let t=this.placeholder.material;t.uniforms&&(t.uniforms.color&&(t.uniforms.color.value=new o.Color(this.errorColor)),t.uniforms.opacity&&(t.uniforms.opacity.value=this.errorOpacity),t.uniforms.fillProgress&&(t.uniforms.fillProgress.value=0),t.uniforms.isError&&(t.uniforms.isError.value=1))}}updatePlaceholderAnimation(t){if(this.placeholder&&this.placeholder instanceof o.Mesh){let r=this.placeholder.material;r.uniforms&&r.uniforms.time&&(r.uniforms.time.value+=t)}}positionAssetAtBottomCenter(t){t.updateMatrixWorld(!0);let r=new o.Box3().setFromObject(t);if(r.isEmpty())return;let l=r.getCenter(new o.Vector3),a=new o.Vector3(l.x,r.min.y-.01,l.z);!Number.isFinite(a.x)||!Number.isFinite(a.y)||!Number.isFinite(a.z)||(t.position.sub(a),t.userData.bottomCenterOffset=a,t.updateMatrixWorld(!0))}ensureBottomCenterOffset(t){let r=t.userData.bottomCenterOffset;if(r instanceof o.Vector3)return r;if(r&&typeof r=="object"){let{x:l=0,y:a=0,z:d=0}=r,i=new o.Vector3(l??0,a??0,d??0);return t.userData.bottomCenterOffset=i,i}return null}normalizeBottomCenterData(t){let r=this.ensureBottomCenterOffset(t)!==null;return t.children.forEach(l=>this.normalizeBottomCenterData(l)),r}async load(t){let{type:r,url:l,size:a,lowResUrl:d,enableCaching:i=!0,disablePlaceholder:c=!1,placeholderColor:e=5227511,placeholderOpacity:s=.4,errorColor:p=16729156,errorOpacity:m=.5}=t;if(i&&this.cache.has(l)){let n=this.cache.get(l).clone(!0);return this.normalizeBottomCenterData(n)?n.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(n),this.loadedAsset=n,this.dispatchEvent({type:"loaded",asset:n}),n}this.errorColor=p,this.errorOpacity=m,a&&!c&&(this.placeholder=this.createPlaceholder(a,e,s),this.dispatchEvent({type:"placeholderCreated",placeholder:this.placeholder}));try{if(d){let h=await this.loadModel(r,d,!0);this.lowResAsset=h,this.dispatchEvent({type:"lowResLoaded",lowRes:h})}let n=await this.loadModel(r,l,!1);if(this.loadedAsset=n,i){let h=n.clone(!0);this.normalizeBottomCenterData(h)?h.updateMatrixWorld(!0):this.positionAssetAtBottomCenter(h),this.cache.set(l,h)}return this.dispatchEvent({type:"loaded",asset:n}),n}catch(n){throw this.setPlaceholderError(),this.dispatchEvent({type:"error",error:n}),n}}loadModel(t,r,l){return new Promise((a,d)=>{let i=e=>{let s=-1;e.lengthComputable&&e.total>0&&e.loaded<=e.total&&(s=e.loaded/e.total*100),this.dispatchEvent({type:"progress",loaded:e.loaded,total:e.total,percentage:s}),!l&&s>=0&&this.updatePlaceholder(s/100)},c=e=>{d(e)};switch(t){case"gltf":this.gltfLoader.load(r,e=>{let s=e.scene;this.positionAssetAtBottomCenter(s),a(s)},i,c);break;case"fbx":this.fbxLoader.load(r,e=>{this.positionAssetAtBottomCenter(e),a(e)},i,c);break;case"obj":this.objLoader.load(r,e=>{this.positionAssetAtBottomCenter(e),a(e)},i,c);break;case"usd":case"usdz":this.usdLoader.load(r,e=>{this.positionAssetAtBottomCenter(e),a(e)},i,c);break;case"dae":this.colladaLoader.load(r,e=>{if(!e){d(new Error(`Failed to load Collada asset: ${r}`));return}let s=e.scene;this.positionAssetAtBottomCenter(s),a(s)},i,c);break;case"stl":this.stlLoader.load(r,e=>{let s=new o.MeshStandardMaterial({color:8947848}),p=new o.Mesh(e,s);this.positionAssetAtBottomCenter(p),a(p)},i,c);break;case"ply":this.plyLoader.load(r,e=>{let s=new o.MeshStandardMaterial({vertexColors:!0}),p=new o.Mesh(e,s);this.positionAssetAtBottomCenter(p),a(p)},i,c);break;case"3mf":this.threeMFLoader.load(r,e=>{this.positionAssetAtBottomCenter(e),a(e)},i,c);break;default:d(new Error(`Unsupported asset type: ${t}`))}})}getPlaceholder(){return this.placeholder}getAsset(){return this.loadedAsset}getLowResAsset(){return this.lowResAsset}clearCache(){this.cache.clear()}removeFromCache(t){this.cache.delete(t)}getCacheSize(){return this.cache.size}};export{f as a};