diff --git a/DataSpec/DNACommon/DNACommon.cpp b/DataSpec/DNACommon/DNACommon.cpp index a4e47644c..1c3633442 100644 --- a/DataSpec/DNACommon/DNACommon.cpp +++ b/DataSpec/DNACommon/DNACommon.cpp @@ -57,12 +57,14 @@ hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID64& id, boo template hecl::ProjectPath UniqueIDBridge::MakePathFromString(const std::string& str) { + if (str.empty()) + return {}; hecl::Database::Project* project = s_Project.get(); if (!project) LogDNACommon.report(logvisor::Fatal, "UniqueIDBridge::setGlobalProject must be called before MakePathFromString"); hecl::ProjectPath path = hecl::ProjectPath(*project, str); - project->addBridgePathToCache(IDType(path), path); + project->addBridgePathToCache(IDType(path).toUint64(), path); return path; } template @@ -101,7 +103,9 @@ void UniqueID32::write(athena::io::YAMLDocWriter& writer) const hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); if (!path) return; - writer.writeString(nullptr, path.getRelativePathUTF8()); + writer.writeString(nullptr, path.getAuxInfo().size() ? + (path.getRelativePathUTF8() + _S('|') + path.getAuxInfoUTF8()) : + path.getRelativePathUTF8()); } size_t UniqueID32::binarySize(size_t __isz) const {return __isz + 4;} @@ -181,7 +185,9 @@ void UniqueID64::write(athena::io::YAMLDocWriter& writer) const hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); if (!path) return; - writer.writeString(nullptr, path.getRelativePathUTF8()); + writer.writeString(nullptr, path.getAuxInfo().size() ? + (path.getRelativePathUTF8() + _S('|') + path.getAuxInfoUTF8()) : + path.getRelativePathUTF8()); } size_t UniqueID64::binarySize(size_t __isz) const {return __isz + 8;} @@ -215,7 +221,9 @@ void UniqueID128::write(athena::io::YAMLDocWriter& writer) const hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); if (!path) return; - writer.writeString(nullptr, path.getRelativePathUTF8()); + writer.writeString(nullptr, path.getAuxInfo().size() ? + (path.getRelativePathUTF8() + _S('|') + path.getAuxInfoUTF8()) : + path.getRelativePathUTF8()); } size_t UniqueID128::binarySize(size_t __isz) const {return __isz + 16;} diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index de99f25ff..417fd37f7 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -1156,6 +1156,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, { hecl::SystemStringView sysStr(arm.name); hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".CINF")).getCookedPath(SpecEntMP1); + pathOut.makeDirChain(false); athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false); if (w.hasError()) Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"), @@ -1227,6 +1228,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, hecl::SystemStringView sysStr(ch.name); hecl::ProjectPath skinPath = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR")).getCookedPath(SpecEntMP1PC); + skinPath.makeDirChain(false); athena::io::FileWriter skinOut(skinPath.getAbsolutePath(), true, false); if (skinOut.hasError()) Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"), @@ -1255,6 +1257,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, hecl::SystemStringView sysStr(act.name); hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM")); hecl::ProjectPath cookedOut = pathOut.getCookedPath(SpecEntMP1PC); + cookedOut.makeDirChain(false); athena::io::FileWriter w(cookedOut.getAbsolutePath(), true, false); if (w.hasError()) Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"), @@ -1277,6 +1280,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, evnt.fromYAMLStream(reader); hecl::ProjectPath evntCookedOut = evntYamlPath.getCookedPath(SpecEntMP1); + evntCookedOut.makeDirChain(false); athena::io::FileWriter w(evntCookedOut.getAbsolutePath(), true, false); if (w.hasError()) Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"), diff --git a/DataSpec/DNAMP1/MLVL.cpp b/DataSpec/DNAMP1/MLVL.cpp index 124742b40..737c81458 100644 --- a/DataSpec/DNAMP1/MLVL.cpp +++ b/DataSpec/DNAMP1/MLVL.cpp @@ -48,9 +48,12 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat mlvl.magic = 0xDEAFBABE; mlvl.version = 0x11; - hecl::ProjectPath savwPath = inPath.ensureAuxInfo(_S(".SAVW")); + hecl::ProjectPath namePath(inPath.getParentPath(), _S("!name.yaml")); + if (namePath.isFile()) + mlvl.worldNameId = namePath; + hecl::ProjectPath savwPath = inPath.ensureAuxInfo(_S("SAVW")); mlvl.saveWorldId = savwPath; - hecl::ProjectPath mapwPath = inPath.ensureAuxInfo(_S(".MAPW")); + hecl::ProjectPath mapwPath = inPath.ensureAuxInfo(_S("MAPW")); mlvl.worldMap = mapwPath; std::vector mapaTags; @@ -112,14 +115,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat if (!areaInit) { /* Finish last area */ - if (mlvl.areas.size()) - { - MLVL::Area& areaLast = mlvl.areas.back(); - areaLast.attachedAreaCount = areaLast.attachedAreas.size(); - areaLast.depCount = areaLast.deps.size(); - areaLast.depLayerCount = areaLast.depLayers.size(); - areaLast.dockCount = areaLast.docks.size(); - } + mlvl.finishLastArea(); /* Area map */ hecl::ProjectPath mapPath(area.path, _S("/!map.blend")); @@ -143,7 +139,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat areaOut.areaId = 0xffffffff; hecl::ProjectPath memIdPath(area.path, _S("/!memoryid.yaml")); - if (namePath.isFile()) + if (memIdPath.isFile()) { athena::io::FileReader fr(memIdPath.getAbsolutePath()); athena::io::YAMLDocReader r; @@ -159,22 +155,31 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat { areaOut.docks.emplace_back(); MLVL::Area::Dock& dockOut = areaOut.docks.back(); - dockOut.endpointCount = 1; - dockOut.endpoints.emplace_back(); - MLVL::Area::Dock::Endpoint& ep = dockOut.endpoints.back(); - ep.areaIdx = dock.targetArea; - ep.dockIdx = dock.targetDock; + + if (dock.targetArea != -1 && dock.targetDock != -1) + { + dockOut.endpointCount = 1; + dockOut.endpoints.emplace_back(); + MLVL::Area::Dock::Endpoint& ep = dockOut.endpoints.back(); + ep.areaIdx = dock.targetArea; + ep.dockIdx = dock.targetDock; + + if (addedAreas.find(dock.targetArea) == addedAreas.cend()) + { + addedAreas.insert(dock.targetArea); + areaOut.attachedAreas.push_back(dock.targetArea); + } + } + else + { + dockOut.endpointCount = 0; + } + dockOut.planeVertCount = 4; dockOut.planeVerts.push_back(dock.verts[0]); dockOut.planeVerts.push_back(dock.verts[1]); dockOut.planeVerts.push_back(dock.verts[2]); dockOut.planeVerts.push_back(dock.verts[3]); - - if (addedAreas.find(dock.targetArea) == addedAreas.cend()) - { - addedAreas.insert(dock.targetArea); - areaOut.attachedAreas.push_back(dock.targetArea); - } } areaOut.attachedAreaCount = areaOut.attachedAreas.size(); } @@ -252,6 +257,8 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat std::unordered_set addedScans; for (const Scan& scan : scans) { + if (!scan.scanId) + continue; if (addedScans.find(scan.scanId) == addedScans.cend()) { addedScans.insert(scan.scanId); @@ -275,9 +282,39 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat ++layerIdx; } + + /* Cull duplicate area paths and add typed hash to list */ + auto& conn = hecl::BlenderConnection::SharedConnection(); + if (conn.openBlend(areaPath)) + { + MLVL::Area& areaOut = mlvl.areas.back(); + areaOut.depLayers.push_back(areaOut.deps.size()); + + auto ds = conn.beginData(); + std::vector texs = ds.getTextures(); + ds.close(); + + std::unordered_set addedPaths; + for (const hecl::ProjectPath& path : texs) + { + if (addedPaths.find(path.hash()) == addedPaths.cend()) + { + addedPaths.insert(path.hash()); + urde::SObjectTag tag = g_curSpec->BuildTagFromPath(path, hecl::SharedBlenderToken); + areaOut.deps.emplace_back(tag.id, tag.type); + } + } + + urde::SObjectTag tag = g_curSpec->BuildTagFromPath(areaPath, hecl::SharedBlenderToken); + areaOut.deps.emplace_back(tag.id, tag.type); + } + ++areaIdx; } + /* Finish last area */ + mlvl.finishLastArea(); + mlvl.memRelayLinkCount = mlvl.memRelayLinks.size(); mlvl.areaCount = mlvl.areas.size(); mlvl.layerFlagCount = mlvl.layerFlags.size(); @@ -294,6 +331,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat { hecl::ProjectPath mapwCooked = mapwPath.getCookedPath(*g_curSpec->overrideDataSpec(mapwPath, nullptr, hecl::SharedBlenderToken)); + mapwCooked.makeDirChain(false); athena::io::FileWriter fo(mapwCooked.getAbsolutePath()); fo.writeUint32Big(0xDEADF00D); fo.writeUint32Big(1); @@ -313,6 +351,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat hecl::ProjectPath savwCooked = savwPath.getCookedPath(*g_curSpec->overrideDataSpec(savwPath, nullptr, hecl::SharedBlenderToken)); + savwCooked.makeDirChain(false); athena::io::FileWriter fo(savwCooked.getAbsolutePath()); savw.write(fo); } diff --git a/DataSpec/DNAMP1/MLVL.hpp b/DataSpec/DNAMP1/MLVL.hpp index 042dcfc54..c06b114f4 100644 --- a/DataSpec/DNAMP1/MLVL.hpp +++ b/DataSpec/DNAMP1/MLVL.hpp @@ -81,6 +81,18 @@ struct MLVL : BigYAML }; Vector areas; + void finishLastArea() + { + if (areas.size()) + { + MLVL::Area& areaLast = areas.back(); + areaLast.attachedAreaCount = areaLast.attachedAreas.size(); + areaLast.depCount = areaLast.deps.size(); + areaLast.depLayerCount = areaLast.depLayers.size(); + areaLast.dockCount = areaLast.docks.size(); + } + } + UniqueID32 worldMap; Value unknown2; Value unknown3; diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index eb3c69f16..d752980cb 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -318,7 +318,7 @@ void SpecBase::flattenDependencies(const hecl::ProjectPath& path, case hecl::BlenderConnection::BlendType::Actor: { hecl::BlenderConnection::DataStream ds = conn.beginData(); - hecl::BlenderConnection::DataStream::Actor actor = ds.compileActor(); + hecl::BlenderConnection::DataStream::Actor actor = ds.compileActorCharacterOnly(); for (auto& sub : actor.subtypes) { if (sub.armature >= 0) diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 0e1916c11..ee560d78d 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -415,9 +415,9 @@ struct SpecMP1 : SpecBase { if (path.getAuxInfo().size()) { - if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".MAPW"))) + if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S("MAPW"))) return {SBIG('MAPW'), path.hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".SAVW"))) + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S("SAVW"))) return {SBIG('SAVW'), path.hash().val32()}; } return {SBIG('MLVL'), path.hash().val32()}; diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index dd4737e28..4947d583d 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -14,9 +14,9 @@ static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, 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()); - if (path.getAuxInfo().size()) - cacheWriter.writeString(nullptr, path.getAuxInfoUTF8().c_str()); + cacheWriter.writeString(nullptr, path.getAuxInfo().size() ? + (path.getRelativePathUTF8() + _S('|') + path.getAuxInfoUTF8()) : + path.getRelativePathUTF8()); cacheWriter.leaveSubVector(); } @@ -221,7 +221,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, pathTag = {SBIG('MLVL'), asGlob.hash().val32()}; useGlob = true; - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(_S(".MAPW")); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(_S("MAPW")); SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; @@ -229,7 +229,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, DumpCacheAdd(pathTag, subPath); #endif - subPath = asGlob.ensureAuxInfo(_S(".SAVW")); + subPath = asGlob.ensureAuxInfo(_S("SAVW")); pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; @@ -320,11 +320,6 @@ void ProjectResourceFactoryBase::BackgroundIndexProc() hecl::FourCC type(node.m_seqChildren.at(0)->m_scalarString.c_str()); hecl::ProjectPath path(m_proj->getProjectWorkingPath(), node.m_seqChildren.at(1)->m_scalarString); - if (node.m_seqChildren.size() >= 3) - { - hecl::SystemStringView sys(node.m_seqChildren[2]->m_scalarString); - path = path.ensureAuxInfo(sys.sys_str()); - } if (path.isFileOrGlob()) { diff --git a/hecl b/hecl index 2cc14eaa3..043e2eaae 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 2cc14eaa3642f003b0c71945e23c4a70482c1bda +Subproject commit 043e2eaae8e1ff9e40619bd8fa56597b4b29dde2