123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /**
- * @author yomboprime / https://github.com/yomboprime/
- *
- * LDraw object packer
- *
- * Usage:
- *
- * - Download official parts library from LDraw.org and unzip in a directory (e.g. ldraw/)
- *
- * - Download your desired model file and place in the ldraw/models/ subfolder.
- *
- * - Place this script also in ldraw/
- *
- * - Issue command 'node packLDrawModel models/<modelFileName>'
- *
- * The packed object will be in ldraw/models/<modelFileName>_Packed.mpd and will contain all the object subtree as embedded files.
- *
- *
- */
- var ldrawPath = './';
- var materialsFileName = 'LDConfig.ldr';
- var fs = require( 'fs' );
- var path = require( 'path' );
- if ( process.argv.length !== 3 ) {
- console.log( "Usage: node packLDrawModel <modelFilePath>" );
- exit( 0 );
- }
- var fileName = process.argv[ 2 ];
- var materialsFilePath = path.join( ldrawPath, materialsFileName );
- console.log( 'Loading materials file "' + materialsFilePath + '"...' );
- var materialsContent = fs.readFileSync( materialsFilePath, { encoding: "utf8" } );
- console.log( 'Packing "' + fileName + '"...' );
- var objectsPaths = [];
- var objectsContents = [];
- var pathMap = {};
- var listOfNotFound = [];
- // Parse object tree
- parseObject( fileName, true );
- // Check if previously files not found are found now
- // (if so, probably they were already embedded)
- var someNotFound = false;
- for ( var i = 0; i < listOfNotFound.length; i ++ ) {
- if ( ! pathMap[ listOfNotFound[ i ] ] ) {
- someNotFound = true;
- console.log( 'Error: File object not found: "' + fileName + '".' );
- }
- }
- if ( someNotFound ) {
- console.log( "Some files were not found, aborting." );
- process.exit( - 1 );
- }
- // Obtain packed content
- var packedContent = materialsContent + "\n";
- for ( var i = objectsPaths.length - 1; i >= 0; i -- ) {
- packedContent += objectsContents[ i ];
- }
- packedContent += "\n";
- // Save output file
- var outPath = fileName + "_Packed.mpd";
- console.log( 'Writing "' + outPath + '"...' );
- fs.writeFileSync( outPath, packedContent );
- console.log( 'Done.' );
- //
- function parseObject( fileName, isRoot ) {
- // Returns the located path for fileName or null if not found
- console.log( 'Adding "' + fileName + '".' );
- var originalFileName = fileName;
- var prefix = "";
- var objectContent = null;
- for ( var attempt = 0; attempt < 2; attempt ++ ) {
- prefix = "";
- if ( attempt === 1 ) {
- fileName = fileName.toLowerCase();
- }
- if ( fileName.startsWith( '48/' ) ) {
- prefix = "p/";
- } else if ( fileName.startsWith( 's/' ) ) {
- prefix = "parts/";
- }
- var absoluteObjectPath = path.join( ldrawPath, fileName );
- try {
- objectContent = fs.readFileSync( absoluteObjectPath, { encoding: "utf8" } );
- break;
- } catch ( e ) {
- prefix = "parts/";
- absoluteObjectPath = path.join( ldrawPath, prefix, fileName );
- try {
- objectContent = fs.readFileSync( absoluteObjectPath, { encoding: "utf8" } );
- break;
- } catch ( e ) {
- prefix = "p/";
- absoluteObjectPath = path.join( ldrawPath, prefix, fileName );
- try {
- objectContent = fs.readFileSync( absoluteObjectPath, { encoding: "utf8" } );
- break;
- } catch ( e ) {
- try {
- prefix = "models/";
- absoluteObjectPath = path.join( ldrawPath, prefix, fileName );
- objectContent = fs.readFileSync( absoluteObjectPath, { encoding: "utf8" } );
- break;
- } catch ( e ) {
- if ( attempt === 1 ) {
- // The file has not been found, add to list of not found
- listOfNotFound.push( originalFileName );
- }
- }
- }
- }
- }
- }
- var objectPath = path.join( prefix, fileName );
- if ( ! objectContent ) {
- // File was not found, but could be a referenced embedded file.
- return null;
- }
- if ( objectContent.indexOf( '\r\n' ) !== - 1 ) {
- // This is faster than String.split with regex that splits on both
- objectContent = objectContent.replace( /\r\n/g, '\n' );
- }
- var processedObjectContent = isRoot ? "" : "0 FILE " + objectPath + "\n";
- var lines = objectContent.split( "\n" );
- for ( var i = 0, n = lines.length; i < n; i ++ ) {
- var line = lines[ i ];
- var lineLength = line.length;
- // Skip spaces/tabs
- var charIndex = 0;
- while ( ( line.charAt( charIndex ) === ' ' || line.charAt( charIndex ) === '\t' ) && charIndex < lineLength ) {
- charIndex ++;
- }
- line = line.substring( charIndex );
- lineLength = line.length;
- charIndex = 0;
- if ( line.startsWith( '0 FILE ' ) ) {
- if ( i === 0 ) {
- // Ignore first line FILE meta directive
- continue;
- }
- // Embedded object was found, add to path map
- var subobjectFileName = line.substring( charIndex ).trim().replace( "\\", "/" );
- if ( subobjectFileName ) {
- // Find name in path cache
- var subobjectPath = pathMap[ subobjectFileName ];
- if ( ! subobjectPath ) {
- pathMap[ subobjectFileName ] = subobjectFileName;
- }
- }
- }
- if ( line.startsWith( '1 ' ) ) {
- // Subobject, add it
- charIndex = 2;
- // Skip material, position and transform
- for ( var token = 0; token < 13 && charIndex < lineLength; token ++ ) {
- // Skip token
- while ( line.charAt( charIndex ) !== ' ' && line.charAt( charIndex ) !== '\t' && charIndex < lineLength ) {
- charIndex ++;
- }
- // Skip spaces/tabs
- while ( ( line.charAt( charIndex ) === ' ' || line.charAt( charIndex ) === '\t' ) && charIndex < lineLength ) {
- charIndex ++;
- }
- }
- var subobjectFileName = line.substring( charIndex ).trim().replace( "\\", "/" );
- if ( subobjectFileName ) {
- // Find name in path cache
- var subobjectPath = pathMap[ subobjectFileName ];
- if ( ! subobjectPath ) {
- // Add new object
- subobjectPath = parseObject( subobjectFileName );
- }
- pathMap[ subobjectFileName ] = subobjectPath ? subobjectPath : subobjectFileName;
- processedObjectContent += line.substring( 0, charIndex ) + pathMap[ subobjectFileName ] + "\n";
- }
- } else {
- processedObjectContent += line + "\n";
- }
- }
- if ( objectsPaths.indexOf( objectPath ) < 0 ) {
- objectsPaths.push( objectPath );
- objectsContents.push( processedObjectContent );
- }
- return objectPath;
- }
|