@2112-lab/central-plant 0.1.9 → 0.1.11

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.
@@ -9231,16 +9231,953 @@ function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
9231
9231
 
9232
9232
  }
9233
9233
 
9234
+ // o object_name | g group_name
9235
+ const _object_pattern = /^[og]\s*(.+)?/;
9236
+ // mtllib file_reference
9237
+ const _material_library_pattern = /^mtllib /;
9238
+ // usemtl material_name
9239
+ const _material_use_pattern = /^usemtl /;
9240
+ // usemap map_name
9241
+ const _map_use_pattern = /^usemap /;
9242
+ const _face_vertex_data_separator_pattern = /\s+/;
9243
+
9244
+ const _vA = new THREE.Vector3();
9245
+ const _vB = new THREE.Vector3();
9246
+ const _vC = new THREE.Vector3();
9247
+
9248
+ const _ab = new THREE.Vector3();
9249
+ const _cb = new THREE.Vector3();
9250
+
9251
+ const _color = new THREE.Color();
9252
+
9253
+ function ParserState() {
9254
+
9255
+ const state = {
9256
+ objects: [],
9257
+ object: {},
9258
+
9259
+ vertices: [],
9260
+ normals: [],
9261
+ colors: [],
9262
+ uvs: [],
9263
+
9264
+ materials: {},
9265
+ materialLibraries: [],
9266
+
9267
+ startObject: function ( name, fromDeclaration ) {
9268
+
9269
+ // If the current object (initial from reset) is not from a g/o declaration in the parsed
9270
+ // file. We need to use it for the first parsed g/o to keep things in sync.
9271
+ if ( this.object && this.object.fromDeclaration === false ) {
9272
+
9273
+ this.object.name = name;
9274
+ this.object.fromDeclaration = ( fromDeclaration !== false );
9275
+ return;
9276
+
9277
+ }
9278
+
9279
+ const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
9280
+
9281
+ if ( this.object && typeof this.object._finalize === 'function' ) {
9282
+
9283
+ this.object._finalize( true );
9284
+
9285
+ }
9286
+
9287
+ this.object = {
9288
+ name: name || '',
9289
+ fromDeclaration: ( fromDeclaration !== false ),
9290
+
9291
+ geometry: {
9292
+ vertices: [],
9293
+ normals: [],
9294
+ colors: [],
9295
+ uvs: [],
9296
+ hasUVIndices: false
9297
+ },
9298
+ materials: [],
9299
+ smooth: true,
9300
+
9301
+ startMaterial: function ( name, libraries ) {
9302
+
9303
+ const previous = this._finalize( false );
9304
+
9305
+ // New usemtl declaration overwrites an inherited material, except if faces were declared
9306
+ // after the material, then it must be preserved for proper MultiMaterial continuation.
9307
+ if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
9308
+
9309
+ this.materials.splice( previous.index, 1 );
9310
+
9311
+ }
9312
+
9313
+ const material = {
9314
+ index: this.materials.length,
9315
+ name: name || '',
9316
+ mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
9317
+ smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
9318
+ groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
9319
+ groupEnd: - 1,
9320
+ groupCount: - 1,
9321
+ inherited: false,
9322
+
9323
+ clone: function ( index ) {
9324
+
9325
+ const cloned = {
9326
+ index: ( typeof index === 'number' ? index : this.index ),
9327
+ name: this.name,
9328
+ mtllib: this.mtllib,
9329
+ smooth: this.smooth,
9330
+ groupStart: 0,
9331
+ groupEnd: - 1,
9332
+ groupCount: - 1,
9333
+ inherited: false
9334
+ };
9335
+ cloned.clone = this.clone.bind( cloned );
9336
+ return cloned;
9337
+
9338
+ }
9339
+ };
9340
+
9341
+ this.materials.push( material );
9342
+
9343
+ return material;
9344
+
9345
+ },
9346
+
9347
+ currentMaterial: function () {
9348
+
9349
+ if ( this.materials.length > 0 ) {
9350
+
9351
+ return this.materials[ this.materials.length - 1 ];
9352
+
9353
+ }
9354
+
9355
+ return undefined;
9356
+
9357
+ },
9358
+
9359
+ _finalize: function ( end ) {
9360
+
9361
+ const lastMultiMaterial = this.currentMaterial();
9362
+ if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
9363
+
9364
+ lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
9365
+ lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
9366
+ lastMultiMaterial.inherited = false;
9367
+
9368
+ }
9369
+
9370
+ // Ignore objects tail materials if no face declarations followed them before a new o/g started.
9371
+ if ( end && this.materials.length > 1 ) {
9372
+
9373
+ for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {
9374
+
9375
+ if ( this.materials[ mi ].groupCount <= 0 ) {
9376
+
9377
+ this.materials.splice( mi, 1 );
9378
+
9379
+ }
9380
+
9381
+ }
9382
+
9383
+ }
9384
+
9385
+ // Guarantee at least one empty material, this makes the creation later more straight forward.
9386
+ if ( end && this.materials.length === 0 ) {
9387
+
9388
+ this.materials.push( {
9389
+ name: '',
9390
+ smooth: this.smooth
9391
+ } );
9392
+
9393
+ }
9394
+
9395
+ return lastMultiMaterial;
9396
+
9397
+ }
9398
+ };
9399
+
9400
+ // Inherit previous objects material.
9401
+ // Spec tells us that a declared material must be set to all objects until a new material is declared.
9402
+ // If a usemtl declaration is encountered while this new object is being parsed, it will
9403
+ // overwrite the inherited material. Exception being that there was already face declarations
9404
+ // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
9405
+
9406
+ if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
9407
+
9408
+ const declared = previousMaterial.clone( 0 );
9409
+ declared.inherited = true;
9410
+ this.object.materials.push( declared );
9411
+
9412
+ }
9413
+
9414
+ this.objects.push( this.object );
9415
+
9416
+ },
9417
+
9418
+ finalize: function () {
9419
+
9420
+ if ( this.object && typeof this.object._finalize === 'function' ) {
9421
+
9422
+ this.object._finalize( true );
9423
+
9424
+ }
9425
+
9426
+ },
9427
+
9428
+ parseVertexIndex: function ( value, len ) {
9429
+
9430
+ const index = parseInt( value, 10 );
9431
+ return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
9432
+
9433
+ },
9434
+
9435
+ parseNormalIndex: function ( value, len ) {
9436
+
9437
+ const index = parseInt( value, 10 );
9438
+ return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
9439
+
9440
+ },
9441
+
9442
+ parseUVIndex: function ( value, len ) {
9443
+
9444
+ const index = parseInt( value, 10 );
9445
+ return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
9446
+
9447
+ },
9448
+
9449
+ addVertex: function ( a, b, c ) {
9450
+
9451
+ const src = this.vertices;
9452
+ const dst = this.object.geometry.vertices;
9453
+
9454
+ dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
9455
+ dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
9456
+ dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
9457
+
9458
+ },
9459
+
9460
+ addVertexPoint: function ( a ) {
9461
+
9462
+ const src = this.vertices;
9463
+ const dst = this.object.geometry.vertices;
9464
+
9465
+ dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
9466
+
9467
+ },
9468
+
9469
+ addVertexLine: function ( a ) {
9470
+
9471
+ const src = this.vertices;
9472
+ const dst = this.object.geometry.vertices;
9473
+
9474
+ dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
9475
+
9476
+ },
9477
+
9478
+ addNormal: function ( a, b, c ) {
9479
+
9480
+ const src = this.normals;
9481
+ const dst = this.object.geometry.normals;
9482
+
9483
+ dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
9484
+ dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
9485
+ dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
9486
+
9487
+ },
9488
+
9489
+ addFaceNormal: function ( a, b, c ) {
9490
+
9491
+ const src = this.vertices;
9492
+ const dst = this.object.geometry.normals;
9493
+
9494
+ _vA.fromArray( src, a );
9495
+ _vB.fromArray( src, b );
9496
+ _vC.fromArray( src, c );
9497
+
9498
+ _cb.subVectors( _vC, _vB );
9499
+ _ab.subVectors( _vA, _vB );
9500
+ _cb.cross( _ab );
9501
+
9502
+ _cb.normalize();
9503
+
9504
+ dst.push( _cb.x, _cb.y, _cb.z );
9505
+ dst.push( _cb.x, _cb.y, _cb.z );
9506
+ dst.push( _cb.x, _cb.y, _cb.z );
9507
+
9508
+ },
9509
+
9510
+ addColor: function ( a, b, c ) {
9511
+
9512
+ const src = this.colors;
9513
+ const dst = this.object.geometry.colors;
9514
+
9515
+ if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
9516
+ if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
9517
+ if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
9518
+
9519
+ },
9520
+
9521
+ addUV: function ( a, b, c ) {
9522
+
9523
+ const src = this.uvs;
9524
+ const dst = this.object.geometry.uvs;
9525
+
9526
+ dst.push( src[ a + 0 ], src[ a + 1 ] );
9527
+ dst.push( src[ b + 0 ], src[ b + 1 ] );
9528
+ dst.push( src[ c + 0 ], src[ c + 1 ] );
9529
+
9530
+ },
9531
+
9532
+ addDefaultUV: function () {
9533
+
9534
+ const dst = this.object.geometry.uvs;
9535
+
9536
+ dst.push( 0, 0 );
9537
+ dst.push( 0, 0 );
9538
+ dst.push( 0, 0 );
9539
+
9540
+ },
9541
+
9542
+ addUVLine: function ( a ) {
9543
+
9544
+ const src = this.uvs;
9545
+ const dst = this.object.geometry.uvs;
9546
+
9547
+ dst.push( src[ a + 0 ], src[ a + 1 ] );
9548
+
9549
+ },
9550
+
9551
+ addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
9552
+
9553
+ const vLen = this.vertices.length;
9554
+
9555
+ let ia = this.parseVertexIndex( a, vLen );
9556
+ let ib = this.parseVertexIndex( b, vLen );
9557
+ let ic = this.parseVertexIndex( c, vLen );
9558
+
9559
+ this.addVertex( ia, ib, ic );
9560
+ this.addColor( ia, ib, ic );
9561
+
9562
+ // normals
9563
+
9564
+ if ( na !== undefined && na !== '' ) {
9565
+
9566
+ const nLen = this.normals.length;
9567
+
9568
+ ia = this.parseNormalIndex( na, nLen );
9569
+ ib = this.parseNormalIndex( nb, nLen );
9570
+ ic = this.parseNormalIndex( nc, nLen );
9571
+
9572
+ this.addNormal( ia, ib, ic );
9573
+
9574
+ } else {
9575
+
9576
+ this.addFaceNormal( ia, ib, ic );
9577
+
9578
+ }
9579
+
9580
+ // uvs
9581
+
9582
+ if ( ua !== undefined && ua !== '' ) {
9583
+
9584
+ const uvLen = this.uvs.length;
9585
+
9586
+ ia = this.parseUVIndex( ua, uvLen );
9587
+ ib = this.parseUVIndex( ub, uvLen );
9588
+ ic = this.parseUVIndex( uc, uvLen );
9589
+
9590
+ this.addUV( ia, ib, ic );
9591
+
9592
+ this.object.geometry.hasUVIndices = true;
9593
+
9594
+ } else {
9595
+
9596
+ // add placeholder values (for inconsistent face definitions)
9597
+
9598
+ this.addDefaultUV();
9599
+
9600
+ }
9601
+
9602
+ },
9603
+
9604
+ addPointGeometry: function ( vertices ) {
9605
+
9606
+ this.object.geometry.type = 'Points';
9607
+
9608
+ const vLen = this.vertices.length;
9609
+
9610
+ for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
9611
+
9612
+ const index = this.parseVertexIndex( vertices[ vi ], vLen );
9613
+
9614
+ this.addVertexPoint( index );
9615
+ this.addColor( index );
9616
+
9617
+ }
9618
+
9619
+ },
9620
+
9621
+ addLineGeometry: function ( vertices, uvs ) {
9622
+
9623
+ this.object.geometry.type = 'Line';
9624
+
9625
+ const vLen = this.vertices.length;
9626
+ const uvLen = this.uvs.length;
9627
+
9628
+ for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
9629
+
9630
+ this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
9631
+
9632
+ }
9633
+
9634
+ for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
9635
+
9636
+ this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
9637
+
9638
+ }
9639
+
9640
+ }
9641
+
9642
+ };
9643
+
9644
+ state.startObject( '', false );
9645
+
9646
+ return state;
9647
+
9648
+ }
9649
+
9650
+
9651
+ /**
9652
+ * A loader for the OBJ format.
9653
+ *
9654
+ * The [OBJ format]{@link https://en.wikipedia.org/wiki/Wavefront_.obj_file} is a simple data-format that
9655
+ * represents 3D geometry in a human readable format as the position of each vertex, the UV position of
9656
+ * each texture coordinate vertex, vertex normals, and the faces that make each polygon defined as a list
9657
+ * of vertices, and texture vertices.
9658
+ *
9659
+ * ```js
9660
+ * const loader = new OBJLoader();
9661
+ * const object = await loader.loadAsync( 'models/monster.obj' );
9662
+ * scene.add( object );
9663
+ * ```
9664
+ *
9665
+ * @augments Loader
9666
+ * @three_import import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
9667
+ */
9668
+ class OBJLoader extends THREE.Loader {
9669
+
9670
+ /**
9671
+ * Constructs a new OBJ loader.
9672
+ *
9673
+ * @param {LoadingManager} [manager] - The loading manager.
9674
+ */
9675
+ constructor( manager ) {
9676
+
9677
+ super( manager );
9678
+
9679
+ /**
9680
+ * A reference to a material creator.
9681
+ *
9682
+ * @type {?MaterialCreator}
9683
+ * @default null
9684
+ */
9685
+ this.materials = null;
9686
+
9687
+ }
9688
+
9689
+ /**
9690
+ * Starts loading from the given URL and passes the loaded OBJ asset
9691
+ * to the `onLoad()` callback.
9692
+ *
9693
+ * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
9694
+ * @param {function(Group)} onLoad - Executed when the loading process has been finished.
9695
+ * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
9696
+ * @param {onErrorCallback} onError - Executed when errors occur.
9697
+ */
9698
+ load( url, onLoad, onProgress, onError ) {
9699
+
9700
+ const scope = this;
9701
+
9702
+ const loader = new THREE.FileLoader( this.manager );
9703
+ loader.setPath( this.path );
9704
+ loader.setRequestHeader( this.requestHeader );
9705
+ loader.setWithCredentials( this.withCredentials );
9706
+ loader.load( url, function ( text ) {
9707
+
9708
+ try {
9709
+
9710
+ onLoad( scope.parse( text ) );
9711
+
9712
+ } catch ( e ) {
9713
+
9714
+ if ( onError ) {
9715
+
9716
+ onError( e );
9717
+
9718
+ } else {
9719
+
9720
+ console.error( e );
9721
+
9722
+ }
9723
+
9724
+ scope.manager.itemError( url );
9725
+
9726
+ }
9727
+
9728
+ }, onProgress, onError );
9729
+
9730
+ }
9731
+
9732
+ /**
9733
+ * Sets the material creator for this OBJ. This object is loaded via {@link MTLLoader}.
9734
+ *
9735
+ * @param {MaterialCreator} materials - An object that creates the materials for this OBJ.
9736
+ * @return {OBJLoader} A reference to this loader.
9737
+ */
9738
+ setMaterials( materials ) {
9739
+
9740
+ this.materials = materials;
9741
+
9742
+ return this;
9743
+
9744
+ }
9745
+
9746
+ /**
9747
+ * Parses the given OBJ data and returns the resulting group.
9748
+ *
9749
+ * @param {string} text - The raw OBJ data as a string.
9750
+ * @return {Group} The parsed OBJ.
9751
+ */
9752
+ parse( text ) {
9753
+
9754
+ const state = new ParserState();
9755
+
9756
+ if ( text.indexOf( '\r\n' ) !== - 1 ) {
9757
+
9758
+ // This is faster than String.split with regex that splits on both
9759
+ text = text.replace( /\r\n/g, '\n' );
9760
+
9761
+ }
9762
+
9763
+ if ( text.indexOf( '\\\n' ) !== - 1 ) {
9764
+
9765
+ // join lines separated by a line continuation character (\)
9766
+ text = text.replace( /\\\n/g, '' );
9767
+
9768
+ }
9769
+
9770
+ const lines = text.split( '\n' );
9771
+ let result = [];
9772
+
9773
+ for ( let i = 0, l = lines.length; i < l; i ++ ) {
9774
+
9775
+ const line = lines[ i ].trimStart();
9776
+
9777
+ if ( line.length === 0 ) continue;
9778
+
9779
+ const lineFirstChar = line.charAt( 0 );
9780
+
9781
+ // @todo invoke passed in handler if any
9782
+ if ( lineFirstChar === '#' ) continue; // skip comments
9783
+
9784
+ if ( lineFirstChar === 'v' ) {
9785
+
9786
+ const data = line.split( _face_vertex_data_separator_pattern );
9787
+
9788
+ switch ( data[ 0 ] ) {
9789
+
9790
+ case 'v':
9791
+ state.vertices.push(
9792
+ parseFloat( data[ 1 ] ),
9793
+ parseFloat( data[ 2 ] ),
9794
+ parseFloat( data[ 3 ] )
9795
+ );
9796
+ if ( data.length >= 7 ) {
9797
+
9798
+ _color.setRGB(
9799
+ parseFloat( data[ 4 ] ),
9800
+ parseFloat( data[ 5 ] ),
9801
+ parseFloat( data[ 6 ] ),
9802
+ THREE.SRGBColorSpace
9803
+ );
9804
+
9805
+ state.colors.push( _color.r, _color.g, _color.b );
9806
+
9807
+ } else {
9808
+
9809
+ // if no colors are defined, add placeholders so color and vertex indices match
9810
+
9811
+ state.colors.push( undefined, undefined, undefined );
9812
+
9813
+ }
9814
+
9815
+ break;
9816
+ case 'vn':
9817
+ state.normals.push(
9818
+ parseFloat( data[ 1 ] ),
9819
+ parseFloat( data[ 2 ] ),
9820
+ parseFloat( data[ 3 ] )
9821
+ );
9822
+ break;
9823
+ case 'vt':
9824
+ state.uvs.push(
9825
+ parseFloat( data[ 1 ] ),
9826
+ parseFloat( data[ 2 ] )
9827
+ );
9828
+ break;
9829
+
9830
+ }
9831
+
9832
+ } else if ( lineFirstChar === 'f' ) {
9833
+
9834
+ const lineData = line.slice( 1 ).trim();
9835
+ const vertexData = lineData.split( _face_vertex_data_separator_pattern );
9836
+ const faceVertices = [];
9837
+
9838
+ // Parse the face vertex data into an easy to work with format
9839
+
9840
+ for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {
9841
+
9842
+ const vertex = vertexData[ j ];
9843
+
9844
+ if ( vertex.length > 0 ) {
9845
+
9846
+ const vertexParts = vertex.split( '/' );
9847
+ faceVertices.push( vertexParts );
9848
+
9849
+ }
9850
+
9851
+ }
9852
+
9853
+ // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
9854
+
9855
+ const v1 = faceVertices[ 0 ];
9856
+
9857
+ for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
9858
+
9859
+ const v2 = faceVertices[ j ];
9860
+ const v3 = faceVertices[ j + 1 ];
9861
+
9862
+ state.addFace(
9863
+ v1[ 0 ], v2[ 0 ], v3[ 0 ],
9864
+ v1[ 1 ], v2[ 1 ], v3[ 1 ],
9865
+ v1[ 2 ], v2[ 2 ], v3[ 2 ]
9866
+ );
9867
+
9868
+ }
9869
+
9870
+ } else if ( lineFirstChar === 'l' ) {
9871
+
9872
+ const lineParts = line.substring( 1 ).trim().split( ' ' );
9873
+ let lineVertices = [];
9874
+ const lineUVs = [];
9875
+
9876
+ if ( line.indexOf( '/' ) === - 1 ) {
9877
+
9878
+ lineVertices = lineParts;
9879
+
9880
+ } else {
9881
+
9882
+ for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {
9883
+
9884
+ const parts = lineParts[ li ].split( '/' );
9885
+
9886
+ if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
9887
+ if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
9888
+
9889
+ }
9890
+
9891
+ }
9892
+
9893
+ state.addLineGeometry( lineVertices, lineUVs );
9894
+
9895
+ } else if ( lineFirstChar === 'p' ) {
9896
+
9897
+ const lineData = line.slice( 1 ).trim();
9898
+ const pointData = lineData.split( ' ' );
9899
+
9900
+ state.addPointGeometry( pointData );
9901
+
9902
+ } else if ( ( result = _object_pattern.exec( line ) ) !== null ) {
9903
+
9904
+ // o object_name
9905
+ // or
9906
+ // g group_name
9907
+
9908
+ // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
9909
+ // let name = result[ 0 ].slice( 1 ).trim();
9910
+ const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 );
9911
+
9912
+ state.startObject( name );
9913
+
9914
+ } else if ( _material_use_pattern.test( line ) ) {
9915
+
9916
+ // material
9917
+
9918
+ state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
9919
+
9920
+ } else if ( _material_library_pattern.test( line ) ) {
9921
+
9922
+ // mtl file
9923
+
9924
+ state.materialLibraries.push( line.substring( 7 ).trim() );
9925
+
9926
+ } else if ( _map_use_pattern.test( line ) ) {
9927
+
9928
+ // the line is parsed but ignored since the loader assumes textures are defined MTL files
9929
+ // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
9930
+
9931
+ console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
9932
+
9933
+ } else if ( lineFirstChar === 's' ) {
9934
+
9935
+ result = line.split( ' ' );
9936
+
9937
+ // smooth shading
9938
+
9939
+ // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
9940
+ // but does not define a usemtl for each face set.
9941
+ // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
9942
+ // This requires some care to not create extra material on each smooth value for "normal" obj files.
9943
+ // where explicit usemtl defines geometry groups.
9944
+ // Example asset: examples/models/obj/cerberus/Cerberus.obj
9945
+
9946
+ /*
9947
+ * http://paulbourke.net/dataformats/obj/
9948
+ *
9949
+ * From chapter "Grouping" Syntax explanation "s group_number":
9950
+ * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
9951
+ * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
9952
+ * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
9953
+ * than 0."
9954
+ */
9955
+ if ( result.length > 1 ) {
9956
+
9957
+ const value = result[ 1 ].trim().toLowerCase();
9958
+ state.object.smooth = ( value !== '0' && value !== 'off' );
9959
+
9960
+ } else {
9961
+
9962
+ // ZBrush can produce "s" lines #11707
9963
+ state.object.smooth = true;
9964
+
9965
+ }
9966
+
9967
+ const material = state.object.currentMaterial();
9968
+ if ( material ) material.smooth = state.object.smooth;
9969
+
9970
+ } else {
9971
+
9972
+ // Handle null terminated files without exception
9973
+ if ( line === '\0' ) continue;
9974
+
9975
+ console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
9976
+
9977
+ }
9978
+
9979
+ }
9980
+
9981
+ state.finalize();
9982
+
9983
+ const container = new THREE.Group();
9984
+ container.materialLibraries = [].concat( state.materialLibraries );
9985
+
9986
+ const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
9987
+
9988
+ if ( hasPrimitives === true ) {
9989
+
9990
+ for ( let i = 0, l = state.objects.length; i < l; i ++ ) {
9991
+
9992
+ const object = state.objects[ i ];
9993
+ const geometry = object.geometry;
9994
+ const materials = object.materials;
9995
+ const isLine = ( geometry.type === 'Line' );
9996
+ const isPoints = ( geometry.type === 'Points' );
9997
+ let hasVertexColors = false;
9998
+
9999
+ // Skip o/g line declarations that did not follow with any faces
10000
+ if ( geometry.vertices.length === 0 ) continue;
10001
+
10002
+ const buffergeometry = new THREE.BufferGeometry();
10003
+
10004
+ buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) );
10005
+
10006
+ if ( geometry.normals.length > 0 ) {
10007
+
10008
+ buffergeometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) );
10009
+
10010
+ }
10011
+
10012
+ if ( geometry.colors.length > 0 ) {
10013
+
10014
+ hasVertexColors = true;
10015
+ buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) );
10016
+
10017
+ }
10018
+
10019
+ if ( geometry.hasUVIndices === true ) {
10020
+
10021
+ buffergeometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) );
10022
+
10023
+ }
10024
+
10025
+ // Create materials
10026
+
10027
+ const createdMaterials = [];
10028
+
10029
+ for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
10030
+
10031
+ const sourceMaterial = materials[ mi ];
10032
+ const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
10033
+ let material = state.materials[ materialHash ];
10034
+
10035
+ if ( this.materials !== null ) {
10036
+
10037
+ material = this.materials.create( sourceMaterial.name );
10038
+
10039
+ // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
10040
+ if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
10041
+
10042
+ const materialLine = new THREE.LineBasicMaterial();
10043
+ THREE.Material.prototype.copy.call( materialLine, material );
10044
+ materialLine.color.copy( material.color );
10045
+ material = materialLine;
10046
+
10047
+ } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) {
10048
+
10049
+ const materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } );
10050
+ THREE.Material.prototype.copy.call( materialPoints, material );
10051
+ materialPoints.color.copy( material.color );
10052
+ materialPoints.map = material.map;
10053
+ material = materialPoints;
10054
+
10055
+ }
10056
+
10057
+ }
10058
+
10059
+ if ( material === undefined ) {
10060
+
10061
+ if ( isLine ) {
10062
+
10063
+ material = new THREE.LineBasicMaterial();
10064
+
10065
+ } else if ( isPoints ) {
10066
+
10067
+ material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } );
10068
+
10069
+ } else {
10070
+
10071
+ material = new THREE.MeshPhongMaterial();
10072
+
10073
+ }
10074
+
10075
+ material.name = sourceMaterial.name;
10076
+ material.flatShading = sourceMaterial.smooth ? false : true;
10077
+ material.vertexColors = hasVertexColors;
10078
+
10079
+ state.materials[ materialHash ] = material;
10080
+
10081
+ }
10082
+
10083
+ createdMaterials.push( material );
10084
+
10085
+ }
10086
+
10087
+ // Create mesh
10088
+
10089
+ let mesh;
10090
+
10091
+ if ( createdMaterials.length > 1 ) {
10092
+
10093
+ for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
10094
+
10095
+ const sourceMaterial = materials[ mi ];
10096
+ buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
10097
+
10098
+ }
10099
+
10100
+ if ( isLine ) {
10101
+
10102
+ mesh = new THREE.LineSegments( buffergeometry, createdMaterials );
10103
+
10104
+ } else if ( isPoints ) {
10105
+
10106
+ mesh = new THREE.Points( buffergeometry, createdMaterials );
10107
+
10108
+ } else {
10109
+
10110
+ mesh = new THREE.Mesh( buffergeometry, createdMaterials );
10111
+
10112
+ }
10113
+
10114
+ } else {
10115
+
10116
+ if ( isLine ) {
10117
+
10118
+ mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] );
10119
+
10120
+ } else if ( isPoints ) {
10121
+
10122
+ mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] );
10123
+
10124
+ } else {
10125
+
10126
+ mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] );
10127
+
10128
+ }
10129
+
10130
+ }
10131
+
10132
+ mesh.name = object.name;
10133
+
10134
+ container.add( mesh );
10135
+
10136
+ }
10137
+
10138
+ } else {
10139
+
10140
+ // if there is only the default parser state object with no geometry data, interpret data as point cloud
10141
+
10142
+ if ( state.vertices.length > 0 ) {
10143
+
10144
+ const material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } );
10145
+
10146
+ const buffergeometry = new THREE.BufferGeometry();
10147
+
10148
+ buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( state.vertices, 3 ) );
10149
+
10150
+ if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
10151
+
10152
+ buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( state.colors, 3 ) );
10153
+ material.vertexColors = true;
10154
+
10155
+ }
10156
+
10157
+ const points = new THREE.Points( buffergeometry, material );
10158
+ container.add( points );
10159
+
10160
+ }
10161
+
10162
+ }
10163
+
10164
+ return container;
10165
+
10166
+ }
10167
+
10168
+ }
10169
+
9234
10170
  var ModelPreloader = /*#__PURE__*/function () {
9235
10171
  function ModelPreloader() {
9236
10172
  _classCallCheck(this, ModelPreloader);
9237
- this.modelCache = new Map(); // Cache for loaded GLB models
10173
+ this.modelCache = new Map(); // Cache for loaded models
9238
10174
  this.loadingPromises = new Map(); // Track ongoing loads to prevent duplicates
9239
10175
  this.gltfLoader = new GLTFLoader();
10176
+ this.objLoader = new OBJLoader();
9240
10177
  this.isPreloading = false;
9241
10178
  this.preloadingPromise = null;
9242
10179
  this.componentDictionary = null;
9243
- console.log('🚀 ModelPreloader initialized');
10180
+ console.log('🚀 ModelPreloader initialized with GLB and OBJ support');
9244
10181
  }
9245
10182
 
9246
10183
  /**
@@ -9253,7 +10190,7 @@ var ModelPreloader = /*#__PURE__*/function () {
9253
10190
  value: (function () {
9254
10191
  var _preloadAllModels = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(componentDictionary) {
9255
10192
  var _this = this;
9256
- var modelKeys, preloadPromises;
10193
+ var modelsToLoad, preloadPromises;
9257
10194
  return _regenerator().w(function (_context) {
9258
10195
  while (1) switch (_context.n) {
9259
10196
  case 0:
@@ -9274,21 +10211,33 @@ var ModelPreloader = /*#__PURE__*/function () {
9274
10211
  this.componentDictionary = componentDictionary;
9275
10212
  this.isPreloading = true;
9276
10213
  console.log('🔄 Starting to preload all models from component dictionary...');
9277
- modelKeys = [];
9278
- preloadPromises = []; // Extract all unique model keys from the component dictionary
10214
+ modelsToLoad = [];
10215
+ preloadPromises = []; // Extract all unique models with their types from the component dictionary
9279
10216
  Object.keys(componentDictionary).forEach(function (componentType) {
9280
10217
  var component = componentDictionary[componentType];
9281
10218
  if (component && component.modelKey) {
9282
- if (!modelKeys.includes(component.modelKey)) {
9283
- modelKeys.push(component.modelKey);
10219
+ var modelInfo = {
10220
+ modelKey: component.modelKey,
10221
+ modelType: component.modelType || 'glb' // Default to GLB if not specified
10222
+ };
10223
+
10224
+ // Check if we already have this model in our list
10225
+ var existingModel = modelsToLoad.find(function (m) {
10226
+ return m.modelKey === modelInfo.modelKey;
10227
+ });
10228
+ if (!existingModel) {
10229
+ modelsToLoad.push(modelInfo);
9284
10230
  }
9285
10231
  }
9286
10232
  });
9287
- console.log("\uD83C\uDFAF Found ".concat(modelKeys.length, " unique models to preload:"), modelKeys);
10233
+ console.log("\uD83C\uDFAF Found ".concat(modelsToLoad.length, " unique models to preload:"));
10234
+ modelsToLoad.forEach(function (model) {
10235
+ console.log(" \uD83D\uDCE6 ".concat(model.modelKey, " (").concat(model.modelType.toUpperCase(), ")"));
10236
+ });
9288
10237
 
9289
10238
  // Create preload promises for each model
9290
- modelKeys.forEach(function (modelKey) {
9291
- preloadPromises.push(_this.preloadSingleModel(modelKey));
10239
+ modelsToLoad.forEach(function (modelInfo) {
10240
+ preloadPromises.push(_this.preloadSingleModel(modelInfo.modelKey, modelInfo.modelType));
9292
10241
  });
9293
10242
 
9294
10243
  // Wait for all models to load (or fail)
@@ -9311,7 +10260,7 @@ var ModelPreloader = /*#__PURE__*/function () {
9311
10260
  return {
9312
10261
  successful: successful,
9313
10262
  failed: failed,
9314
- total: modelKeys.length,
10263
+ total: modelsToLoad.length,
9315
10264
  cache: _this.modelCache
9316
10265
  };
9317
10266
  });
@@ -9327,6 +10276,7 @@ var ModelPreloader = /*#__PURE__*/function () {
9327
10276
  /**
9328
10277
  * Preload a single model
9329
10278
  * @param {string} modelKey - The model key (filename)
10279
+ * @param {string} modelType - The model type ('glb' or 'obj')
9330
10280
  * @returns {Promise} Promise that resolves with the loaded model
9331
10281
  */
9332
10282
  )
@@ -9335,10 +10285,13 @@ var ModelPreloader = /*#__PURE__*/function () {
9335
10285
  value: (function () {
9336
10286
  var _preloadSingleModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(modelKey) {
9337
10287
  var _this2 = this;
9338
- var loadPromise;
10288
+ var modelType,
10289
+ loadPromise,
10290
+ _args2 = arguments;
9339
10291
  return _regenerator().w(function (_context2) {
9340
10292
  while (1) switch (_context2.n) {
9341
10293
  case 0:
10294
+ modelType = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : 'glb';
9342
10295
  if (!this.modelCache.has(modelKey)) {
9343
10296
  _context2.n = 1;
9344
10297
  break;
@@ -9353,28 +10306,72 @@ var ModelPreloader = /*#__PURE__*/function () {
9353
10306
  console.log("\u23F3 Model ".concat(modelKey, " already loading, waiting for completion"));
9354
10307
  return _context2.a(2, this.loadingPromises.get(modelKey));
9355
10308
  case 2:
9356
- console.log("\uD83D\uDD04 Starting preload of model: ".concat(modelKey));
10309
+ console.log("\uD83D\uDD04 Starting preload of ".concat(modelType.toUpperCase(), " model: ").concat(modelKey));
9357
10310
  loadPromise = new Promise(function (resolve, reject) {
9358
- _this2.gltfLoader.load("/library/models/".concat(modelKey), function (gltf) {
9359
- console.log("\u2705 Successfully preloaded model: ".concat(modelKey));
9360
- // Cache the scene for future use
9361
- _this2.modelCache.set(modelKey, gltf.scene);
9362
- // Remove from loading promises
9363
- _this2.loadingPromises.delete(modelKey);
9364
- resolve(gltf.scene);
9365
- }, function (progress) {
9366
- // Optional: track loading progress
9367
- var percentage = progress.loaded / progress.total * 100;
9368
- if (percentage % 25 === 0) {
9369
- // Log every 25%
9370
- console.log("\uD83D\uDCCA Loading ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
9371
- }
9372
- }, function (error) {
9373
- console.error("\u274C Failed to preload model ".concat(modelKey, ":"), error);
9374
- // Remove from loading promises
9375
- _this2.loadingPromises.delete(modelKey);
9376
- reject(error);
9377
- });
10311
+ var modelPath = "/library/models/".concat(modelKey);
10312
+ if (modelType === 'obj') {
10313
+ // Load OBJ model
10314
+ _this2.objLoader.load(modelPath, function (object) {
10315
+ console.log("\u2705 Successfully preloaded OBJ model: ".concat(modelKey));
10316
+
10317
+ // Apply default material to OBJ models (they don't come with materials)
10318
+ object.traverse(function (child) {
10319
+ if (child.isMesh) {
10320
+ if (!child.material) {
10321
+ child.material = new THREE__namespace.MeshStandardMaterial({
10322
+ color: 0x888888,
10323
+ metalness: 0.2,
10324
+ roughness: 0.8
10325
+ });
10326
+ }
10327
+ }
10328
+ });
10329
+
10330
+ // Cache the object for future use
10331
+ _this2.modelCache.set(modelKey, object);
10332
+ // Remove from loading promises
10333
+ _this2.loadingPromises.delete(modelKey);
10334
+ resolve(object);
10335
+ }, function (progress) {
10336
+ // Optional: track loading progress
10337
+ if (progress.lengthComputable) {
10338
+ var percentage = progress.loaded / progress.total * 100;
10339
+ if (percentage % 25 === 0) {
10340
+ // Log every 25%
10341
+ console.log("\uD83D\uDCCA Loading OBJ ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
10342
+ }
10343
+ }
10344
+ }, function (error) {
10345
+ console.error("\u274C Failed to preload OBJ model ".concat(modelKey, ":"), error);
10346
+ // Remove from loading promises
10347
+ _this2.loadingPromises.delete(modelKey);
10348
+ reject(error);
10349
+ });
10350
+ } else {
10351
+ // Load GLB model (default)
10352
+ _this2.gltfLoader.load(modelPath, function (gltf) {
10353
+ console.log("\u2705 Successfully preloaded GLB model: ".concat(modelKey));
10354
+ // Cache the scene for future use
10355
+ _this2.modelCache.set(modelKey, gltf.scene);
10356
+ // Remove from loading promises
10357
+ _this2.loadingPromises.delete(modelKey);
10358
+ resolve(gltf.scene);
10359
+ }, function (progress) {
10360
+ // Optional: track loading progress
10361
+ if (progress.lengthComputable) {
10362
+ var percentage = progress.loaded / progress.total * 100;
10363
+ if (percentage % 25 === 0) {
10364
+ // Log every 25%
10365
+ console.log("\uD83D\uDCCA Loading GLB ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
10366
+ }
10367
+ }
10368
+ }, function (error) {
10369
+ console.error("\u274C Failed to preload GLB model ".concat(modelKey, ":"), error);
10370
+ // Remove from loading promises
10371
+ _this2.loadingPromises.delete(modelKey);
10372
+ reject(error);
10373
+ });
10374
+ }
9378
10375
  }); // Cache the loading promise
9379
10376
  this.loadingPromises.set(modelKey, loadPromise);
9380
10377
  return _context2.a(2, loadPromise);
@@ -9498,23 +10495,58 @@ var ModelPreloader = /*#__PURE__*/function () {
9498
10495
  /**
9499
10496
  * Force reload a specific model
9500
10497
  * @param {string} modelKey - The model key to reload
10498
+ * @param {string} modelType - The model type ('glb' or 'obj'), will try to detect from component dictionary if not provided
9501
10499
  * @returns {Promise} Promise that resolves with the reloaded model
9502
10500
  */
9503
10501
  }, {
9504
10502
  key: "reloadModel",
9505
10503
  value: (function () {
9506
10504
  var _reloadModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(modelKey) {
10505
+ var modelType,
10506
+ _i,
10507
+ _Object$keys,
10508
+ componentType,
10509
+ component,
10510
+ _args3 = arguments;
9507
10511
  return _regenerator().w(function (_context3) {
9508
10512
  while (1) switch (_context3.n) {
9509
10513
  case 0:
10514
+ modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : null;
9510
10515
  console.log("\uD83D\uDD04 Force reloading model: ".concat(modelKey));
9511
10516
 
10517
+ // Try to determine model type from component dictionary if not provided
10518
+ if (!(!modelType && this.componentDictionary)) {
10519
+ _context3.n = 3;
10520
+ break;
10521
+ }
10522
+ _i = 0, _Object$keys = Object.keys(this.componentDictionary);
10523
+ case 1:
10524
+ if (!(_i < _Object$keys.length)) {
10525
+ _context3.n = 3;
10526
+ break;
10527
+ }
10528
+ componentType = _Object$keys[_i];
10529
+ component = this.componentDictionary[componentType];
10530
+ if (!(component && component.modelKey === modelKey)) {
10531
+ _context3.n = 2;
10532
+ break;
10533
+ }
10534
+ modelType = component.modelType || 'glb';
10535
+ return _context3.a(3, 3);
10536
+ case 2:
10537
+ _i++;
10538
+ _context3.n = 1;
10539
+ break;
10540
+ case 3:
10541
+ // Default to GLB if still not determined
10542
+ modelType = modelType || 'glb';
10543
+
9512
10544
  // Remove from cache and loading promises
9513
10545
  this.modelCache.delete(modelKey);
9514
10546
  this.loadingPromises.delete(modelKey);
9515
10547
 
9516
10548
  // Preload again
9517
- return _context3.a(2, this.preloadSingleModel(modelKey));
10549
+ return _context3.a(2, this.preloadSingleModel(modelKey, modelType));
9518
10550
  }
9519
10551
  }, _callee3, this);
9520
10552
  }));
@@ -9559,6 +10591,100 @@ var ModelPreloader = /*#__PURE__*/function () {
9559
10591
  console.log('✅ Model preloader cache cleared');
9560
10592
  }
9561
10593
 
10594
+ /**
10595
+ * Get model type from component dictionary
10596
+ * @param {string} modelKey - The model key
10597
+ * @returns {string} Model type ('glb' or 'obj')
10598
+ */
10599
+ }, {
10600
+ key: "getModelType",
10601
+ value: function getModelType(modelKey) {
10602
+ if (!this.componentDictionary) {
10603
+ return 'glb'; // Default fallback
10604
+ }
10605
+ for (var _i2 = 0, _Object$keys2 = Object.keys(this.componentDictionary); _i2 < _Object$keys2.length; _i2++) {
10606
+ var componentType = _Object$keys2[_i2];
10607
+ var component = this.componentDictionary[componentType];
10608
+ if (component && component.modelKey === modelKey) {
10609
+ return component.modelType || 'glb';
10610
+ }
10611
+ }
10612
+ return 'glb'; // Default fallback
10613
+ }
10614
+
10615
+ /**
10616
+ * Load a component model by its library ID (for SceneOperationsManager compatibility)
10617
+ * @param {string} libraryId - The library ID to look up
10618
+ * @param {Function} callback - Callback function to receive the loaded model
10619
+ */
10620
+ }, {
10621
+ key: "loadComponentById",
10622
+ value: function loadComponentById(libraryId, callback) {
10623
+ if (!this.componentDictionary || !libraryId || typeof callback !== 'function') {
10624
+ console.warn("\u26A0\uFE0F Invalid parameters for loadComponentById: libraryId=".concat(libraryId, ", callback=").concat(_typeof(callback)));
10625
+ callback(null);
10626
+ return;
10627
+ }
10628
+
10629
+ // Find the component data by library ID
10630
+ var componentData = this.componentDictionary[libraryId];
10631
+ if (!componentData || !componentData.modelKey) {
10632
+ console.warn("\u26A0\uFE0F No component found for library ID: ".concat(libraryId));
10633
+ callback(null);
10634
+ return;
10635
+ }
10636
+ var modelKey = componentData.modelKey;
10637
+ var modelType = componentData.modelType || 'glb';
10638
+
10639
+ // Check if model is already cached
10640
+ if (this.modelCache.has(modelKey)) {
10641
+ console.log("\uD83C\uDFAF Returning cached model for library ID ".concat(libraryId, ": ").concat(modelKey));
10642
+ var clonedModel = this.modelCache.get(modelKey).clone();
10643
+
10644
+ // Add dimensions if available
10645
+ if (componentData.boundingBox) {
10646
+ if (!clonedModel.userData) {
10647
+ clonedModel.userData = {};
10648
+ }
10649
+ clonedModel.userData.dimensions = {
10650
+ x: componentData.boundingBox.x,
10651
+ y: componentData.boundingBox.y,
10652
+ z: componentData.boundingBox.z
10653
+ };
10654
+ }
10655
+ callback(clonedModel);
10656
+ return;
10657
+ }
10658
+
10659
+ // Model not cached, need to load it
10660
+ console.log("\uD83D\uDD04 Loading model for library ID ".concat(libraryId, ": ").concat(modelKey, " (").concat(modelType.toUpperCase(), ")"));
10661
+ this.preloadSingleModel(modelKey, modelType).then(function (model) {
10662
+ if (model) {
10663
+ var _clonedModel = model.clone();
10664
+
10665
+ // Add dimensions if available
10666
+ if (componentData.boundingBox) {
10667
+ if (!_clonedModel.userData) {
10668
+ _clonedModel.userData = {};
10669
+ }
10670
+ _clonedModel.userData.dimensions = {
10671
+ x: componentData.boundingBox.x,
10672
+ y: componentData.boundingBox.y,
10673
+ z: componentData.boundingBox.z
10674
+ };
10675
+ }
10676
+ console.log("\u2705 Successfully loaded model for library ID ".concat(libraryId));
10677
+ callback(_clonedModel);
10678
+ } else {
10679
+ console.error("\u274C Failed to load model for library ID ".concat(libraryId));
10680
+ callback(null);
10681
+ }
10682
+ }).catch(function (error) {
10683
+ console.error("\u274C Error loading model for library ID ".concat(libraryId, ":"), error);
10684
+ callback(null);
10685
+ });
10686
+ }
10687
+
9562
10688
  /**
9563
10689
  * Get cache statistics
9564
10690
  * @returns {Object} Cache statistics
@@ -22858,6 +23984,7 @@ var CentralPlant = /*#__PURE__*/function () {
22858
23984
  // Name utilities
22859
23985
  this.utilities.generateUuidFromName = generateUuidFromName;
22860
23986
  this.utilities.getHardcodedUuid = getHardcodedUuid;
23987
+ this.utilities.findObjectByHardcodedUuid = findObjectByHardcodedUuid;
22861
23988
 
22862
23989
  // Loggers
22863
23990
  this.utilities.logger = logger;
@@ -23906,6 +25033,17 @@ var CentralPlant = /*#__PURE__*/function () {
23906
25033
  return _objectSpread2({}, this.managers);
23907
25034
  }
23908
25035
 
25036
+ /**
25037
+ * Get a specific manager instance
25038
+ * @param {string} managerName - The name of the manager to retrieve
25039
+ * @returns {Object|null} The manager instance or null if not found
25040
+ */
25041
+ }, {
25042
+ key: "getManager",
25043
+ value: function getManager(managerName) {
25044
+ return this.managers[managerName] || null;
25045
+ }
25046
+
23909
25047
  /**
23910
25048
  * Get all utilities for external access
23911
25049
  * @returns {Object} All utility instances
@@ -23915,6 +25053,17 @@ var CentralPlant = /*#__PURE__*/function () {
23915
25053
  value: function getAllUtilities() {
23916
25054
  return _objectSpread2({}, this.utilities);
23917
25055
  }
25056
+
25057
+ /**
25058
+ * Get a specific utility instance
25059
+ * @param {string} utilityName - The name of the utility to retrieve
25060
+ * @returns {any|null} The utility instance or null if not found
25061
+ */
25062
+ }, {
25063
+ key: "getUtility",
25064
+ value: function getUtility(utilityName) {
25065
+ return this.utilities[utilityName] || null;
25066
+ }
23918
25067
  }]);
23919
25068
  }();
23920
25069
 
@@ -31389,7 +32538,7 @@ var Export = /*#__PURE__*/function () {
31389
32538
  ply: new PLYExporter()
31390
32539
  };
31391
32540
  this.supportedFormats = {
31392
- models: ['gltf', 'glb', 'obj', 'stl', 'ply', 'dae'],
32541
+ models: ['gltf', 'glb', 'obj', 'stl', 'ply'],
31393
32542
  scenes: ['json'],
31394
32543
  images: ['png', 'jpg', 'jpeg', 'webp'],
31395
32544
  data: ['json', 'csv', 'xml']
@@ -31432,41 +32581,35 @@ var Export = /*#__PURE__*/function () {
31432
32581
  includeCustomExtensions: false
31433
32582
  }, options);
31434
32583
  _t = format.toLowerCase();
31435
- _context.n = _t === 'gltf' ? 2 : _t === 'glb' ? 2 : _t === 'obj' ? 4 : _t === 'stl' ? 6 : _t === 'ply' ? 8 : _t === 'dae' ? 10 : 12;
32584
+ _context.n = _t === 'gltf' ? 2 : _t === 'glb' ? 2 : _t === 'obj' ? 4 : _t === 'stl' ? 6 : _t === 'ply' ? 8 : 10;
31436
32585
  break;
31437
32586
  case 2:
31438
32587
  _context.n = 3;
31439
32588
  return this.exportGLTF(object, exportOptions);
31440
32589
  case 3:
31441
32590
  result = _context.v;
31442
- return _context.a(3, 13);
32591
+ return _context.a(3, 11);
31443
32592
  case 4:
31444
32593
  _context.n = 5;
31445
32594
  return this.exportOBJ(object, exportOptions);
31446
32595
  case 5:
31447
32596
  result = _context.v;
31448
- return _context.a(3, 13);
32597
+ return _context.a(3, 11);
31449
32598
  case 6:
31450
32599
  _context.n = 7;
31451
32600
  return this.exportSTL(object, exportOptions);
31452
32601
  case 7:
31453
32602
  result = _context.v;
31454
- return _context.a(3, 13);
32603
+ return _context.a(3, 11);
31455
32604
  case 8:
31456
32605
  _context.n = 9;
31457
32606
  return this.exportPLY(object, exportOptions);
31458
32607
  case 9:
31459
32608
  result = _context.v;
31460
- return _context.a(3, 13);
32609
+ return _context.a(3, 11);
31461
32610
  case 10:
31462
- _context.n = 11;
31463
- return this.exportCollada(object, exportOptions);
31464
- case 11:
31465
- result = _context.v;
31466
- return _context.a(3, 13);
31467
- case 12:
31468
32611
  throw new Error("Unsupported format: ".concat(format));
31469
- case 13:
32612
+ case 11:
31470
32613
  exportTime = performance.now() - startTime;
31471
32614
  exportRecord = {
31472
32615
  timestamp: new Date().toISOString(),
@@ -31484,8 +32627,8 @@ var Export = /*#__PURE__*/function () {
31484
32627
  exportTime: exportTime,
31485
32628
  filename: this.generateFilename(object.name || 'model', format)
31486
32629
  });
31487
- case 14:
31488
- _context.p = 14;
32630
+ case 12:
32631
+ _context.p = 12;
31489
32632
  _t2 = _context.v;
31490
32633
  _exportTime = performance.now() - startTime;
31491
32634
  _exportRecord = {
@@ -31500,10 +32643,10 @@ var Export = /*#__PURE__*/function () {
31500
32643
  this.exportHistory.push(_exportRecord);
31501
32644
  logger.error("\u274C Failed to export model to ".concat(format.toUpperCase(), ":"), _t2);
31502
32645
  throw _t2;
31503
- case 15:
32646
+ case 13:
31504
32647
  return _context.a(2);
31505
32648
  }
31506
- }, _callee, this, [[1, 14]]);
32649
+ }, _callee, this, [[1, 12]]);
31507
32650
  }));
31508
32651
  function exportModel(_x, _x2) {
31509
32652
  return _exportModel.apply(this, arguments);
@@ -31628,36 +32771,6 @@ var Export = /*#__PURE__*/function () {
31628
32771
  }
31629
32772
  return exportPLY;
31630
32773
  }()
31631
- /**
31632
- * Export to Collada (DAE) format
31633
- * @param {THREE.Object3D} object - Object to export
31634
- * @param {Object} options - Export options
31635
- * @returns {Promise<string>} Collada XML string
31636
- */
31637
- )
31638
- }, {
31639
- key: "exportCollada",
31640
- value: (function () {
31641
- var _exportCollada = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(object) {
31642
- var _this5 = this;
31643
- var options,
31644
- _args6 = arguments;
31645
- return _regenerator().w(function (_context6) {
31646
- while (1) switch (_context6.n) {
31647
- case 0:
31648
- options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
31649
- return _context6.a(2, new Promise(function (resolve) {
31650
- var result = _this5.exporters.collada.parse(object, options);
31651
- resolve(result.data);
31652
- }));
31653
- }
31654
- }, _callee6);
31655
- }));
31656
- function exportCollada(_x7) {
31657
- return _exportCollada.apply(this, arguments);
31658
- }
31659
- return exportCollada;
31660
- }()
31661
32774
  /**
31662
32775
  * Export scene configuration to JSON
31663
32776
  * @param {THREE.Scene} scene - Scene to export
@@ -31700,7 +32813,7 @@ var Export = /*#__PURE__*/function () {
31700
32813
  }, {
31701
32814
  key: "serializeObject",
31702
32815
  value: function serializeObject(object) {
31703
- var _this6 = this;
32816
+ var _this5 = this;
31704
32817
  var serialized = {
31705
32818
  uuid: object.uuid,
31706
32819
  name: object.name,
@@ -31731,7 +32844,7 @@ var Export = /*#__PURE__*/function () {
31731
32844
 
31732
32845
  // Recursively serialize children
31733
32846
  object.children.forEach(function (child) {
31734
- serialized.children.push(_this6.serializeObject(child));
32847
+ serialized.children.push(_this5.serializeObject(child));
31735
32848
  });
31736
32849
  return serialized;
31737
32850
  }
@@ -31904,7 +33017,7 @@ var Export = /*#__PURE__*/function () {
31904
33017
  }, {
31905
33018
  key: "exportToXML",
31906
33019
  value: function exportToXML(data) {
31907
- var _this7 = this;
33020
+ var _this6 = this;
31908
33021
  var rootElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'root';
31909
33022
  var xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>\n';
31910
33023
  var _objectToXML = function objectToXML(obj) {
@@ -31923,12 +33036,12 @@ var Export = /*#__PURE__*/function () {
31923
33036
  if (_typeof(item) === 'object') {
31924
33037
  xml += '\n' + _objectToXML(item, indent + 1) + spaces;
31925
33038
  } else {
31926
- xml += _this7.escapeXML(item);
33039
+ xml += _this6.escapeXML(item);
31927
33040
  }
31928
33041
  xml += "</".concat(key, ">\n");
31929
33042
  });
31930
33043
  } else {
31931
- xml += "".concat(spaces, "<").concat(key, ">").concat(_this7.escapeXML(value), "</").concat(key, ">\n");
33044
+ xml += "".concat(spaces, "<").concat(key, ">").concat(_this6.escapeXML(value), "</").concat(key, ">\n");
31932
33045
  }
31933
33046
  });
31934
33047
  return xml;
@@ -31980,63 +33093,63 @@ var Export = /*#__PURE__*/function () {
31980
33093
  }, {
31981
33094
  key: "exportBatch",
31982
33095
  value: (function () {
31983
- var _exportBatch = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(objects) {
33096
+ var _exportBatch = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(objects) {
31984
33097
  var results, errors, _iterator, _step, item, result, _t3, _t4;
31985
- return _regenerator().w(function (_context7) {
31986
- while (1) switch (_context7.n) {
33098
+ return _regenerator().w(function (_context6) {
33099
+ while (1) switch (_context6.n) {
31987
33100
  case 0:
31988
33101
  logger.info("\uD83D\uDD04 Starting batch export of ".concat(objects.length, " objects..."));
31989
33102
  results = [];
31990
33103
  errors = [];
31991
33104
  _iterator = _createForOfIteratorHelper(objects);
31992
- _context7.p = 1;
33105
+ _context6.p = 1;
31993
33106
  _iterator.s();
31994
33107
  case 2:
31995
33108
  if ((_step = _iterator.n()).done) {
31996
- _context7.n = 7;
33109
+ _context6.n = 7;
31997
33110
  break;
31998
33111
  }
31999
33112
  item = _step.value;
32000
- _context7.p = 3;
32001
- _context7.n = 4;
33113
+ _context6.p = 3;
33114
+ _context6.n = 4;
32002
33115
  return this.exportModel(item.object, item.format, item.options);
32003
33116
  case 4:
32004
- result = _context7.v;
33117
+ result = _context6.v;
32005
33118
  results.push(result);
32006
- _context7.n = 6;
33119
+ _context6.n = 6;
32007
33120
  break;
32008
33121
  case 5:
32009
- _context7.p = 5;
32010
- _t3 = _context7.v;
33122
+ _context6.p = 5;
33123
+ _t3 = _context6.v;
32011
33124
  errors.push({
32012
33125
  object: item.object.name || 'Unnamed Object',
32013
33126
  format: item.format,
32014
33127
  error: _t3.message
32015
33128
  });
32016
33129
  case 6:
32017
- _context7.n = 2;
33130
+ _context6.n = 2;
32018
33131
  break;
32019
33132
  case 7:
32020
- _context7.n = 9;
33133
+ _context6.n = 9;
32021
33134
  break;
32022
33135
  case 8:
32023
- _context7.p = 8;
32024
- _t4 = _context7.v;
33136
+ _context6.p = 8;
33137
+ _t4 = _context6.v;
32025
33138
  _iterator.e(_t4);
32026
33139
  case 9:
32027
- _context7.p = 9;
33140
+ _context6.p = 9;
32028
33141
  _iterator.f();
32029
- return _context7.f(9);
33142
+ return _context6.f(9);
32030
33143
  case 10:
32031
33144
  logger.info("\u2705 Batch export complete: ".concat(results.length, " successful, ").concat(errors.length, " failed"));
32032
- return _context7.a(2, {
33145
+ return _context6.a(2, {
32033
33146
  results: results,
32034
33147
  errors: errors
32035
33148
  });
32036
33149
  }
32037
- }, _callee7, this, [[3, 5], [1, 8, 9, 10]]);
33150
+ }, _callee6, this, [[3, 5], [1, 8, 9, 10]]);
32038
33151
  }));
32039
- function exportBatch(_x8) {
33152
+ function exportBatch(_x7) {
32040
33153
  return _exportBatch.apply(this, arguments);
32041
33154
  }
32042
33155
  return exportBatch;