Added fast mode for mesh cooking

This commit is contained in:
Jack Andersen 2015-10-21 16:01:08 -10:00
parent 87b86b7553
commit bcee8aa897
9 changed files with 224 additions and 99 deletions

View File

@ -17,6 +17,19 @@
#include <fcntl.h>
#endif
namespace std
{
template <> struct hash<std::pair<uint32_t,uint32_t>>
{
size_t operator()(const std::pair<uint32_t,uint32_t>& 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<skins.size() ; ++i)
{
std::unordered_map<std::pair<uint32_t,uint32_t>, 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)
{

View File

@ -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<std::vector<SkinBind>> skins;
std::vector<size_t> 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<void(int)>;
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()

View File

@ -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))

View File

@ -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))

View File

@ -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, '<HECL>', '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)

View File

@ -10,6 +10,7 @@ class ToolCook final : public ToolBase
std::unique_ptr<HECL::Database::Project> 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] [<pathspec>...]\n"));
help.wrap(_S("hecl cook [-rf] [--fast] [<pathspec>...]\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;
}

View File

@ -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;

View File

@ -67,6 +67,7 @@ class IDataSpec
public:
virtual ~IDataSpec() {}
using FProgress = FProgress;
using FCookProgress = std::function<void(const SystemChar*)>;
/**
* @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)

View File

@ -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<const DataSpecEntry*, std::unique_ptr<IDataSpec>>;
static void VisitFile(const ProjectPath& path, bool force,
static void VisitFile(const ProjectPath& path, bool force, bool fast,
std::vector<SpecInst>& 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<SpecInst>& 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<SpecInst>& 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<SpecInst> 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;