void TextureCooker::process( Vector<VirtFS::VirtDesc>& files, TerminalCursor& cursor) { using FileElement = Pair<CString, ImageProcessor>; using FileContainer = Vector<FileElement>; FileContainer targets; for(auto& desc : files) { auto path = Path(desc.filename); for(auto ext : imageExtensions) /* Check if we recognize the extension */ if(libc::str::cmp<libc::str::comp_nocase>( path.extension().c_str(), ext.c_str())) { if(ext == "") continue; #if defined(HAVE_LIBTIFF) else if(ext == "TIFF" || ext == "TIF") targets.push_back({desc.filename, ImageProc_tiff}); #endif else targets.push_back({desc.filename, ImageProc_stb}); continue; } } /* Set default texture sizes, for the cases where nothing is specified. * There is also a program-defined default to fallback to. */ if(Env::ExistsVar(TEX_MAX_SIZE)) max_texture_size = cast_string<i32>(Env::GetVar(TEX_MAX_SIZE)); if(Env::ExistsVar(TEX_MIN_SIZE)) min_texture_size = cast_string<i32>(Env::GetVar(TEX_MIN_SIZE)); cursor.progress( TEXCOMPRESS_API "Compressable textures found: {0}", targets.size()); Map<ThreadId::Hash, Vector<VirtFS::VirtDesc>> threadFiles; /* Each thread works on a texture and its mipmaps. */ threads::Parallel::ForEach( targets, static_cast<Function<void(FileElement&)>>([&](FileElement& e) { CompressTextureSet(threadFiles[ThreadId().hash()], e, this, cursor); }), this->numWorkers); for(auto& thread : threadFiles) { files.reserve(files.size() + thread.second.size()); for(auto& file : thread.second) files.push_back(std::move(file)); } #if defined(HAVE_LIBTIFF) auto removePred = [&](VirtFS::VirtDesc const& desc) { for(auto const& e : targets) if(e.first == desc.filename) return true; return false; }; auto removeIt = std::remove_if(files.begin(), files.end(), removePred); for(auto it = removeIt; it != files.end(); it++) it->data = Bytes(); files.erase(removeIt, files.end()); #endif }