diff --git a/hecl/blender/BlenderConnection.cpp b/hecl/blender/BlenderConnection.cpp index 0c5336e45..a6ef28ace 100644 --- a/hecl/blender/BlenderConnection.cpp +++ b/hecl/blender/BlenderConnection.cpp @@ -17,6 +17,19 @@ #include #endif +namespace std +{ +template <> struct hash> +{ + size_t operator()(const std::pair& val) const NOEXCEPT + { + /* this will potentially truncate the second value if 32-bit size_t, + * however, its application here is intended to operate in 16-bit indices */ + return val.first | (val.second << 16); + } +}; +} + namespace HECL { @@ -219,7 +232,7 @@ BlenderConnection::BlenderConnection(int verbosityLevel) wchar_t cmdLine[2048]; _snwprintf(cmdLine, 2048, L" --background -P \"%s\" -- %" PRIuPTR " %" PRIuPTR " %d \"%s\"", blenderShellPath.c_str(), uintptr_t(writehandle), uintptr_t(readhandle), - verbosityLevel > 1 ? 1 : 0, blenderAddonPath.c_str()); + verbosityLevel, blenderAddonPath.c_str()); STARTUPINFO sinfo = {sizeof(STARTUPINFO)}; HANDLE nulHandle = NULL; @@ -266,15 +279,15 @@ BlenderConnection::BlenderConnection(int verbosityLevel) snprintf(readfds, 32, "%d", m_writepipe[0]); char writefds[32]; snprintf(writefds, 32, "%d", m_readpipe[1]); - char dverbose[32]; - snprintf(dverbose, 32, "%d", verbosityLevel > 1 ? 1 : 0); + char vLevel[32]; + snprintf(vLevel, 32, "%d", verbosityLevel); /* Try user-specified blender first */ if (blenderBin) { execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), - "--", readfds, writefds, dverbose, blenderAddonPath.c_str(), NULL); + "--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL); if (errno != ENOENT) { snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno)); @@ -286,7 +299,7 @@ BlenderConnection::BlenderConnection(int verbosityLevel) /* Otherwise default blender */ execlp(DEFAULT_BLENDER_BIN, DEFAULT_BLENDER_BIN, "--background", "-P", blenderShellPath.c_str(), - "--", readfds, writefds, dverbose, blenderAddonPath.c_str(), NULL); + "--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL); if (errno != ENOENT) { snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno)); @@ -467,8 +480,9 @@ void BlenderConnection::PyOutStream::linkBlend(const std::string& target, objName.c_str(), objName.c_str(), target.c_str(), objName.c_str()); } -BlenderConnection::DataStream::Mesh::Mesh(BlenderConnection& conn, int skinSlotCount) -: aabbMin(conn), aabbMax(conn) +BlenderConnection::DataStream::Mesh::Mesh +(BlenderConnection& conn, OutputMode outMode, int skinSlotCount, SurfProgFunc& surfProg) +: outputMode(outMode), aabbMin(conn), aabbMax(conn) { uint32_t matSetCount; conn._readBuf(&matSetCount, 4); @@ -538,9 +552,11 @@ BlenderConnection::DataStream::Mesh::Mesh(BlenderConnection& conn, int skinSlotC surfaces.reserve(materialSets.front().size() * 16); uint8_t isSurf; conn._readBuf(&isSurf, 1); + int prog = 0; while (isSurf) { surfaces.emplace_back(conn, *this, skinSlotCount); + surfProg(++prog); conn._readBuf(&isSurf, 1); } @@ -565,6 +581,48 @@ BlenderConnection::DataStream::Mesh::Mesh(BlenderConnection& conn, int skinSlotC } } +BlenderConnection::DataStream::Mesh +BlenderConnection::DataStream::Mesh::getContiguousSkinningVersion() const +{ + Mesh newMesh = *this; + newMesh.pos.clear(); + newMesh.norm.clear(); + newMesh.contiguousSkinVertCounts.reserve(skins.size()); + for (size_t i=0 ; i, uint32_t> contigMap; + size_t vertCount = 0; + for (Surface& surf : newMesh.surfaces) + { + for (Surface::Vert& vert : surf.verts) + { + if (vert.iSkin == i) + { + auto key = std::make_pair(vert.iPos, vert.iNorm); + auto search = contigMap.find(key); + if (search != contigMap.end()) + { + vert.iPos = search->second; + vert.iNorm = search->second; + } + else + { + uint32_t newIdx = newMesh.pos.size(); + contigMap[key] = newIdx; + newMesh.pos.push_back(pos.at(vert.iPos)); + newMesh.norm.push_back(norm.at(vert.iNorm)); + vert.iPos = newIdx; + vert.iNorm = newIdx; + ++vertCount; + } + } + } + } + newMesh.contiguousSkinVertCounts.push_back(vertCount); + } + return newMesh; +} + BlenderConnection::DataStream::Mesh::Material::Material (BlenderConnection& conn) { diff --git a/hecl/blender/BlenderConnection.hpp b/hecl/blender/BlenderConnection.hpp index 79e1aa486..51efad996 100644 --- a/hecl/blender/BlenderConnection.hpp +++ b/hecl/blender/BlenderConnection.hpp @@ -305,6 +305,12 @@ public: operator const uint32_t&() const {return val;} }; + enum OutputMode + { + OutputTriangles, + OutputTriStrips, + } outputMode; + /* Cumulative AABB */ Vector3f aabbMin; Vector3f aabbMax; @@ -338,6 +344,7 @@ public: SkinBind(BlenderConnection& conn) {conn._readBuf(&boneIdx, 8);} }; std::vector> skins; + std::vector contiguousSkinVertCounts; /* Islands of the same material/skinBank are represented here */ struct Surface @@ -380,14 +387,27 @@ public: uint32_t addSurface(const Surface& surf, int skinSlotCount); } skinBanks; - Mesh(BlenderConnection& conn, int skinSlotCount); + using SurfProgFunc = std::function; + Mesh(BlenderConnection& conn, OutputMode outMode, int skinSlotCount, SurfProgFunc& surfProg); + + Mesh getContiguousSkinningVersion() const; }; + + static const char* MeshOutputModeString(Mesh::OutputMode mode) + { + static const char* STRS[] = {"TRIANGLES", "TRISTRIPS"}; + return STRS[mode]; + } + + /* Compile mesh by context */ - Mesh compileMesh(int skinSlotCount=10) + Mesh compileMesh(Mesh::OutputMode outMode, int skinSlotCount=10, + Mesh::SurfProgFunc surfProg=[](int){}) { char req[128]; - snprintf(req, 128, "MESHCOMPILE %d", skinSlotCount); + snprintf(req, 128, "MESHCOMPILE %s %d", + MeshOutputModeString(outMode), skinSlotCount); m_parent->_writeLine(req); char readBuf[256]; @@ -395,14 +415,16 @@ public: if (strcmp(readBuf, "OK")) BlenderLog.report(LogVisor::FatalError, "unable to cook mesh: %s", readBuf); - return Mesh(*m_parent, skinSlotCount); + return Mesh(*m_parent, outMode, skinSlotCount, surfProg); } /* Compile mesh by name */ - Mesh compileMesh(const std::string& name, int skinSlotCount=10) + Mesh compileMesh(const std::string& name, Mesh::OutputMode outMode, int skinSlotCount=10, + Mesh::SurfProgFunc surfProg=[](int){}) { char req[128]; - snprintf(req, 128, "MESHCOMPILENAME %s %d", name.c_str(), skinSlotCount); + snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(), + MeshOutputModeString(outMode), skinSlotCount); m_parent->_writeLine(req); char readBuf[256]; @@ -410,14 +432,17 @@ public: if (strcmp(readBuf, "OK")) BlenderLog.report(LogVisor::FatalError, "unable to cook mesh '%s': %s", name.c_str(), readBuf); - return Mesh(*m_parent, skinSlotCount); + return Mesh(*m_parent, outMode, skinSlotCount, surfProg); } /* Compile all meshes into one */ - Mesh compileAllMeshes(int skinSlotCount=10, float maxOctantLength=5.0) + Mesh compileAllMeshes(Mesh::OutputMode outMode, int skinSlotCount=10, float maxOctantLength=5.0, + Mesh::SurfProgFunc surfProg=[](int){}) { char req[128]; - snprintf(req, 128, "MESHCOMPILEALL %d %f", skinSlotCount, maxOctantLength); + snprintf(req, 128, "MESHCOMPILEALL %s %d %f", + MeshOutputModeString(outMode), + skinSlotCount, maxOctantLength); m_parent->_writeLine(req); char readBuf[256]; @@ -425,7 +450,7 @@ public: if (strcmp(readBuf, "OK")) BlenderLog.report(LogVisor::FatalError, "unable to cook all meshes: %s", readBuf); - return Mesh(*m_parent, skinSlotCount); + return Mesh(*m_parent, outMode, skinSlotCount, surfProg); } }; DataStream beginData() diff --git a/hecl/blender/hecl/hmdl/HMDLMesh.py b/hecl/blender/hecl/hmdl/HMDLMesh.py index a0812c9ec..eecc9d71f 100644 --- a/hecl/blender/hecl/hmdl/HMDLMesh.py +++ b/hecl/blender/hecl/hmdl/HMDLMesh.py @@ -226,7 +226,7 @@ def strip_next_loop(prev_loop, out_count): loop = radial_loop.link_loop_next return loop.link_loop_next, loop -def write_out_surface(writebuf, vert_pool, island_faces, mat_idx): +def write_out_surface(writebuf, output_mode, vert_pool, island_faces, mat_idx): # Centroid of surface centroid = Vector() @@ -258,57 +258,63 @@ def write_out_surface(writebuf, vert_pool, island_faces, mat_idx): avg_norm.normalize() writebuf(struct.pack('fff', avg_norm[0], avg_norm[1], avg_norm[2])) - # Count estimate + # Count estimate (as raw triangles) writebuf(struct.pack('I', len(island_faces) * 3)) # Verts themselves - prev_loop_emit = None - out_count = 0 - while len(island_faces): - sel_lists_local = [] - restore_out_count = out_count - for start_face in island_faces: - for l in start_face.loops: - out_count = restore_out_count - island_local = list(island_faces) - if out_count & 1: - prev_loop = l.link_loop_prev - loop = prev_loop.link_loop_prev - sel_list = [l, prev_loop, loop] - prev_loop = loop - else: - prev_loop = l.link_loop_next - loop = prev_loop.link_loop_next - sel_list = [l, prev_loop, loop] - out_count += 3 - island_local.remove(start_face) - while True: - if not prev_loop.edge.is_contiguous or prev_loop.edge.tag: - break - loop, prev_loop = strip_next_loop(prev_loop, out_count) - face = loop.face - if face not in island_local: - break - sel_list.append(loop) - island_local.remove(face) - out_count += 1 - sel_lists_local.append((sel_list, island_local, out_count)) - max_count = 0 - max_sl = None - max_island_faces = None - for sl in sel_lists_local: - if len(sl[0]) > max_count: - max_count = len(sl[0]) - max_sl = sl[0] - max_island_faces = sl[1] - out_count = sl[2] - island_faces = max_island_faces - if prev_loop_emit: - vert_pool.loop_out(writebuf, prev_loop_emit) - vert_pool.loop_out(writebuf, max_sl[0]) - for loop in max_sl: - vert_pool.loop_out(writebuf, loop) - prev_loop_emit = loop + if output_mode == 'TRIANGLES': + for f in island_faces: + for l in f.loops: + vert_pool.loop_out(writebuf, l) + + elif output_mode == 'TRISTRIPS': + prev_loop_emit = None + out_count = 0 + while len(island_faces): + sel_lists_local = [] + restore_out_count = out_count + for start_face in island_faces: + for l in start_face.loops: + out_count = restore_out_count + island_local = list(island_faces) + if out_count & 1: + prev_loop = l.link_loop_prev + loop = prev_loop.link_loop_prev + sel_list = [l, prev_loop, loop] + prev_loop = loop + else: + prev_loop = l.link_loop_next + loop = prev_loop.link_loop_next + sel_list = [l, prev_loop, loop] + out_count += 3 + island_local.remove(start_face) + while True: + if not prev_loop.edge.is_contiguous or prev_loop.edge.tag: + break + loop, prev_loop = strip_next_loop(prev_loop, out_count) + face = loop.face + if face not in island_local: + break + sel_list.append(loop) + island_local.remove(face) + out_count += 1 + sel_lists_local.append((sel_list, island_local, out_count)) + max_count = 0 + max_sl = None + max_island_faces = None + for sl in sel_lists_local: + if len(sl[0]) > max_count: + max_count = len(sl[0]) + max_sl = sl[0] + max_island_faces = sl[1] + out_count = sl[2] + island_faces = max_island_faces + if prev_loop_emit: + vert_pool.loop_out(writebuf, prev_loop_emit) + vert_pool.loop_out(writebuf, max_sl[0]) + for loop in max_sl: + vert_pool.loop_out(writebuf, loop) + prev_loop_emit = loop writebuf(struct.pack('B', 0)) diff --git a/hecl/blender/hecl/hmdl/__init__.py b/hecl/blender/hecl/hmdl/__init__.py index a5f0b7eaa..04aa48646 100644 --- a/hecl/blender/hecl/hmdl/__init__.py +++ b/hecl/blender/hecl/hmdl/__init__.py @@ -91,7 +91,7 @@ def write_out_material(writebuf, mat, mesh_obj): # Takes a Blender 'Mesh' object (not the datablock) # and performs a one-shot conversion process to HMDL; packaging # into the HECL data-pipeline and returning a hash once complete -def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): +def cook(writebuf, mesh_obj, output_mode, max_skin_banks, max_octant_length=None): if mesh_obj.type != 'MESH': raise RuntimeError("%s is not a mesh" % mesh_obj.name) @@ -207,7 +207,7 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): mat_faces_rem.remove(f) writebuf(struct.pack('B', 1)) - HMDLMesh.write_out_surface(writebuf, vert_pool, the_list, mat_idx) + HMDLMesh.write_out_surface(writebuf, output_mode, vert_pool, the_list, mat_idx) # Generate island meshes (if transparent) @@ -241,7 +241,7 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): faces = next_faces writebuf(struct.pack('B', 1)) - HMDLMesh.write_out_surface(writebuf, vert_pool, the_list, mat_idx) + HMDLMesh.write_out_surface(writebuf, output_mode, vert_pool, the_list, mat_idx) # No more surfaces writebuf(struct.pack('B', 0)) diff --git a/hecl/blender/hecl_blendershell.py b/hecl/blender/hecl_blendershell.py index 2384e8006..e94453034 100644 --- a/hecl/blender/hecl_blendershell.py +++ b/hecl/blender/hecl_blendershell.py @@ -9,7 +9,7 @@ if '--' not in sys.argv: args = sys.argv[sys.argv.index('--')+1:] readfd = int(args[0]) writefd = int(args[1]) -double_verbose = int(args[2]) +verbosity_level = int(args[2]) if sys.platform == "win32": import msvcrt readfd = msvcrt.open_osfhandle(readfd, os.O_RDONLY | os.O_BINARY) @@ -89,7 +89,7 @@ def read_cmdargs(): # Complete sequences of statements compiled/executed here def exec_compbuf(compbuf, globals): - if double_verbose: + if verbosity_level >= 3: print('EXEC', compbuf) co = compile(compbuf, '', 'exec') exec(co, globals) @@ -144,7 +144,7 @@ def dataout_loop(): writepipeline(meshobj.name.encode()) elif cmdargs[0] == 'MESHCOMPILE': - maxSkinBanks = int(cmdargs[1]) + maxSkinBanks = int(cmdargs[2]) meshName = bpy.context.scene.hecl_mesh_obj if meshName not in bpy.data.objects: @@ -152,22 +152,22 @@ def dataout_loop(): continue writepipeline(b'OK') - hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], maxSkinBanks) + hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[1], maxSkinBanks) elif cmdargs[0] == 'MESHCOMPILENAME': meshName = cmdargs[1] - maxSkinBanks = int(cmdargs[2]) + maxSkinBanks = int(cmdargs[3]) if meshName not in bpy.data.objects: writepipeline(('mesh %s not found' % meshName).encode()) continue writepipeline(b'OK') - hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], maxSkinBanks) + hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[2], maxSkinBanks) elif cmdargs[0] == 'MESHCOMPILEALL': - maxSkinBanks = int(cmdargs[1]) - maxOctantLength = float(cmdargs[2]) + maxSkinBanks = int(cmdargs[2]) + maxOctantLength = float(cmdargs[3]) bpy.ops.object.select_all(action='DESELECT') join_mesh = bpy.data.meshes.new('JOIN_MESH') @@ -178,7 +178,7 @@ def dataout_loop(): bpy.ops.object.join() writepipeline(b'OK') - hecl.hmdl.cook(writepipebuf, join_obj, maxSkinBanks, maxOctantLength) + hecl.hmdl.cook(writepipebuf, join_obj, cmdargs[1], maxSkinBanks, maxOctantLength) bpy.context.scene.objects.unlink(join_obj) bpy.data.objects.remove(join_obj) diff --git a/hecl/driver/ToolCook.hpp b/hecl/driver/ToolCook.hpp index 7fa20fe1b..5aa0ca70f 100644 --- a/hecl/driver/ToolCook.hpp +++ b/hecl/driver/ToolCook.hpp @@ -10,6 +10,7 @@ class ToolCook final : public ToolBase std::unique_ptr m_fallbackProj; HECL::Database::Project* m_useProj; bool m_recursive = false; + bool m_fast = false; public: ToolCook(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) @@ -28,6 +29,14 @@ public: { if (arg.empty()) continue; + else if (!arg.compare("--fast")) + { + m_fast = true; + continue; + } + else if (arg.size() >= 2 && arg[0] == _S('-') && arg[1] == _S('-')) + continue; + HECL::SystemString subPath; HECL::ProjectRootPath root = HECL::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath); if (root) @@ -70,7 +79,7 @@ public: help.secHead(_S("SYNOPSIS")); help.beginWrap(); - help.wrap(_S("hecl cook [-rf] [...]\n")); + help.wrap(_S("hecl cook [-rf] [--fast] [...]\n")); help.endWrap(); help.secHead(_S("DESCRIPTION")); @@ -117,6 +126,10 @@ public: help.beginWrap(); help.wrap(_S("Forces cooking of all matched files, ignoring timestamp differences.\n")); help.endWrap(); + help.optionHead(_S("--fast"), _S("fast cook")); + help.beginWrap(); + help.wrap(_S("Performs draft-optimization cooking for supported data types.\n")); + help.endWrap(); } HECL::SystemString toolName() const {return _S("cook");} @@ -131,7 +144,7 @@ public: const HECL::SystemChar* submessage, int lidx, float factor) {ToolPrintProgress(message, submessage, lidx, factor, lineIdx);}, - m_recursive, m_info.force); + m_recursive, m_info.force, m_fast); } return 0; } diff --git a/hecl/driver/main.cpp b/hecl/driver/main.cpp index 571c01f1f..bacbc512c 100644 --- a/hecl/driver/main.cpp +++ b/hecl/driver/main.cpp @@ -189,7 +189,7 @@ int main(int argc, const char** argv) for (auto it = args.cbegin() ; it != args.cend() ;) { const HECL::SystemString& arg = *it; - if (arg.empty() || arg[0] != _S('-')) + if (arg.size() < 2 || arg[0] != _S('-') || arg[1] == _S('-')) { ++it; continue; diff --git a/hecl/include/HECL/Database.hpp b/hecl/include/HECL/Database.hpp index e228bb619..9fca3b001 100644 --- a/hecl/include/HECL/Database.hpp +++ b/hecl/include/HECL/Database.hpp @@ -67,6 +67,7 @@ class IDataSpec public: virtual ~IDataSpec() {} using FProgress = FProgress; + using FCookProgress = std::function; /** * @brief Extract Pass Info @@ -101,8 +102,9 @@ public: virtual bool canCook(const ProjectPath& path) {(void)path;LogModule.report(LogVisor::Error, "not implemented");return false;} - virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath) - {(void)path;(void)cookedPath;} + virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath, + bool fast, FCookProgress progress) + {(void)path;(void)cookedPath;(void)fast;(void)progress;} /** * @brief Package Pass Info @@ -406,13 +408,15 @@ public: * @param path directory of intermediates to cook * @param feedbackCb a callback to run reporting cook-progress * @param recursive traverse subdirectories to cook as well + * @param fast enables faster (draft) extraction for supported data types * @return true on success * * Object cooking is generally an expensive process for large projects. * This method blocks execution during the procedure, with periodic * feedback delivered via feedbackCb. */ - bool cookPath(const ProjectPath& path, FProgress feedbackCb, bool recursive=false, bool force=false); + bool cookPath(const ProjectPath& path, FProgress feedbackCb, + bool recursive=false, bool force=false, bool fast=false); /** * @brief Interrupts a cook in progress (call from SIGINT handler) diff --git a/hecl/lib/Database/Project.cpp b/hecl/lib/Database/Project.cpp index 4a0537675..d3805d9cf 100644 --- a/hecl/lib/Database/Project.cpp +++ b/hecl/lib/Database/Project.cpp @@ -357,12 +357,22 @@ public: submsg += _S(')'); m_progFunc(m_dir, submsg.c_str(), lidx, m_prog); } + void reportFile(const DataSpecEntry* specEnt, const SystemChar* extra) + { + SystemString submsg(m_file); + submsg += _S(" ("); + submsg += specEnt->m_name; + submsg += _S(", "); + submsg += extra; + submsg += _S(')'); + m_progFunc(m_dir, submsg.c_str(), lidx, m_prog); + } void reportDirComplete() {m_progFunc(m_dir, nullptr, lidx, 1.0);} }; using SpecInst = std::pair>; -static void VisitFile(const ProjectPath& path, bool force, +static void VisitFile(const ProjectPath& path, bool force, bool fast, std::vector& specInsts, CookProgress& progress) { @@ -371,17 +381,24 @@ static void VisitFile(const ProjectPath& path, bool force, if (spec.second->canCook(path)) { ProjectPath cooked = path.getCookedPath(*spec.first); + if (fast) + cooked = cooked.getWithExtension(".fast"); if (force || cooked.getPathType() == ProjectPath::PT_NONE || path.getModtime() > cooked.getModtime()) { progress.reportFile(spec.first); - spec.second->doCook(path, cooked); + spec.second->doCook(path, cooked, fast, + [&](const SystemChar* extra) + { + progress.reportFile(spec.first, extra); + }); } } } } -static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, +static void VisitDirectory(const ProjectPath& dir, + bool recursive, bool force, bool fast, std::vector& specInsts, CookProgress& progress) { @@ -421,7 +438,7 @@ static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, case ProjectPath::PT_FILE: { progress.changeFile(child.first.c_str(), progNum++/progDenom); - VisitFile(child.second, force, specInsts, progress); + VisitFile(child.second, force, fast, specInsts, progress); break; } case ProjectPath::PT_LINK: @@ -430,7 +447,7 @@ static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, if (target.getPathType() == ProjectPath::PT_FILE) { progress.changeFile(target.getLastComponent(), progNum++/progDenom); - VisitFile(target, force, specInsts, progress); + VisitFile(target, force, fast, specInsts, progress); } break; } @@ -448,7 +465,7 @@ static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, { case ProjectPath::PT_DIRECTORY: { - VisitDirectory(child.second, recursive, force, specInsts, progress); + VisitDirectory(child.second, recursive, force, fast, specInsts, progress); break; } default: break; @@ -457,7 +474,8 @@ static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, } } -static void VisitGlob(const ProjectPath& path, bool recursive, bool force, +static void VisitGlob(const ProjectPath& path, + bool recursive, bool force, bool fast, std::vector& specInsts, CookProgress& progress) { @@ -497,7 +515,7 @@ static void VisitGlob(const ProjectPath& path, bool recursive, bool force, case ProjectPath::PT_FILE: { progress.changeFile(child.getLastComponent(), progNum++/progDenom); - VisitFile(child, force, specInsts, progress); + VisitFile(child, force, fast, specInsts, progress); break; } case ProjectPath::PT_LINK: @@ -506,7 +524,7 @@ static void VisitGlob(const ProjectPath& path, bool recursive, bool force, if (target.getPathType() == ProjectPath::PT_FILE) { progress.changeFile(target.getLastComponent(), progNum++/progDenom); - VisitFile(target, force, specInsts, progress); + VisitFile(target, force, fast, specInsts, progress); } break; } @@ -524,7 +542,7 @@ static void VisitGlob(const ProjectPath& path, bool recursive, bool force, { case ProjectPath::PT_DIRECTORY: { - VisitDirectory(child, recursive, force, specInsts, progress); + VisitDirectory(child, recursive, force, fast, specInsts, progress); break; } default: break; @@ -533,7 +551,8 @@ static void VisitGlob(const ProjectPath& path, bool recursive, bool force, } } -bool Project::cookPath(const ProjectPath& path, FProgress progress, bool recursive, bool force) +bool Project::cookPath(const ProjectPath& path, FProgress progress, + bool recursive, bool force, bool fast) { /* Construct DataSpec instances for cooking */ std::vector specInsts; @@ -550,7 +569,7 @@ bool Project::cookPath(const ProjectPath& path, FProgress progress, bool recursi case ProjectPath::PT_FILE: { cookProg.changeFile(path.getLastComponent(), 0.0); - VisitFile(path, force, specInsts, cookProg); + VisitFile(path, force, fast, specInsts, cookProg); break; } case ProjectPath::PT_LINK: @@ -559,18 +578,18 @@ bool Project::cookPath(const ProjectPath& path, FProgress progress, bool recursi if (target.getPathType() == ProjectPath::PT_FILE) { cookProg.changeFile(target.getLastComponent(), 0.0); - VisitFile(target, force, specInsts, cookProg); + VisitFile(target, force, fast, specInsts, cookProg); } break; } case ProjectPath::PT_DIRECTORY: { - VisitDirectory(path, recursive, force, specInsts, cookProg); + VisitDirectory(path, recursive, force, fast, specInsts, cookProg); break; } case ProjectPath::PT_GLOB: { - VisitGlob(path, recursive, force, specInsts, cookProg); + VisitGlob(path, recursive, force, fast, specInsts, cookProg); break; } default: break;