diff --git a/DataSpec/DNACommon/ParticleCommon.hpp b/DataSpec/DNACommon/ParticleCommon.hpp index e5842c69f..138a3a257 100644 --- a/DataSpec/DNACommon/ParticleCommon.hpp +++ b/DataSpec/DNACommon/ParticleCommon.hpp @@ -626,12 +626,15 @@ struct VEConstant : IVectorElement void read(athena::io::YAMLDocReader& r) { - for (int i=0 ; i<3 ; ++i) + size_t elemCount; + r.enterSubVector(nullptr, elemCount); + for (int i=0 ; i<3 && i::value; -SpecBase::SpecBase(hecl::Database::Project& project, bool pc) -: m_project(project), m_pc(pc), +SpecBase::SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) +: hecl::Database::IDataSpec(specEntry), m_project(project), m_pc(pc), m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") {} bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector& reps) @@ -114,13 +114,13 @@ void SpecBase::doExtract(const ExtractPassInfo& info, FProgress progress) extractFromDisc(*m_disc, info.force, progress); } -bool SpecBase::canCook(const hecl::ProjectPath& path) +bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::BlenderToken& btok) { if (!checkPathPrefix(path)) return false; if (hecl::IsPathBlend(path)) { - hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection(); + hecl::BlenderConnection& conn = btok.getBlenderConnection(); if (!conn.openBlend(path)) return false; if (conn.getBlendType() != hecl::BlenderConnection::BlendType::None) @@ -141,13 +141,14 @@ bool SpecBase::canCook(const hecl::ProjectPath& path) } const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::ProjectPath& path, - const hecl::Database::DataSpecEntry* oldEntry) + const hecl::Database::DataSpecEntry* oldEntry, + hecl::BlenderToken& btok) { if (!checkPathPrefix(path)) return nullptr; if (hecl::IsPathBlend(path)) { - hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection(); + hecl::BlenderConnection& conn = btok.getBlenderConnection(); if (!conn.openBlend(path)) { Log.report(logvisor::Error, _S("unable to cook '%s'"), @@ -167,12 +168,12 @@ const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::Proj } void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, - bool fast, FCookProgress progress) + bool fast, hecl::BlenderToken& btok, FCookProgress progress) { DataSpec::g_curSpec = this; if (hecl::IsPathBlend(path)) { - hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection(); + hecl::BlenderConnection& conn = btok.getBlenderConnection(); if (!conn.openBlend(path)) return; switch (conn.getBlendType()) @@ -209,6 +210,7 @@ void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& co { FILE* fp = hecl::Fopen(path.getAbsolutePath().c_str(), _S("r")); cookYAML(cookedPath, path, fp, progress); + fclose(fp); } } diff --git a/DataSpec/SpecBase.hpp b/DataSpec/SpecBase.hpp index 11cb8e5c1..52136c254 100644 --- a/DataSpec/SpecBase.hpp +++ b/DataSpec/SpecBase.hpp @@ -16,11 +16,12 @@ struct SpecBase : hecl::Database::IDataSpec bool canExtract(const ExtractPassInfo& info, std::vector& reps); void doExtract(const ExtractPassInfo& info, FProgress progress); - bool canCook(const hecl::ProjectPath& path); + bool canCook(const hecl::ProjectPath& path, hecl::BlenderToken& btok); const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path, - const hecl::Database::DataSpecEntry* oldEntry); + const hecl::Database::DataSpecEntry* oldEntry, + hecl::BlenderToken& btok); void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, - bool fast, FCookProgress progress); + bool fast, hecl::BlenderToken& btok, FCookProgress progress); bool canPackage(const PackagePassInfo& info); void gatherDependencies(const PackagePassInfo& info, @@ -72,7 +73,7 @@ struct SpecBase : hecl::Database::IDataSpec /* Project accessor */ hecl::Database::Project& getProject() const {return m_project;} - SpecBase(hecl::Database::Project& project, bool pc); + SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc); protected: hecl::Database::Project& m_project; bool m_pc; diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index d8b07df44..a1d787ad3 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -9,6 +9,7 @@ #include "DNAMP1/STRG.hpp" #include "DNAMP1/CMDL.hpp" #include "DNAMP1/ANCS.hpp" +#include "DNACommon/PART.hpp" namespace DataSpec { @@ -33,8 +34,8 @@ struct SpecMP1 : SpecBase hecl::ProjectPath m_cookPath; PAKRouter m_pakRouter; - SpecMP1(hecl::Database::Project& project, bool pc) - : SpecBase(project, pc), + SpecMP1(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc), m_workPath(project.getProjectWorkingPath(), _S("MP1")), m_cookPath(project.getProjectCookedPath(SpecEntMP1), _S("MP1")), m_pakRouter(*this, m_workPath, m_cookPath) {} @@ -286,11 +287,18 @@ struct SpecMP1 : SpecBase bool validateYAMLDNAType(FILE* fp) const { - if (BigYAML::ValidateFromYAMLFile(fp)) - return true; - if (BigYAML::ValidateFromYAMLFile(fp)) - return true; - return false; + athena::io::YAMLDocReader reader; + yaml_parser_set_input_file(reader.getParser(), fp); + return reader.ClassTypeOperation([](const char* classType) + { + if (!strcmp(classType, DNAMP1::MLVL::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::STRG::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::GPSM::DNAType())) + return true; + return false; + }); } void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, @@ -319,6 +327,27 @@ struct SpecMP1 : SpecBase void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FILE* fin, FCookProgress progress) const { + athena::io::YAMLDocReader reader; + yaml_parser_set_input_file(reader.getParser(), fin); + if (reader.parse()) + { + std::string classStr = reader.readString("DNAType"); + if (classStr.empty()) + return; + + if (!classStr.compare(DNAMP1::STRG::DNAType())) + { + DNAMP1::STRG strg; + strg.read(reader); + DNAMP1::STRG::Cook(strg, out); + } + else if (!classStr.compare(DNAParticle::GPSM::DNAType())) + { + DNAParticle::GPSM gpsm; + gpsm.read(reader); + DNAParticle::WriteGPSM(gpsm, out); + } + } } }; @@ -327,7 +356,7 @@ hecl::Database::DataSpecEntry SpecEntMP1 = _S("MP1"), _S("Data specification for original Metroid Prime engine"), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) - -> hecl::Database::IDataSpec* {return new struct SpecMP1(project, false);} + -> hecl::Database::IDataSpec* {return new struct SpecMP1(&SpecEntMP1, project, false);} }; hecl::Database::DataSpecEntry SpecEntMP1PC = @@ -338,7 +367,7 @@ hecl::Database::DataSpecEntry SpecEntMP1PC = -> hecl::Database::IDataSpec* { if (tool != hecl::Database::DataSpecTool::Extract) - return new struct SpecMP1(project, true); + return new struct SpecMP1(&SpecEntMP1PC, project, true); return nullptr; } }; diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 0c28220aa..9b3836ff5 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -29,8 +29,8 @@ struct SpecMP2 : SpecBase hecl::ProjectPath m_cookPath; PAKRouter m_pakRouter; - SpecMP2(hecl::Database::Project& project, bool pc) - : SpecBase(project, pc), + SpecMP2(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc), m_workPath(project.getProjectWorkingPath(), _S("MP2")), m_cookPath(project.getProjectCookedPath(SpecEntMP2), _S("MP2")), m_pakRouter(*this, m_workPath, m_cookPath) {} @@ -307,7 +307,7 @@ hecl::Database::DataSpecEntry SpecEntMP2 _S("MP2"), _S("Data specification for original Metroid Prime 2 engine"), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) - -> hecl::Database::IDataSpec* {return new struct SpecMP2(project, false);} + -> hecl::Database::IDataSpec* {return new struct SpecMP2(&SpecEntMP2, project, false);} ); hecl::Database::DataSpecEntry SpecEntMP2PC = @@ -318,7 +318,7 @@ hecl::Database::DataSpecEntry SpecEntMP2PC = -> hecl::Database::IDataSpec* { if (tool != hecl::Database::DataSpecTool::Extract) - return new struct SpecMP2(project, true); + return new struct SpecMP2(&SpecEntMP2PC, project, true); return nullptr; } }; diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 02f318d17..c2c5b4a48 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -42,8 +42,8 @@ struct SpecMP3 : SpecBase hecl::ProjectPath m_feCookPath; PAKRouter m_fePakRouter; - SpecMP3(hecl::Database::Project& project, bool pc) - : SpecBase(project, pc), + SpecMP3(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc), m_workPath(project.getProjectWorkingPath(), _S("MP3")), m_cookPath(project.getProjectCookedPath(SpecEntMP3), _S("MP3")), m_pakRouter(*this, m_workPath, m_cookPath), @@ -491,7 +491,7 @@ hecl::Database::DataSpecEntry SpecEntMP3 _S("MP3"), _S("Data specification for original Metroid Prime 3 engine"), [](hecl::Database::Project& project, hecl::Database::DataSpecTool) - -> hecl::Database::IDataSpec* {return new struct SpecMP3(project, false);} + -> hecl::Database::IDataSpec* {return new struct SpecMP3(&SpecEntMP3, project, false);} ); hecl::Database::DataSpecEntry SpecEntMP3PC = @@ -502,7 +502,7 @@ hecl::Database::DataSpecEntry SpecEntMP3PC = -> hecl::Database::IDataSpec* { if (tool != hecl::Database::DataSpecTool::Extract) - return new struct SpecMP3(project, true); + return new struct SpecMP3(&SpecEntMP3PC, project, true); return nullptr; } }; diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 93573bdd4..5fc6988b9 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -20,7 +20,8 @@ hecl::BlenderConnection& ProjectResourceFactoryBase::GetBackgroundBlender() cons return *shareConn; } -void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPath) +void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPath, + athena::io::YAMLDocWriter& nameWriter) { FILE* fp = hecl::Fopen(catalogPath.getAbsolutePath().c_str(), _S("r")); if (!fp) @@ -44,6 +45,10 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat { std::unique_lock lk(m_backgroundIndexMutex); m_catalogNameToTag[p.first] = pathTag; + + char idStr[9]; + snprintf(idStr, 9, "%08X", uint32_t(pathTag.id)); + nameWriter.writeString(p.first.c_str(), idStr); #if 0 fprintf(stderr, "%s %s %08X\n", p.first.c_str(), @@ -53,7 +58,43 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat } } -void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::ProjectPath& dir, int level) +void ProjectResourceFactoryBase::BackgroundIndexRecursiveCatalogs(const hecl::ProjectPath& dir, + athena::io::YAMLDocWriter& nameWriter, + int level) +{ + hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), + hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, + false, false, true); + + /* Enumerate all items */ + for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) + { + hecl::ProjectPath path(dir, ent.m_name); + if (ent.m_isDir && level < 1) + BackgroundIndexRecursiveCatalogs(path, nameWriter, level+1); + else + { + if (path.getPathType() != hecl::ProjectPath::Type::File) + continue; + + /* Read catalog.yaml for .pak directory if exists */ + if (level == 1 && !ent.m_name.compare(_S("catalog.yaml"))) + { + ReadCatalog(path, nameWriter); + continue; + } + } + + /* bail if cancelled by client */ + if (!m_backgroundRunning) + break; + } +} + +void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::ProjectPath& dir, + athena::io::YAMLDocWriter& cacheWriter, + athena::io::YAMLDocWriter& nameWriter, + int level) { hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, @@ -64,7 +105,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec { hecl::ProjectPath path(dir, ent.m_name); if (ent.m_isDir) - BackgroundIndexRecursiveProc(path, level+1); + BackgroundIndexRecursiveProc(path, cacheWriter, nameWriter, level+1); else { if (path.getPathType() != hecl::ProjectPath::Type::File) @@ -73,7 +114,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec /* Read catalog.yaml for .pak directory if exists */ if (level == 1 && !ent.m_name.compare(_S("catalog.yaml"))) { - ReadCatalog(path); + ReadCatalog(path, nameWriter); continue; } @@ -83,7 +124,13 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec { std::unique_lock lk(m_backgroundIndexMutex); m_tagToPath[pathTag] = path; -#if 0 + char idStr[9]; + snprintf(idStr, 9, "%08X", uint32_t(pathTag.id)); + cacheWriter.enterSubVector(idStr); + cacheWriter.writeString(nullptr, pathTag.type.toString().c_str()); + cacheWriter.writeString(nullptr, path.getRelativePathUTF8().c_str()); + cacheWriter.leaveSubVector(); +#if 1 fprintf(stderr, "%s %08X %s\n", pathTag.type.toString().c_str(), uint32_t(pathTag.id), path.getRelativePathUTF8().c_str()); @@ -99,19 +146,107 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec void ProjectResourceFactoryBase::BackgroundIndexProc() { + hecl::ProjectPath tagCachePath(m_proj->getProjectCookedPath(*m_origSpec), _S("tag_cache.yaml")); + hecl::ProjectPath nameCachePath(m_proj->getProjectCookedPath(*m_origSpec), _S("name_cache.yaml")); hecl::ProjectPath specRoot(m_proj->getProjectWorkingPath(), m_origSpec->m_name); - BackgroundIndexRecursiveProc(specRoot, 0); + + /* Read in tag cache */ + if (tagCachePath.getPathType() == hecl::ProjectPath::Type::File) + { + FILE* cacheFile = hecl::Fopen(tagCachePath.getAbsolutePath().c_str(), _S("r")); + if (cacheFile) + { + Log.report(logvisor::Info, _S("Cache index of '%s' loading"), m_origSpec->m_name); + athena::io::YAMLDocReader cacheReader; + yaml_parser_set_input_file(cacheReader.getParser(), cacheFile); + if (cacheReader.parse()) + { + std::unique_lock lk(m_backgroundIndexMutex); + m_tagToPath.reserve(cacheReader.getRootNode()->m_mapChildren.size()); + for (const auto& child : cacheReader.getRootNode()->m_mapChildren) + { + unsigned long id = strtoul(child.first.c_str(), nullptr, 16); + hecl::FourCC type(child.second->m_seqChildren.at(0)->m_scalarString.c_str()); + hecl::ProjectPath path(m_proj->getProjectWorkingPath(), + child.second->m_seqChildren.at(1)->m_scalarString); + m_tagToPath[SObjectTag(type, id)] = path; + } + } + fclose(cacheFile); + Log.report(logvisor::Info, _S("Cache index of '%s' loaded; %d tags"), + m_origSpec->m_name, m_tagToPath.size()); + + if (nameCachePath.getPathType() == hecl::ProjectPath::Type::File) + { + /* Read in name cache */ + Log.report(logvisor::Info, _S("Name index of '%s' loading"), m_origSpec->m_name); + FILE* nameFile = hecl::Fopen(nameCachePath.getAbsolutePath().c_str(), _S("r")); + athena::io::YAMLDocReader nameReader; + yaml_parser_set_input_file(nameReader.getParser(), nameFile); + if (nameReader.parse()) + { + std::unique_lock lk(m_backgroundIndexMutex); + m_catalogNameToTag.reserve(nameReader.getRootNode()->m_mapChildren.size()); + for (const auto& child : nameReader.getRootNode()->m_mapChildren) + { + unsigned long id = strtoul(child.second->m_scalarString.c_str(), nullptr, 16); + auto search = m_tagToPath.find(SObjectTag(FourCC(), uint32_t(id))); + if (search != m_tagToPath.cend()) + m_catalogNameToTag[child.first] = search->first; + } + } + fclose(nameFile); + Log.report(logvisor::Info, _S("Name index of '%s' loaded; %d names"), + m_origSpec->m_name, m_catalogNameToTag.size()); + } + else + { + /* Build name cache */ + Log.report(logvisor::Info, _S("Name index of '%s' started"), m_origSpec->m_name); + athena::io::YAMLDocWriter nameWriter(nullptr); + BackgroundIndexRecursiveCatalogs(specRoot, nameWriter, 0); + FILE* nameFile = hecl::Fopen(nameCachePath.getAbsolutePath().c_str(), _S("w")); + yaml_emitter_set_output_file(nameWriter.getEmitter(), nameFile); + nameWriter.finish(); + fclose(nameFile); + Log.report(logvisor::Info, _S("Name index of '%s' complete; %d names"), + m_origSpec->m_name, m_catalogNameToTag.size()); + } + m_backgroundRunning = false; + return; + } + } + + Log.report(logvisor::Info, _S("Background index of '%s' started"), m_origSpec->m_name); + athena::io::YAMLDocWriter cacheWriter(nullptr); + athena::io::YAMLDocWriter nameWriter(nullptr); + BackgroundIndexRecursiveProc(specRoot, cacheWriter, nameWriter, 0); + + FILE* cacheFile = hecl::Fopen(tagCachePath.getAbsolutePath().c_str(), _S("w")); + yaml_emitter_set_output_file(cacheWriter.getEmitter(), cacheFile); + cacheWriter.finish(); + fclose(cacheFile); + + FILE* nameFile = hecl::Fopen(nameCachePath.getAbsolutePath().c_str(), _S("w")); + yaml_emitter_set_output_file(nameWriter.getEmitter(), nameFile); + nameWriter.finish(); + fclose(nameFile); + + if (m_backgroundBlender) + { + m_backgroundBlender->quitBlender(); + m_backgroundBlender = std::experimental::nullopt; + } + Log.report(logvisor::Info, _S("Background index of '%s' complete; %d tags, %d names"), + m_origSpec->m_name, m_tagToPath.size(), m_catalogNameToTag.size()); m_backgroundRunning = false; - m_backgroundBlender = std::experimental::nullopt; } void ProjectResourceFactoryBase::CancelBackgroundIndex() { - if (m_backgroundRunning && m_backgroundIndexTh.joinable()) - { - m_backgroundRunning = false; + m_backgroundRunning = false; + if (m_backgroundIndexTh.joinable()) m_backgroundIndexTh.join(); - } } void ProjectResourceFactoryBase::BeginBackgroundIndex @@ -135,7 +270,7 @@ hecl::ProjectPath ProjectResourceFactoryBase::GetCookedPath(const hecl::ProjectP { const hecl::Database::DataSpecEntry* spec = m_origSpec; if (pcTarget) - spec = m_cookSpec->overrideDataSpec(working, m_pcSpec); + spec = m_cookSpec->overrideDataSpec(working, m_pcSpec, hecl::SharedBlenderToken); if (!spec) return {}; return working.getCookedPath(*spec); @@ -143,7 +278,7 @@ hecl::ProjectPath ProjectResourceFactoryBase::GetCookedPath(const hecl::ProjectP bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working) { - return m_clientProc.syncCook(working) == 0; + return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::SharedBlenderToken); } CFactoryFnReturn ProjectResourceFactoryBase::SyncMakeObject(const SObjectTag& tag, @@ -210,7 +345,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const hecl::ProjectPath& m_cookedPath.getModtime() < path.getModtime()) { /* Start a background cook here */ - m_cookTransaction = m_parent.m_clientProc.addCookTransaction(path); + m_cookTransaction = m_parent.m_clientProc.addCookTransaction(path, m_parent.m_cookSpec.get()); return; } @@ -246,7 +381,10 @@ bool ProjectResourceFactoryBase::AsyncTask::AsyncPump() if (m_bufTransaction) { if (m_bufTransaction->m_complete) + { + m_complete = true; return true; + } } else if (m_cookTransaction) { @@ -274,6 +412,8 @@ std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjec if (search != m_tagToPath.end()) break; } + if (search == m_tagToPath.end()) + return {}; } else return {}; @@ -312,6 +452,8 @@ bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) if (search != m_tagToPath.end()) break; } + if (search == m_tagToPath.end()) + return false; } else return false; @@ -339,6 +481,8 @@ const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const ch if (search != m_catalogNameToTag.end()) break; } + if (search == m_catalogNameToTag.end()) + return nullptr; } else return nullptr; @@ -363,26 +507,29 @@ void ProjectResourceFactoryBase::AsyncIdle() /* Ensure requested resource is in the index */ std::unique_lock lk(m_backgroundIndexMutex); - AsyncTask& data = it->second; - auto search = m_tagToPath.find(data.x0_tag); + AsyncTask& task = it->second; + auto search = m_tagToPath.find(task.x0_tag); if (search == m_tagToPath.end()) { if (!m_backgroundRunning) { Log.report(logvisor::Error, _S("unable to find async load resource (%s, %08X)"), - data.x0_tag.type.toString().c_str(), data.x0_tag.id); + task.x0_tag.type.toString().c_str(), task.x0_tag.id); it = m_asyncLoadList.erase(it); } continue; } - data.EnsurePath(search->second); + task.EnsurePath(search->second); /* Pump load pipeline (cooking if needed) */ - if (data.AsyncPump()) + if (task.AsyncPump()) { - /* Load complete, build resource */ - athena::io::MemoryReader mr(data.x10_loadBuffer.get(), data.x14_resSize); - *data.xc_targetPtr = m_factoryMgr.MakeObject(data.x0_tag, mr, data.x18_cvXfer).release(); + if (task.m_complete) + { + /* Load complete, build resource */ + athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize); + *task.xc_targetPtr = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer).release(); + } it = m_asyncLoadList.erase(it); continue; } diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index ffc1b31c4..a18a748ac 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -50,6 +50,7 @@ protected: const hecl::ClientProcess::CookTransaction* m_cookTransaction = nullptr; const hecl::ClientProcess::BufferTransaction* m_bufTransaction = nullptr; bool m_failed = false; + bool m_complete = false; AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, IObj** ptr, const CVParamTransfer& xfer) @@ -64,8 +65,15 @@ protected: virtual SObjectTag TagFromPath(const hecl::ProjectPath& path) const=0; hecl::BlenderConnection& GetBackgroundBlender() const; - void ReadCatalog(const hecl::ProjectPath& catalogPath); - void BackgroundIndexRecursiveProc(const hecl::ProjectPath& path, int level); + void ReadCatalog(const hecl::ProjectPath& catalogPath, + athena::io::YAMLDocWriter& nameWriter); + void BackgroundIndexRecursiveProc(const hecl::ProjectPath& path, + athena::io::YAMLDocWriter& cacheWriter, + athena::io::YAMLDocWriter& nameWriter, + int level); + void BackgroundIndexRecursiveCatalogs(const hecl::ProjectPath& path, + athena::io::YAMLDocWriter& nameWriter, + int level); void BackgroundIndexProc(); void CancelBackgroundIndex(); void BeginBackgroundIndex(hecl::Database::Project& proj, @@ -87,6 +95,8 @@ public: void AsyncIdle(); void Shutdown() {CancelBackgroundIndex();} + + ~ProjectResourceFactoryBase() {Shutdown();} }; } diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 877b509e9..62c465534 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -21,21 +21,23 @@ namespace urde void ViewManager::BuildTestPART(urde::IObjectStore& objStore) { //m_partGenDesc = objStore.GetObj({hecl::FOURCC('PART'), 0x972A5CD2}); - /* m_partGenDesc = objStore.GetObj("BusterSparks"); m_partGen.reset(new urde::CElementGen(m_partGenDesc, urde::CElementGen::EModelOrientationType::Normal, urde::CElementGen::EOptionalSystemFlags::None)); m_partGen->SetGlobalScale({5.f, 5.f, 5.f}); m_lineRenderer.reset(new urde::CLineRenderer(urde::CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true)); - */ + m_particleView.reset(new ParticleView(*this, m_viewResources, *m_rootView)); + + /* m_moviePlayer.reset(new CMoviePlayer("Video/SpecialEnding.thp", 1.f, false, true)); m_moviePlayer->SetFrame({-1.0f, 1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {1.0f, -1.0f, 0.f}, {1.0f, 1.0f, 0.f}); CDvdFile testRSF("Audio/frontend_1.rsf"); u64 rsfLen = testRSF.Length(); m_rsfBuf.reset(new u8[rsfLen]); testRSF.SyncRead(m_rsfBuf.get(), rsfLen); + */ //CMoviePlayer::SetStaticAudio(m_rsfBuf.get(), rsfLen, 416480, 1973664); m_videoVoice = m_voiceEngine->allocateNewStereoVoice(32000, &m_voiceCallback); diff --git a/Runtime/IFactory.hpp b/Runtime/IFactory.hpp index 10006a064..bf667a154 100644 --- a/Runtime/IFactory.hpp +++ b/Runtime/IFactory.hpp @@ -12,7 +12,7 @@ class IObj; class IFactory { public: - virtual ~IFactory() {} + virtual ~IFactory() = default; virtual std::unique_ptr Build(const SObjectTag&, const CVParamTransfer&)=0; virtual void BuildAsync(const SObjectTag&, const CVParamTransfer&, IObj**)=0; virtual void CancelBuild(const SObjectTag&)=0; diff --git a/hecl b/hecl index 0dead9f66..fe207bf42 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 0dead9f66e4f5221e22cd2ecfb4ea9857c3a801f +Subproject commit fe207bf42c08164a83420e8ed82ad7f009972307