@@ -271,18 +271,6 @@ THREE.LDrawLoader = ( function () {
271271
272272 } , onProgress , onError ) ;
273273
274- function subobjectLoad ( url , onLoad , onProgress , onError , subobject ) {
275-
276- var fileLoader = new THREE . FileLoader ( scope . manager ) ;
277- fileLoader . setPath ( scope . path ) ;
278- fileLoader . load ( url , function ( text ) {
279-
280- processObject ( text , onLoad , subobject ) ;
281-
282- } , onProgress , onError ) ;
283-
284- }
285-
286274 function processObject ( text , onProcessed , subobject ) {
287275
288276 var parseScope = scope . newParseScopeLevel ( ) ;
@@ -292,6 +280,12 @@ THREE.LDrawLoader = ( function () {
292280
293281 // Add to cache
294282 var currentFileName = parentParseScope . currentFileName ;
283+ if ( currentFileName !== null ) {
284+
285+ currentFileName = parentParseScope . currentFileName . toLowerCase ( ) ;
286+
287+ }
288+
295289 if ( scope . subobjectCache [ currentFileName ] === undefined ) {
296290
297291 scope . subobjectCache [ currentFileName ] = text ;
@@ -308,37 +302,39 @@ THREE.LDrawLoader = ( function () {
308302 parseScope . numSubobjects = parseScope . subobjects . length ;
309303 parseScope . subobjectIndex = 0 ;
310304
311- if ( parseScope . numSubobjects > 0 ) {
305+ var finishedCount = 0 ;
306+ onSubobjectFinish ( ) ;
312307
313- // Load the first subobject
314- var subobjectGroup = loadSubobject ( parseScope . subobjects [ 0 ] , true ) ;
308+ return objGroup ;
315309
316- // Optimization for loading pack: If subobjects are obtained from cache, keep loading them iteratively rather than recursively
317- if ( subobjectGroup ) {
310+ function onSubobjectFinish ( ) {
318311
319- while ( subobjectGroup && parseScope . subobjectIndex < parseScope . numSubobjects - 1 ) {
312+ finishedCount ++ ;
320313
321- subobjectGroup = loadSubobject ( parseScope . subobjects [ ++ parseScope . subobjectIndex ] , true ) ;
314+ if ( finishedCount === parseScope . subobjects . length + 1 ) {
322315
323- }
324-
325- if ( subobjectGroup ) {
316+ finalizeObject ( ) ;
326317
327- finalizeObject ( ) ;
318+ } else {
328319
329- }
320+ // Once the previous subobject has finished we can start processing the next one in the list.
321+ // The subobject processing shares scope in processing so it's important that they be loaded serially
322+ // to avoid race conditions.
323+ // Promise.resolve is used as an approach to asynchronously schedule a task _before_ this frame ends to
324+ // avoid stack overflow exceptions when loading many subobjects from the cache. RequestAnimationFrame
325+ // will work but causes the load to happen after the next frame which causes the load to take significantly longer.
326+ var subobject = parseScope . subobjects [ parseScope . subobjectIndex ] ;
327+ Promise . resolve ( ) . then ( function ( ) {
330328
331- }
329+ loadSubobject ( subobject ) ;
332330
333- } else {
331+ } ) ;
332+ parseScope . subobjectIndex ++ ;
334333
335- // No subobjects, finish object
336- finalizeObject ( ) ;
334+ }
337335
338336 }
339337
340- return objGroup ;
341-
342338 function finalizeObject ( ) {
343339
344340 if ( ! scope . separateObjects && ! parentParseScope . isFromParse ) {
@@ -368,7 +364,7 @@ THREE.LDrawLoader = ( function () {
368364
369365 }
370366
371- function loadSubobject ( subobject , sync ) {
367+ function loadSubobject ( subobject ) {
372368
373369 parseScope . mainColourCode = subobject . material . userData . code ;
374370 parseScope . mainEdgeColourCode = subobject . material . userData . edgeMaterial . userData . code ;
@@ -382,16 +378,15 @@ THREE.LDrawLoader = ( function () {
382378 }
383379
384380 // If subobject was cached previously, use the cached one
385- var cached = scope . subobjectCache [ subobject . originalFileName ] ;
381+ var cached = scope . subobjectCache [ subobject . originalFileName . toLowerCase ( ) ] ;
386382 if ( cached ) {
387383
388- var subobjectGroup = processObject ( cached , sync ? undefined : onSubobjectLoaded , subobject ) ;
389- if ( sync ) {
384+ processObject ( cached , function ( subobjectGroup ) {
390385
391- addSubobject ( subobject , subobjectGroup ) ;
392- return subobjectGroup ;
386+ onSubobjectLoaded ( subobjectGroup , subobject ) ;
387+ onSubobjectFinish ( ) ;
393388
394- }
389+ } , subobject ) ;
395390
396391 return ;
397392
@@ -451,22 +446,6 @@ THREE.LDrawLoader = ( function () {
451446 // All location possibilities have been tried, give up loading this object
452447 console . warn ( 'LDrawLoader: Subobject "' + subobject . originalFileName + '" could not be found.' ) ;
453448
454- // Try to read the next subobject
455- parseScope . subobjectIndex ++ ;
456-
457- if ( parseScope . subobjectIndex >= parseScope . numSubobjects ) {
458-
459- // All subojects have been loaded. Finish parent object
460- scope . removeScopeLevel ( ) ;
461- onProcessed ( objGroup ) ;
462-
463- } else {
464-
465- // Load next subobject
466- loadSubobject ( parseScope . subobjects [ parseScope . subobjectIndex ] ) ;
467-
468- }
469-
470449 return ;
471450
472451 }
@@ -481,15 +460,22 @@ THREE.LDrawLoader = ( function () {
481460 fileLoader . setPath ( scope . path ) ;
482461 fileLoader . load ( subobjectURL , function ( text ) {
483462
484- processObject ( text , onSubobjectLoaded , subobject ) ;
463+ processObject ( text , function ( subobjectGroup ) {
485464
486- } , undefined , onSubobjectError ) ;
465+ onSubobjectLoaded ( subobjectGroup , subobject ) ;
466+ onSubobjectFinish ( ) ;
487467
488- }
468+ } , subobject ) ;
469+
470+ } , undefined , function ( err ) {
471+
472+ onSubobjectError ( err , subobject ) ;
473+
474+ } , subobject ) ;
489475
490- function onSubobjectLoaded ( subobjectGroup ) {
476+ }
491477
492- var subobject = parseScope . subobjects [ parseScope . subobjectIndex ] ;
478+ function onSubobjectLoaded ( subobjectGroup , subobject ) {
493479
494480 if ( subobjectGroup === null ) {
495481
@@ -502,20 +488,6 @@ THREE.LDrawLoader = ( function () {
502488 // Add the subobject just loaded
503489 addSubobject ( subobject , subobjectGroup ) ;
504490
505- // Proceed to load the next subobject, or finish the parent object
506-
507- parseScope . subobjectIndex ++ ;
508-
509- if ( parseScope . subobjectIndex < parseScope . numSubobjects ) {
510-
511- loadSubobject ( parseScope . subobjects [ parseScope . subobjectIndex ] ) ;
512-
513- } else {
514-
515- finalizeObject ( ) ;
516-
517- }
518-
519491 }
520492
521493 function addSubobject ( subobject , subobjectGroup ) {
@@ -533,10 +505,10 @@ THREE.LDrawLoader = ( function () {
533505
534506 }
535507
536- function onSubobjectError ( err ) {
508+ function onSubobjectError ( err , subobject ) {
537509
538510 // Retry download from a different default possible location
539- loadSubobject ( parseScope . subobjects [ parseScope . subobjectIndex ] ) ;
511+ loadSubobject ( subobject ) ;
540512
541513 }
542514
@@ -1071,7 +1043,7 @@ THREE.LDrawLoader = ( function () {
10711043 if ( line . startsWith ( '0 FILE ' ) ) {
10721044
10731045 // Save previous embedded file in the cache
1074- this . subobjectCache [ currentEmbeddedFileName ] = currentEmbeddedText ;
1046+ this . subobjectCache [ currentEmbeddedFileName . toLowerCase ( ) ] = currentEmbeddedText ;
10751047
10761048 // New embedded text file
10771049 currentEmbeddedFileName = line . substring ( 7 ) ;
@@ -1436,7 +1408,7 @@ THREE.LDrawLoader = ( function () {
14361408
14371409 if ( parsingEmbeddedFiles ) {
14381410
1439- this . subobjectCache [ currentEmbeddedFileName ] = currentEmbeddedText ;
1411+ this . subobjectCache [ currentEmbeddedFileName . toLowerCase ( ) ] = currentEmbeddedText ;
14401412
14411413 }
14421414
0 commit comments