255 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | "use strict"; | ||
|  | Object.defineProperty(exports, "__esModule", { value: true }); | ||
|  | exports.AssetConverter = void 0; | ||
|  | const ProjectFile_1 = require("./ProjectFile"); | ||
|  | const fs = require("fs-extra"); | ||
|  | const path = require("path"); | ||
|  | const log = require("./log"); | ||
|  | const chokidar = require("chokidar"); | ||
|  | const crypto = require("crypto"); | ||
|  | const Throttle = require("promise-parallel-throttle"); | ||
|  | class AssetConverter { | ||
|  |     constructor(exporter, options, assetMatchers) { | ||
|  |         this.exporter = exporter; | ||
|  |         this.options = options; | ||
|  |         this.platform = options.target; | ||
|  |         this.assetMatchers = assetMatchers; | ||
|  |     } | ||
|  |     close() { | ||
|  |         if (this.watcher) | ||
|  |             this.watcher.close(); | ||
|  |     } | ||
|  |     static replacePattern(pattern, name, fileinfo, options, from) { | ||
|  |         let basePath = options.nameBaseDir ? path.join(from, options.nameBaseDir) : from; | ||
|  |         let dirValue = path.relative(basePath, fileinfo.dir); | ||
|  |         if (basePath.length > 0 && basePath[basePath.length - 1] === path.sep | ||
|  |             && dirValue.length > 0 && dirValue[dirValue.length - 1] !== path.sep) { | ||
|  |             dirValue += path.sep; | ||
|  |         } | ||
|  |         if (options.namePathSeparator) { | ||
|  |             dirValue = dirValue.split(path.sep).join(options.namePathSeparator); | ||
|  |         } | ||
|  |         const dirRegex = dirValue === '' | ||
|  |             ? /{dir}\//g | ||
|  |             : /{dir}/g; | ||
|  |         return pattern.replace(/{name}/g, name).replace(/{ext}/g, fileinfo.ext).replace(dirRegex, dirValue); | ||
|  |     } | ||
|  |     static createExportInfo(fileinfo, keepextension, options, from) { | ||
|  |         let nameValue = fileinfo.name; | ||
|  |         let destination = fileinfo.name; | ||
|  |         if (options.md5sum) { | ||
|  |             let data = fs.readFileSync(path.join(fileinfo.dir, fileinfo.base)); | ||
|  |             let md5sum = crypto.createHash('md5').update(data).digest('hex'); // TODO yield generateMd5Sum(file);
 | ||
|  |             destination += '_' + md5sum; | ||
|  |         } | ||
|  |         if ((keepextension || options.noprocessing) && (!options.destination || options.destination.indexOf('{ext}') < 0)) { | ||
|  |             destination += fileinfo.ext; | ||
|  |         } | ||
|  |         if (options.destination) { | ||
|  |             destination = AssetConverter.replacePattern(options.destination, destination, fileinfo, options, from); | ||
|  |         } | ||
|  |         if (options.destinationCallback) { | ||
|  |             destination = options.destinationCallback(destination); | ||
|  |         } | ||
|  |         if (keepextension && (!options.name || options.name.indexOf('{ext}') < 0)) { | ||
|  |             nameValue += fileinfo.ext; | ||
|  |         } | ||
|  |         if (options.name) { | ||
|  |             nameValue = AssetConverter.replacePattern(options.name, nameValue, fileinfo, options, from); | ||
|  |         } | ||
|  |         return { name: nameValue, destination: destination }; | ||
|  |     } | ||
|  |     watch(watch, match, temp, options) { | ||
|  |         return new Promise((resolve, reject) => { | ||
|  |             let ready = false; | ||
|  |             let files = []; | ||
|  |             this.watcher = chokidar.watch(match, { ignored: /[\/\\]\.(svn|git|DS_Store)/, persistent: watch, followSymlinks: false }); | ||
|  |             const onFileChange = async (file) => { | ||
|  |                 const fileinfo = path.parse(file); | ||
|  |                 let outPath = fileinfo.name; | ||
|  |                 // with subfolders
 | ||
|  |                 if (options.destination) { | ||
|  |                     const from = path.resolve(options.baseDir, '..'); | ||
|  |                     outPath = AssetConverter.replacePattern(options.destination, fileinfo.name, fileinfo, options, from); | ||
|  |                 } | ||
|  |                 log.info('Reexporting ' + outPath + fileinfo.ext); | ||
|  |                 switch (fileinfo.ext) { | ||
|  |                     case '.png': | ||
|  |                     case '.jpg': | ||
|  |                     case '.jpeg': | ||
|  |                     case '.hdr': | ||
|  |                         { } | ||
|  |                         await this.exporter.copyImage(this.platform, file, outPath, {}, {}); | ||
|  |                         break; | ||
|  |                     case '.ogg': | ||
|  |                     case '.mp3': | ||
|  |                     case '.flac': | ||
|  |                     case '.wav': { | ||
|  |                         await this.exporter.copySound(this.platform, file, outPath, {}); | ||
|  |                         break; | ||
|  |                     } | ||
|  |                     case '.mp4': | ||
|  |                     case '.webm': | ||
|  |                     case '.mov': | ||
|  |                     case '.wmv': | ||
|  |                     case '.avi': { | ||
|  |                         await this.exporter.copyVideo(this.platform, file, outPath, {}); | ||
|  |                         break; | ||
|  |                     } | ||
|  |                     case '.ttf': | ||
|  |                         await this.exporter.copyFont(this.platform, file, outPath, {}); | ||
|  |                         break; | ||
|  |                     default: | ||
|  |                         await this.exporter.copyBlob(this.platform, file, outPath + fileinfo.ext, {}); | ||
|  |                 } | ||
|  |                 for (let callback of ProjectFile_1.Callbacks.postAssetReexporting) { | ||
|  |                     callback(outPath + fileinfo.ext); | ||
|  |                 } | ||
|  |             }; | ||
|  |             this.watcher.on('add', (file) => { | ||
|  |                 if (ready) { | ||
|  |                     onFileChange(file); | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     files.push(file); | ||
|  |                 } | ||
|  |             }); | ||
|  |             if (watch) { | ||
|  |                 this.watcher.on('change', (file) => { | ||
|  |                     if (ready) { | ||
|  |                         onFileChange(file); | ||
|  |                     } | ||
|  |                 }); | ||
|  |             } | ||
|  |             this.watcher.on('ready', async () => { | ||
|  |                 ready = true; | ||
|  |                 let parsedFiles = []; | ||
|  |                 let cache = {}; | ||
|  |                 let cachePath = path.join(temp, 'cache.json'); | ||
|  |                 if (fs.existsSync(cachePath)) { | ||
|  |                     cache = JSON.parse(fs.readFileSync(cachePath, 'utf8')); | ||
|  |                 } | ||
|  |                 const self = this; | ||
|  |                 async function convertAsset(file, index) { | ||
|  |                     let fileinfo = path.parse(file); | ||
|  |                     log.info('Exporting asset ' + (index + 1) + ' of ' + files.length + ' (' + fileinfo.base + ').'); | ||
|  |                     const ext = fileinfo.ext.toLowerCase(); | ||
|  |                     switch (ext) { | ||
|  |                         case '.png': | ||
|  |                         case '.jpg': | ||
|  |                         case '.jpeg': | ||
|  |                         case '.hdr': { | ||
|  |                             let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from); | ||
|  |                             let images; | ||
|  |                             if (options.noprocessing) { | ||
|  |                                 images = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             else { | ||
|  |                                 images = await self.exporter.copyImage(self.platform, file, exportInfo.destination, options, cache); | ||
|  |                             } | ||
|  |                             if (!options.notinlist) { | ||
|  |                                 parsedFiles.push({ name: exportInfo.name, from: file, type: 'image', files: images.files, file_sizes: images.sizes, original_width: options.original_width, original_height: options.original_height, readable: options.readable }); | ||
|  |                             } | ||
|  |                             break; | ||
|  |                         } | ||
|  |                         case '.ogg': | ||
|  |                         case '.mp3': | ||
|  |                         case '.flac': | ||
|  |                         case '.wav': { | ||
|  |                             let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from); | ||
|  |                             let sounds; | ||
|  |                             if (options.noprocessing) { | ||
|  |                                 sounds = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             else { | ||
|  |                                 sounds = await self.exporter.copySound(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             if (sounds.files.length === 0) { | ||
|  |                                 throw 'Audio file ' + file + ' could not be exported, you have to specify a path to ffmpeg.'; | ||
|  |                             } | ||
|  |                             if (!options.notinlist) { | ||
|  |                                 parsedFiles.push({ name: exportInfo.name, from: file, type: 'sound', files: sounds.files, file_sizes: sounds.sizes, original_width: undefined, original_height: undefined, readable: undefined }); | ||
|  |                             } | ||
|  |                             break; | ||
|  |                         } | ||
|  |                         case '.ttf': { | ||
|  |                             let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from); | ||
|  |                             let fonts; | ||
|  |                             if (options.noprocessing) { | ||
|  |                                 fonts = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             else { | ||
|  |                                 fonts = await self.exporter.copyFont(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             if (!options.notinlist) { | ||
|  |                                 parsedFiles.push({ name: exportInfo.name, from: file, type: 'font', files: fonts.files, file_sizes: fonts.sizes, original_width: undefined, original_height: undefined, readable: undefined }); | ||
|  |                             } | ||
|  |                             break; | ||
|  |                         } | ||
|  |                         case '.mp4': | ||
|  |                         case '.webm': | ||
|  |                         case '.mov': | ||
|  |                         case '.wmv': | ||
|  |                         case '.avi': { | ||
|  |                             let exportInfo = AssetConverter.createExportInfo(fileinfo, false, options, self.exporter.options.from); | ||
|  |                             let videos; | ||
|  |                             if (options.noprocessing) { | ||
|  |                                 videos = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             else { | ||
|  |                                 videos = await self.exporter.copyVideo(self.platform, file, exportInfo.destination, options); | ||
|  |                             } | ||
|  |                             if (videos.files.length === 0) { | ||
|  |                                 log.error('Video file ' + file + ' could not be exported, you have to specify a path to ffmpeg.'); | ||
|  |                             } | ||
|  |                             if (!options.notinlist) { | ||
|  |                                 parsedFiles.push({ name: exportInfo.name, from: file, type: 'video', files: videos.files, file_sizes: videos.sizes, original_width: undefined, original_height: undefined, readable: undefined }); | ||
|  |                             } | ||
|  |                             break; | ||
|  |                         } | ||
|  |                         default: { | ||
|  |                             let exportInfo = AssetConverter.createExportInfo(fileinfo, true, options, self.exporter.options.from); | ||
|  |                             let blobs = await self.exporter.copyBlob(self.platform, file, exportInfo.destination, options); | ||
|  |                             if (!options.notinlist) { | ||
|  |                                 parsedFiles.push({ name: exportInfo.name, from: file, type: 'blob', files: blobs.files, file_sizes: blobs.sizes, original_width: undefined, original_height: undefined, readable: undefined }); | ||
|  |                             } | ||
|  |                             break; | ||
|  |                         } | ||
|  |                     } | ||
|  |                 } | ||
|  |                 if (this.options.parallelAssetConversion !== 0) { | ||
|  |                     let todo = files.map((file, index) => { | ||
|  |                         return async () => { | ||
|  |                             await convertAsset(file, index); | ||
|  |                         }; | ||
|  |                     }); | ||
|  |                     let processes = this.options.parallelAssetConversion === -1 | ||
|  |                         ? require('os').cpus().length - 1 | ||
|  |                         : this.options.parallelAssetConversion; | ||
|  |                     await Throttle.all(todo, { | ||
|  |                         maxInProgress: processes, | ||
|  |                     }); | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     let index = 0; | ||
|  |                     for (let file of files) { | ||
|  |                         await convertAsset(file, index); | ||
|  |                         index += 1; | ||
|  |                     } | ||
|  |                 } | ||
|  |                 fs.ensureDirSync(temp); | ||
|  |                 fs.writeFileSync(cachePath, JSON.stringify(cache), { encoding: 'utf8' }); | ||
|  |                 resolve(parsedFiles); | ||
|  |             }); | ||
|  |         }); | ||
|  |     } | ||
|  |     async run(watch, temp) { | ||
|  |         let files = []; | ||
|  |         for (let matcher of this.assetMatchers) { | ||
|  |             files = files.concat(await this.watch(watch, matcher.match, temp, matcher.options)); | ||
|  |         } | ||
|  |         return files; | ||
|  |     } | ||
|  | } | ||
|  | exports.AssetConverter = AssetConverter; | ||
|  | //# sourceMappingURL=AssetConverter.js.map
 |