mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-08 17:04:55 +00:00
Implement hecl package
This commit is contained in:
@@ -1791,6 +1791,39 @@ std::vector<std::string> BlenderConnection::DataStream::getActionNames()
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> BlenderConnection::DataStream::getSubtypeOverlayNames(const std::string& name)
|
||||
{
|
||||
if (m_parent->m_loadedType != BlendType::Actor)
|
||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||
|
||||
char req[128];
|
||||
snprintf(req, 128, "GETSUBTYPEOVERLAYNAMES %s", name.c_str());
|
||||
m_parent->_writeStr(req);
|
||||
|
||||
char readBuf[256];
|
||||
m_parent->_readStr(readBuf, 256);
|
||||
if (strcmp(readBuf, "OK"))
|
||||
BlenderLog.report(logvisor::Fatal, "unable to get subtype overlays of actor: %s", readBuf);
|
||||
|
||||
std::vector<std::string> ret;
|
||||
|
||||
uint32_t subCount;
|
||||
m_parent->_readBuf(&subCount, 4);
|
||||
ret.reserve(subCount);
|
||||
for (uint32_t i=0 ; i<subCount ; ++i)
|
||||
{
|
||||
ret.emplace_back();
|
||||
std::string& name = ret.back();
|
||||
uint32_t bufSz;
|
||||
m_parent->_readBuf(&bufSz, 4);
|
||||
name.assign(bufSz, ' ');
|
||||
m_parent->_readBuf(&name[0], bufSz);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, BlenderConnection::DataStream::Matrix3f>
|
||||
BlenderConnection::DataStream::getBoneMatrices(const std::string& name)
|
||||
{
|
||||
|
||||
@@ -47,13 +47,6 @@ void ClientProcess::BufferTransaction::run(BlenderToken& btok)
|
||||
void ClientProcess::CookTransaction::run(BlenderToken& btok)
|
||||
{
|
||||
m_dataSpec->setThreadProject();
|
||||
if (m_path.getAuxInfo().empty())
|
||||
LogModule.report(logvisor::Info, _S("Cooking %s"),
|
||||
m_path.getRelativePath().c_str());
|
||||
else
|
||||
LogModule.report(logvisor::Info, _S("Cooking %s|%s"),
|
||||
m_path.getRelativePath().c_str(),
|
||||
m_path.getAuxInfo().c_str());
|
||||
m_returnResult = m_parent.syncCook(m_path, m_dataSpec, btok);
|
||||
m_complete = true;
|
||||
}
|
||||
@@ -105,8 +98,8 @@ void ClientProcess::Worker::proc()
|
||||
m_blendTok.shutdown();
|
||||
}
|
||||
|
||||
ClientProcess::ClientProcess(int verbosityLevel)
|
||||
: m_verbosity(verbosityLevel)
|
||||
ClientProcess::ClientProcess(int verbosityLevel, bool fast, bool force)
|
||||
: m_verbosity(verbosityLevel), m_fast(fast), m_force(force)
|
||||
{
|
||||
#ifdef HECL_MULTIPROCESSOR
|
||||
const int cpuCount = GetCPUCount();
|
||||
@@ -161,8 +154,21 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
|
||||
if (specEnt)
|
||||
{
|
||||
hecl::ProjectPath cooked = path.getCookedPath(*specEnt);
|
||||
if (m_fast)
|
||||
cooked = cooked.getWithExtension(_S(".fast"));
|
||||
cooked.makeDirChain(false);
|
||||
spec->doCook(path, cooked, false, btok, [](const SystemChar*) {});
|
||||
if (m_force || cooked.getPathType() == ProjectPath::Type::None ||
|
||||
path.getModtime() > cooked.getModtime())
|
||||
{
|
||||
if (path.getAuxInfo().empty())
|
||||
LogModule.report(logvisor::Info, _S("Cooking %s"),
|
||||
path.getRelativePath().c_str());
|
||||
else
|
||||
LogModule.report(logvisor::Info, _S("Cooking %s|%s"),
|
||||
path.getRelativePath().c_str(),
|
||||
path.getAuxInfo().c_str());
|
||||
spec->doCook(path, cooked, false, btok, [](const SystemChar*) {});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "hecl/Database.hpp"
|
||||
#include "hecl/Blender/BlenderConnection.hpp"
|
||||
#include "hecl/ClientProcess.hpp"
|
||||
|
||||
namespace hecl
|
||||
{
|
||||
@@ -56,6 +57,7 @@ std::vector<std::string>& Project::ConfigFile::lockAndRead()
|
||||
return m_lines;
|
||||
|
||||
m_lockedFile = hecl::Fopen(m_filepath.c_str(), _S("a+"), FileLockType::Write);
|
||||
hecl::FSeek(m_lockedFile, 0, SEEK_SET);
|
||||
|
||||
std::string mainString;
|
||||
char readBuf[1024];
|
||||
@@ -366,7 +368,8 @@ public:
|
||||
submsg += _S(" (");
|
||||
submsg += specEnt->m_name;
|
||||
submsg += _S(')');
|
||||
m_progFunc(m_dir, submsg.c_str(), lidx, m_prog);
|
||||
if (m_progFunc)
|
||||
m_progFunc(m_dir, submsg.c_str(), lidx, m_prog);
|
||||
}
|
||||
void reportFile(const DataSpecEntry* specEnt, const SystemChar* extra)
|
||||
{
|
||||
@@ -376,36 +379,47 @@ public:
|
||||
submsg += _S(", ");
|
||||
submsg += extra;
|
||||
submsg += _S(')');
|
||||
m_progFunc(m_dir, submsg.c_str(), lidx, m_prog);
|
||||
if (m_progFunc)
|
||||
m_progFunc(m_dir, submsg.c_str(), lidx, m_prog);
|
||||
}
|
||||
void reportDirComplete()
|
||||
{
|
||||
if (m_progFunc)
|
||||
m_progFunc(m_dir, nullptr, lidx, 1.0);
|
||||
}
|
||||
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, bool fast,
|
||||
std::vector<SpecInst>& specInsts,
|
||||
CookProgress& progress)
|
||||
std::vector<std::unique_ptr<IDataSpec>>& specInsts,
|
||||
CookProgress& progress, ClientProcess* cp)
|
||||
{
|
||||
for (SpecInst& spec : specInsts)
|
||||
for (auto& spec : specInsts)
|
||||
{
|
||||
if (spec.second->canCook(path, hecl::SharedBlenderToken))
|
||||
if (spec->canCook(path, hecl::SharedBlenderToken))
|
||||
{
|
||||
const DataSpecEntry* override = spec.second->overrideDataSpec(path, spec.first, hecl::SharedBlenderToken);
|
||||
if (!override)
|
||||
continue;
|
||||
ProjectPath cooked = path.getCookedPath(*override);
|
||||
if (fast)
|
||||
cooked = cooked.getWithExtension(_S(".fast"));
|
||||
if (force || cooked.getPathType() == ProjectPath::Type::None ||
|
||||
path.getModtime() > cooked.getModtime())
|
||||
if (cp)
|
||||
{
|
||||
progress.reportFile(override);
|
||||
spec.second->doCook(path, cooked, fast, hecl::SharedBlenderToken,
|
||||
[&](const SystemChar* extra)
|
||||
cp->addCookTransaction(path, spec.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
const DataSpecEntry* override = spec->overrideDataSpec(path, spec->getDataSpecEntry(),
|
||||
hecl::SharedBlenderToken);
|
||||
if (!override)
|
||||
continue;
|
||||
ProjectPath cooked = path.getCookedPath(*override);
|
||||
if (fast)
|
||||
cooked = cooked.getWithExtension(_S(".fast"));
|
||||
if (force || cooked.getPathType() == ProjectPath::Type::None ||
|
||||
path.getModtime() > cooked.getModtime())
|
||||
{
|
||||
progress.reportFile(override, extra);
|
||||
});
|
||||
progress.reportFile(override);
|
||||
spec->doCook(path, cooked, fast, hecl::SharedBlenderToken,
|
||||
[&](const SystemChar* extra)
|
||||
{
|
||||
progress.reportFile(override, extra);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,9 +427,12 @@ static void VisitFile(const ProjectPath& path, bool force, bool fast,
|
||||
|
||||
static void VisitDirectory(const ProjectPath& dir,
|
||||
bool recursive, bool force, bool fast,
|
||||
std::vector<SpecInst>& specInsts,
|
||||
CookProgress& progress)
|
||||
std::vector<std::unique_ptr<IDataSpec>>& specInsts,
|
||||
CookProgress& progress, ClientProcess* cp)
|
||||
{
|
||||
if (dir.getLastComponent()[0] == _S('.'))
|
||||
return;
|
||||
|
||||
std::map<SystemString, ProjectPath> children;
|
||||
dir.getDirChildren(children);
|
||||
|
||||
@@ -434,7 +451,7 @@ static void VisitDirectory(const ProjectPath& dir,
|
||||
if (child.second.getPathType() == ProjectPath::Type::File)
|
||||
{
|
||||
progress.changeFile(child.first.c_str(), progNum++/progDenom);
|
||||
VisitFile(child.second, force, fast, specInsts, progress);
|
||||
VisitFile(child.second, force, fast, specInsts, progress, cp);
|
||||
}
|
||||
}
|
||||
progress.reportDirComplete();
|
||||
@@ -448,7 +465,7 @@ static void VisitDirectory(const ProjectPath& dir,
|
||||
{
|
||||
case ProjectPath::Type::Directory:
|
||||
{
|
||||
VisitDirectory(child.second, recursive, force, fast, specInsts, progress);
|
||||
VisitDirectory(child.second, recursive, force, fast, specInsts, progress, cp);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@@ -457,70 +474,32 @@ static void VisitDirectory(const ProjectPath& dir,
|
||||
}
|
||||
}
|
||||
|
||||
static void VisitGlob(const ProjectPath& path,
|
||||
bool recursive, bool force, bool fast,
|
||||
std::vector<SpecInst>& specInsts,
|
||||
CookProgress& progress)
|
||||
{
|
||||
std::vector<ProjectPath> children;
|
||||
path.getGlobResults(children, path.getProject().getProjectRootPath().getAbsolutePath());
|
||||
|
||||
/* Pass 1: child file count */
|
||||
int childFileCount = 0;
|
||||
for (ProjectPath& child : children)
|
||||
if (child.getPathType() == ProjectPath::Type::File)
|
||||
++childFileCount;
|
||||
|
||||
/* Pass 2: child files */
|
||||
int progNum = 0;
|
||||
float progDenom = childFileCount;
|
||||
progress.changeDir(path.getLastComponent());
|
||||
for (ProjectPath& child : children)
|
||||
{
|
||||
if (child.getPathType() == ProjectPath::Type::File)
|
||||
{
|
||||
progress.changeFile(child.getLastComponent(), progNum++/progDenom);
|
||||
VisitFile(child, force, fast, specInsts, progress);
|
||||
}
|
||||
}
|
||||
progress.reportDirComplete();
|
||||
|
||||
/* Pass 3: child directories */
|
||||
if (recursive)
|
||||
for (ProjectPath& child : children)
|
||||
if (child.getPathType() == ProjectPath::Type::Directory)
|
||||
VisitDirectory(child, recursive, force, fast, specInsts, progress);
|
||||
}
|
||||
|
||||
bool Project::cookPath(const ProjectPath& path, FProgress progress,
|
||||
bool recursive, bool force, bool fast)
|
||||
bool recursive, bool force, bool fast, ClientProcess* cp)
|
||||
{
|
||||
/* Construct DataSpec instances for cooking */
|
||||
std::vector<SpecInst> specInsts;
|
||||
specInsts.reserve(m_compiledSpecs.size());
|
||||
for (const ProjectDataSpec& spec : m_compiledSpecs)
|
||||
if (spec.active && spec.spec.m_factory)
|
||||
specInsts.emplace_back(&spec.spec,
|
||||
std::unique_ptr<IDataSpec>(spec.spec.m_factory(*this, DataSpecTool::Cook)));
|
||||
if (m_cookSpecs.empty())
|
||||
{
|
||||
m_cookSpecs.reserve(m_compiledSpecs.size());
|
||||
for (const ProjectDataSpec& spec : m_compiledSpecs)
|
||||
if (spec.active && spec.spec.m_factory)
|
||||
m_cookSpecs.push_back(std::unique_ptr<IDataSpec>(spec.spec.m_factory(*this, DataSpecTool::Cook)));
|
||||
}
|
||||
|
||||
/* Iterate complete directory/file/glob list */
|
||||
CookProgress cookProg(progress);
|
||||
switch (path.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::File:
|
||||
case ProjectPath::Type::Glob:
|
||||
{
|
||||
cookProg.changeFile(path.getLastComponent(), 0.0);
|
||||
VisitFile(path, force, fast, specInsts, cookProg);
|
||||
VisitFile(path, force, fast, m_cookSpecs, cookProg, cp);
|
||||
break;
|
||||
}
|
||||
case ProjectPath::Type::Directory:
|
||||
{
|
||||
VisitDirectory(path, recursive, force, fast, specInsts, cookProg);
|
||||
break;
|
||||
}
|
||||
case ProjectPath::Type::Glob:
|
||||
{
|
||||
VisitGlob(path, recursive, force, fast, specInsts, cookProg);
|
||||
VisitDirectory(path, recursive, force, fast, m_cookSpecs, cookProg, cp);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@@ -529,6 +508,39 @@ bool Project::cookPath(const ProjectPath& path, FProgress progress,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Project::packagePath(const ProjectPath& path, FProgress progress, bool fast, ClientProcess* cp)
|
||||
{
|
||||
/* Construct DataSpec instance for packaging */
|
||||
const DataSpecEntry* specEntry = nullptr;
|
||||
bool foundPC = false;
|
||||
for (const ProjectDataSpec& spec : m_compiledSpecs)
|
||||
{
|
||||
if (spec.active && spec.spec.m_factory)
|
||||
{
|
||||
if (hecl::StringUtils::EndsWith(spec.spec.m_name, _S("-PC")))
|
||||
{
|
||||
foundPC = true;
|
||||
specEntry = &spec.spec;
|
||||
}
|
||||
else if (!foundPC)
|
||||
{
|
||||
specEntry = &spec.spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (specEntry && (!m_lastPackageSpec || m_lastPackageSpec->getDataSpecEntry() != specEntry))
|
||||
m_lastPackageSpec = std::unique_ptr<IDataSpec>(specEntry->m_factory(*this, DataSpecTool::Package));
|
||||
|
||||
if (m_lastPackageSpec->canPackage(path))
|
||||
{
|
||||
m_lastPackageSpec->doPackage(path, specEntry, fast, hecl::SharedBlenderToken, progress, cp);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Project::interruptCook()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ Time ProjectPath::getModtime() const
|
||||
if (m_absPath.find(_S('*')) != SystemString::npos)
|
||||
{
|
||||
std::vector<ProjectPath> globResults;
|
||||
getGlobResults(globResults, m_proj->getProjectRootPath().getAbsolutePath());
|
||||
getGlobResults(globResults);
|
||||
for (ProjectPath& path : globResults)
|
||||
{
|
||||
if (!hecl::Stat(path.getAbsolutePath().c_str(), &theStat))
|
||||
@@ -197,13 +197,21 @@ static void _recursiveGlob(Database::Project& proj,
|
||||
return;
|
||||
|
||||
const SystemString& comp = matches[1];
|
||||
if (comp.find(_S('*')) != SystemString::npos)
|
||||
if (comp.find(_S('*')) == SystemString::npos)
|
||||
{
|
||||
SystemString nextItStr = itStr;
|
||||
if (needSlash)
|
||||
nextItStr += _S('/');
|
||||
nextItStr += comp;
|
||||
_recursiveGlob(proj, outPaths, matches.suffix(), nextItStr, true);
|
||||
|
||||
hecl::Sstat theStat;
|
||||
if (Stat(nextItStr.c_str(), &theStat))
|
||||
return;
|
||||
|
||||
if (S_ISDIR(theStat.st_mode))
|
||||
_recursiveGlob(proj, outPaths, matches.suffix(), nextItStr, true);
|
||||
else
|
||||
outPaths.emplace_back(proj, nextItStr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -213,7 +221,7 @@ static void _recursiveGlob(Database::Project& proj,
|
||||
hecl::DirectoryEnumerator de(itStr);
|
||||
for (const hecl::DirectoryEnumerator::Entry& ent : de)
|
||||
{
|
||||
if (std::regex_search(ent.m_name, regComp))
|
||||
if (std::regex_match(ent.m_name, regComp))
|
||||
{
|
||||
SystemString nextItStr = itStr;
|
||||
if (needSlash)
|
||||
@@ -244,24 +252,10 @@ hecl::DirectoryEnumerator ProjectPath::enumerateDir() const
|
||||
return hecl::DirectoryEnumerator(m_absPath);
|
||||
}
|
||||
|
||||
void ProjectPath::getGlobResults(std::vector<ProjectPath>& outPaths, const SystemString& startPath) const
|
||||
void ProjectPath::getGlobResults(std::vector<ProjectPath>& outPaths) const
|
||||
{
|
||||
SystemString itStr;
|
||||
if (startPath == _S(""))
|
||||
{
|
||||
#if _WIN32
|
||||
SystemRegexMatch letterMatch;
|
||||
if (m_absPath.compare(0, 2, _S("//")))
|
||||
itStr = _S("\\\\");
|
||||
else if (std::regex_search(m_absPath, letterMatch, regDRIVELETTER))
|
||||
if (letterMatch[1].str().size())
|
||||
itStr = letterMatch[1];
|
||||
#else
|
||||
itStr = _S("/");
|
||||
#endif
|
||||
}
|
||||
|
||||
_recursiveGlob(*m_proj, outPaths, m_absPath, itStr, false);
|
||||
const SystemString& rootPath = m_proj->getProjectRootPath().getAbsolutePath();
|
||||
_recursiveGlob(*m_proj, outPaths, m_relPath, rootPath, rootPath.back() != _S('/'));
|
||||
}
|
||||
|
||||
ProjectRootPath SearchForProject(const SystemString& path)
|
||||
|
||||
Reference in New Issue
Block a user