mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-07-03 07:55:52 +00:00
Work on world cooking
This commit is contained in:
parent
2dad2e2051
commit
26eb9891c8
@ -2,6 +2,7 @@
|
|||||||
#include "../DNAMP1/DNAMP1.hpp"
|
#include "../DNAMP1/DNAMP1.hpp"
|
||||||
#include "../DNAMP2/DNAMP2.hpp"
|
#include "../DNAMP2/DNAMP2.hpp"
|
||||||
#include "../DNAMP3/DNAMP3.hpp"
|
#include "../DNAMP3/DNAMP3.hpp"
|
||||||
|
#include "zeus/CTransform.hpp"
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
@ -286,6 +287,18 @@ bool ReadMAPAToBlender(hecl::BlenderConnection& conn,
|
|||||||
"bpy.context.scene.objects.link(obj)\n"
|
"bpy.context.scene.objects.link(obj)\n"
|
||||||
"bm.free()\n";
|
"bm.free()\n";
|
||||||
|
|
||||||
|
const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id);
|
||||||
|
const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::CMatrix4f::skIdentityMatrix4f;
|
||||||
|
os.format("mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||||
|
"mtxd = mtx.decompose()\n"
|
||||||
|
"obj.rotation_mode = 'QUATERNION'\n"
|
||||||
|
"obj.location = mtxd[0]\n"
|
||||||
|
"obj.rotation_quaternion = mtxd[1]\n"
|
||||||
|
"obj.scale = mtxd[2]\n",
|
||||||
|
mtx[0][0], mtx[1][0], mtx[2][0], mtx[3][0],
|
||||||
|
mtx[0][1], mtx[1][1], mtx[2][1], mtx[3][1],
|
||||||
|
mtx[0][2], mtx[1][2], mtx[2][2], mtx[3][2]);
|
||||||
|
|
||||||
/* World background */
|
/* World background */
|
||||||
hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend");
|
hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend");
|
||||||
if (worldBlend.isFile())
|
if (worldBlend.isFile())
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "DNACommon.hpp"
|
#include "DNACommon.hpp"
|
||||||
#include "GX.hpp"
|
#include "GX.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
namespace DNAMAPA
|
namespace DNAMAPA
|
||||||
|
@ -202,6 +202,10 @@ void PAKRouter<BRIDGETYPE>::build(std::vector<BRIDGETYPE>& bridges, std::functio
|
|||||||
athena::io::YAMLDocWriter catalogWriter(nullptr);
|
athena::io::YAMLDocWriter catalogWriter(nullptr);
|
||||||
|
|
||||||
enterPAKBridge(bridge);
|
enterPAKBridge(bridge);
|
||||||
|
|
||||||
|
/* Add MAPA transforms to global map */
|
||||||
|
bridge.addMAPATransforms(*this, m_mapaTransforms, m_overrideEntries);
|
||||||
|
|
||||||
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
|
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
|
||||||
for (const auto& namedEntry : pak.m_nameEntries)
|
for (const auto& namedEntry : pak.m_nameEntries)
|
||||||
{
|
{
|
||||||
@ -224,7 +228,7 @@ void PAKRouter<BRIDGETYPE>::build(std::vector<BRIDGETYPE>& bridges, std::functio
|
|||||||
/* Write catalog */
|
/* Write catalog */
|
||||||
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
||||||
const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first;
|
const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first;
|
||||||
hecl::SystemString catalogPath = hecl::ProjectPath(pakPath, "catalog.yaml").getAbsolutePath();
|
hecl::SystemString catalogPath = hecl::ProjectPath(pakPath, "!catalog.yaml").getAbsolutePath();
|
||||||
athena::io::FileWriter writer(catalogPath);
|
athena::io::FileWriter writer(catalogPath);
|
||||||
catalogWriter.finish(&writer);
|
catalogWriter.finish(&writer);
|
||||||
}
|
}
|
||||||
@ -274,6 +278,11 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getWorking(const EntryType* entry,
|
|||||||
{
|
{
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return hecl::ProjectPath();
|
return hecl::ProjectPath();
|
||||||
|
|
||||||
|
auto overrideSearch = m_overrideEntries.find(entry->id);
|
||||||
|
if (overrideSearch != m_overrideEntries.end())
|
||||||
|
return overrideSearch->second;
|
||||||
|
|
||||||
const PAKType* pak = m_pak.get();
|
const PAKType* pak = m_pak.get();
|
||||||
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
||||||
if (!pak)
|
if (!pak)
|
||||||
@ -384,6 +393,16 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getCooked(const EntryType* entry) const
|
|||||||
{
|
{
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return hecl::ProjectPath();
|
return hecl::ProjectPath();
|
||||||
|
|
||||||
|
auto overrideSearch = m_overrideEntries.find(entry->id);
|
||||||
|
if (overrideSearch != m_overrideEntries.end())
|
||||||
|
{
|
||||||
|
return overrideSearch->second.getCookedPath(
|
||||||
|
*m_dataSpec.overrideDataSpec(overrideSearch->second,
|
||||||
|
m_dataSpec.getDataSpecEntry(),
|
||||||
|
hecl::SharedBlenderToken));
|
||||||
|
}
|
||||||
|
|
||||||
const PAKType* pak = m_pak.get();
|
const PAKType* pak = m_pak.get();
|
||||||
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
intptr_t curBridgeIdx = reinterpret_cast<intptr_t>(m_curBridgeIdx.get());
|
||||||
if (!pak)
|
if (!pak)
|
||||||
@ -636,6 +655,15 @@ const typename PAKRouter<BRIDGETYPE>::RigPair* PAKRouter<BRIDGETYPE>::lookupCMDL
|
|||||||
return &search->second;
|
return &search->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class BRIDGETYPE>
|
||||||
|
const zeus::CMatrix4f* PAKRouter<BRIDGETYPE>::lookupMAPATransform(const IDType& id) const
|
||||||
|
{
|
||||||
|
auto search = m_mapaTransforms.find(id);
|
||||||
|
if (search == m_mapaTransforms.end())
|
||||||
|
return nullptr;
|
||||||
|
return &search->second;
|
||||||
|
}
|
||||||
|
|
||||||
template <class BRIDGETYPE>
|
template <class BRIDGETYPE>
|
||||||
hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerWorking(const IDType& areaId, int layerIdx) const
|
hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerWorking(const IDType& areaId, int layerIdx) const
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "DNACommon.hpp"
|
#include "DNACommon.hpp"
|
||||||
#include "boo/ThreadLocalPtr.hpp"
|
#include "boo/ThreadLocalPtr.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include "zeus/CMatrix4f.hpp"
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
@ -168,8 +169,10 @@ private:
|
|||||||
ThreadLocalPtr<const nod::Node> m_node;
|
ThreadLocalPtr<const nod::Node> m_node;
|
||||||
std::unordered_map<IDType, std::pair<size_t, EntryType*>> m_uniqueEntries;
|
std::unordered_map<IDType, std::pair<size_t, EntryType*>> m_uniqueEntries;
|
||||||
std::unordered_map<IDType, std::pair<size_t, EntryType*>> m_sharedEntries;
|
std::unordered_map<IDType, std::pair<size_t, EntryType*>> m_sharedEntries;
|
||||||
|
std::unordered_map<IDType, hecl::ProjectPath> m_overrideEntries;
|
||||||
std::unordered_map<IDType, RigPair> m_cmdlRigs;
|
std::unordered_map<IDType, RigPair> m_cmdlRigs;
|
||||||
std::unordered_map<IDType, std::pair<IDType, std::string>> m_cskrCinfToCharacter;
|
std::unordered_map<IDType, std::pair<IDType, std::string>> m_cskrCinfToCharacter;
|
||||||
|
std::unordered_map<IDType, zeus::CMatrix4f> m_mapaTransforms;
|
||||||
|
|
||||||
hecl::ProjectPath getCharacterWorking(const EntryType* entry) const;
|
hecl::ProjectPath getCharacterWorking(const EntryType* entry) const;
|
||||||
|
|
||||||
@ -221,6 +224,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const RigPair* lookupCMDLRigPair(const IDType& id) const;
|
const RigPair* lookupCMDLRigPair(const IDType& id) const;
|
||||||
|
const zeus::CMatrix4f* lookupMAPATransform(const IDType& mapaId) const;
|
||||||
|
|
||||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const;
|
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const;
|
||||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
||||||
|
@ -34,6 +34,7 @@ add_library(DNAMP1
|
|||||||
DNAMP1.hpp DNAMP1.cpp
|
DNAMP1.hpp DNAMP1.cpp
|
||||||
${liblist}
|
${liblist}
|
||||||
PAK.cpp
|
PAK.cpp
|
||||||
|
MLVL.cpp
|
||||||
STRG.hpp STRG.cpp
|
STRG.hpp STRG.cpp
|
||||||
AGSC.cpp
|
AGSC.cpp
|
||||||
CSNG.cpp
|
CSNG.cpp
|
||||||
|
@ -147,13 +147,7 @@ void PAKBridge::build()
|
|||||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||||
|
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
|
||||||
while (areaDeps.name.size() && iswspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#else
|
|
||||||
while (areaDeps.name.size() && isspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (areaDeps.name.empty())
|
if (areaDeps.name.empty())
|
||||||
{
|
{
|
||||||
@ -273,6 +267,63 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const atVec4f BottomRow = {0.f, 0.f, 0.f, 1.f};
|
||||||
|
|
||||||
|
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const
|
||||||
|
{
|
||||||
|
for (const std::pair<UniqueID32, PAK::Entry*>& entry : m_pak.m_idMap)
|
||||||
|
{
|
||||||
|
if (entry.second->type == FOURCC('MLVL'))
|
||||||
|
{
|
||||||
|
MLVL mlvl;
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
|
||||||
|
mlvl.read(rs);
|
||||||
|
}
|
||||||
|
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(entry.second).getParentPath();
|
||||||
|
|
||||||
|
if (mlvl.worldNameId)
|
||||||
|
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _S("!name.yaml"));
|
||||||
|
|
||||||
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
|
{
|
||||||
|
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||||
|
if (area.areaNameId)
|
||||||
|
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _S("!name.yaml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mlvl.worldMap)
|
||||||
|
{
|
||||||
|
const nod::Node* mapNode;
|
||||||
|
const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
|
||||||
|
if (mapEntry)
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
|
||||||
|
u32 magic = rs.readUint32Big();
|
||||||
|
if (magic == 0xDEADF00D)
|
||||||
|
{
|
||||||
|
rs.readUint32Big();
|
||||||
|
u32 count = rs.readUint32Big();
|
||||||
|
for (u32 i=0 ; i<count && i<mlvl.areas.size() ; ++i)
|
||||||
|
{
|
||||||
|
MLVL::Area& areaData = mlvl.areas[i];
|
||||||
|
UniqueID32 mapaId;
|
||||||
|
mapaId.read(rs);
|
||||||
|
addTo[mapaId] = zeus::CMatrix4f(
|
||||||
|
areaData.transformMtx[0],
|
||||||
|
areaData.transformMtx[1],
|
||||||
|
areaData.transformMtx[2],
|
||||||
|
BottomRow).transposed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK& pak, const PAK::Entry& entry)
|
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK& pak, const PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../DNACommon/DNACommon.hpp"
|
#include "../DNACommon/DNACommon.hpp"
|
||||||
#include "PAK.hpp"
|
#include "PAK.hpp"
|
||||||
|
#include "zeus/CMatrix4f.hpp"
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
@ -37,6 +38,10 @@ public:
|
|||||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
||||||
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo,
|
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo,
|
||||||
std::unordered_map<UniqueID32, std::pair<UniqueID32, std::string>>& cskrCinfToAncs) const;
|
std::unordered_map<UniqueID32, std::pair<UniqueID32, std::string>>& cskrCinfToAncs) const;
|
||||||
|
|
||||||
|
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
93
DataSpec/DNAMP1/MLVL.cpp
Normal file
93
DataSpec/DNAMP1/MLVL.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include "MLVL.hpp"
|
||||||
|
#include "SCLY.hpp"
|
||||||
|
|
||||||
|
namespace DataSpec
|
||||||
|
{
|
||||||
|
namespace DNAMP1
|
||||||
|
{
|
||||||
|
|
||||||
|
bool MLVL::Extract(const SpecBase& dataSpec,
|
||||||
|
PAKEntryReadStream& rs,
|
||||||
|
const hecl::ProjectPath& outPath,
|
||||||
|
PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
const PAK::Entry& entry,
|
||||||
|
bool force,
|
||||||
|
hecl::BlenderToken& btok,
|
||||||
|
std::function<void(const hecl::SystemChar*)> fileChanged)
|
||||||
|
{
|
||||||
|
MLVL mlvl;
|
||||||
|
mlvl.read(rs);
|
||||||
|
athena::io::FileWriter writer(outPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
||||||
|
mlvl.toYAMLStream(writer, static_cast<YAMLWriteMemberFn>(&MLVL::writeMeta));
|
||||||
|
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
||||||
|
return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter,
|
||||||
|
entry, force, fileChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const World& wld)
|
||||||
|
{
|
||||||
|
MLVL mlvl = {};
|
||||||
|
athena::io::FileReader reader(inPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
||||||
|
mlvl.fromYAMLStream(reader, static_cast<YAMLReadMemberFn>(&MLVL::readMeta));
|
||||||
|
|
||||||
|
mlvl.magic = 0xDEAFBABE;
|
||||||
|
mlvl.version = 0x11;
|
||||||
|
mlvl.saveWorldId = inPath.ensureAuxInfo(_S(".SAVW"));
|
||||||
|
|
||||||
|
size_t areaIdx = 0;
|
||||||
|
for (const World::Area& area : wld.areas)
|
||||||
|
{
|
||||||
|
if (area.path.getPathType() != hecl::ProjectPath::Type::Directory)
|
||||||
|
continue;
|
||||||
|
hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(),
|
||||||
|
hecl::DirectoryEnumerator::Mode::DirsSorted);
|
||||||
|
bool areaInit = false;
|
||||||
|
|
||||||
|
for (const hecl::DirectoryEnumerator::Entry& e : dEnum)
|
||||||
|
{
|
||||||
|
hecl::SystemString layerName;
|
||||||
|
hecl::SystemChar* endCh = nullptr;
|
||||||
|
hecl::StrToUl(e.m_name.c_str(), &endCh, 0);
|
||||||
|
if (!endCh)
|
||||||
|
layerName = e.m_name;
|
||||||
|
else
|
||||||
|
layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh));
|
||||||
|
|
||||||
|
hecl::ProjectPath objectsPath(area.path, e.m_name + _S("/!objects.yaml"));
|
||||||
|
if (objectsPath.isNone())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SCLY::ScriptLayer layer;
|
||||||
|
{
|
||||||
|
athena::io::FileReader freader(objectsPath.getAbsolutePath());
|
||||||
|
if (!freader.isOpen())
|
||||||
|
continue;
|
||||||
|
if (!BigYAML::ValidateFromYAMLStream<DNAMP1::SCLY::ScriptLayer>(freader))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
athena::io::YAMLDocReader reader;
|
||||||
|
if (!reader.parse(&freader))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
layer.read(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
hecl::ProjectPath defActivePath(area.path, e.m_name + _S("/!defaultactive"));
|
||||||
|
bool active = defActivePath.isNone() ? false : true;
|
||||||
|
|
||||||
|
if (!areaInit)
|
||||||
|
{
|
||||||
|
mlvl.areas.emplace_back();
|
||||||
|
MLVL::Area& areaOut = mlvl.areas.back();
|
||||||
|
areaInit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++areaIdx;
|
||||||
|
}
|
||||||
|
mlvl.memRelayLinkCount = mlvl.memRelayLinks.size();
|
||||||
|
mlvl.areaCount = mlvl.areas.size();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -108,8 +108,6 @@ struct MLVL : BigYAML
|
|||||||
|
|
||||||
void readMeta(athena::io::YAMLDocReader& __dna_docin)
|
void readMeta(athena::io::YAMLDocReader& __dna_docin)
|
||||||
{
|
{
|
||||||
/* worldNameId */
|
|
||||||
__dna_docin.enumerate("worldNameId", worldNameId);
|
|
||||||
/* worldSkyboxId */
|
/* worldSkyboxId */
|
||||||
__dna_docin.enumerate("worldSkyboxId", worldSkyboxId);
|
__dna_docin.enumerate("worldSkyboxId", worldSkyboxId);
|
||||||
/* audioGroupCount squelched */
|
/* audioGroupCount squelched */
|
||||||
@ -119,8 +117,6 @@ struct MLVL : BigYAML
|
|||||||
|
|
||||||
void writeMeta(athena::io::YAMLDocWriter& __dna_docout) const
|
void writeMeta(athena::io::YAMLDocWriter& __dna_docout) const
|
||||||
{
|
{
|
||||||
/* worldNameId */
|
|
||||||
__dna_docout.enumerate("worldNameId", worldNameId);
|
|
||||||
/* worldSkyboxId */
|
/* worldSkyboxId */
|
||||||
__dna_docout.enumerate("worldSkyboxId", worldSkyboxId);
|
__dna_docout.enumerate("worldSkyboxId", worldSkyboxId);
|
||||||
/* audioGroupCount squelched */
|
/* audioGroupCount squelched */
|
||||||
@ -135,16 +131,13 @@ struct MLVL : BigYAML
|
|||||||
const PAK::Entry& entry,
|
const PAK::Entry& entry,
|
||||||
bool force,
|
bool force,
|
||||||
hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok,
|
||||||
std::function<void(const hecl::SystemChar*)> fileChanged)
|
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||||
{
|
|
||||||
MLVL mlvl;
|
using World = hecl::BlenderConnection::DataStream::World;
|
||||||
mlvl.read(rs);
|
|
||||||
athena::io::FileWriter writer(outPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
static bool Cook(const hecl::ProjectPath& outPath,
|
||||||
mlvl.toYAMLStream(writer, static_cast<YAMLWriteMemFn>(&MLVL::writeMeta));
|
const hecl::ProjectPath& inPath,
|
||||||
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
const World& wld);
|
||||||
return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter,
|
|
||||||
entry, force, fileChanged);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||||||
false, false, true);
|
false, false, true);
|
||||||
for (const hecl::DirectoryEnumerator::Entry& ent : dEnum)
|
for (const hecl::DirectoryEnumerator::Entry& ent : dEnum)
|
||||||
{
|
{
|
||||||
hecl::ProjectPath layerScriptPath(areaDirPath, ent.m_name + _S("/objects.yaml"));
|
hecl::ProjectPath layerScriptPath(areaDirPath, ent.m_name + _S("/!objects.yaml"));
|
||||||
if (layerScriptPath.isFile())
|
if (layerScriptPath.isFile())
|
||||||
layerScriptPaths.push_back(std::move(layerScriptPath));
|
layerScriptPaths.push_back(std::move(layerScriptPath));
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ void SCLY::exportToLayerDirectories(const PAK::Entry& entry, PAKRouter<PAKBridge
|
|||||||
fclose(hecl::Fopen(activePath.getAbsolutePath().c_str(), _S("wb")));
|
fclose(hecl::Fopen(activePath.getAbsolutePath().c_str(), _S("wb")));
|
||||||
}
|
}
|
||||||
|
|
||||||
hecl::ProjectPath yamlFile(layerPath, _S("objects.yaml"));
|
hecl::ProjectPath yamlFile(layerPath, _S("!objects.yaml"));
|
||||||
if (force || yamlFile.isNone())
|
if (force || yamlFile.isNone())
|
||||||
{
|
{
|
||||||
athena::io::FileWriter writer(yamlFile.getAbsolutePath());
|
athena::io::FileWriter writer(yamlFile.getAbsolutePath());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "../DNACommon/FONT.hpp"
|
#include "../DNACommon/FONT.hpp"
|
||||||
#include "../DNACommon/DGRP.hpp"
|
#include "../DNACommon/DGRP.hpp"
|
||||||
#include "../DNACommon/ATBL.hpp"
|
#include "../DNACommon/ATBL.hpp"
|
||||||
|
#include "Runtime/GCNTypes.hpp"
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
@ -121,13 +122,7 @@ void PAKBridge::build()
|
|||||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||||
|
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
|
||||||
while (areaDeps.name.size() && iswspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#else
|
|
||||||
while (areaDeps.name.size() && isspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (areaDeps.name.empty())
|
if (areaDeps.name.empty())
|
||||||
{
|
{
|
||||||
@ -209,6 +204,63 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const atVec4f BottomRow = {0.f, 0.f, 0.f, 1.f};
|
||||||
|
|
||||||
|
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const
|
||||||
|
{
|
||||||
|
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry*>& entry : m_pak.m_idMap)
|
||||||
|
{
|
||||||
|
if (entry.second->type == FOURCC('MLVL'))
|
||||||
|
{
|
||||||
|
MLVL mlvl;
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
|
||||||
|
mlvl.read(rs);
|
||||||
|
}
|
||||||
|
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(entry.second).getParentPath();
|
||||||
|
|
||||||
|
if (mlvl.worldNameId)
|
||||||
|
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _S("!name.yaml"));
|
||||||
|
|
||||||
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
|
{
|
||||||
|
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||||
|
if (area.areaNameId)
|
||||||
|
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _S("!name.yaml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mlvl.worldMap)
|
||||||
|
{
|
||||||
|
const nod::Node* mapNode;
|
||||||
|
const DNAMP1::PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
|
||||||
|
if (mapEntry)
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
|
||||||
|
u32 magic = rs.readUint32Big();
|
||||||
|
if (magic == 0xDEADF00D)
|
||||||
|
{
|
||||||
|
rs.readUint32Big();
|
||||||
|
u32 count = rs.readUint32Big();
|
||||||
|
for (u32 i=0 ; i<count && i<mlvl.areas.size() ; ++i)
|
||||||
|
{
|
||||||
|
MLVL::Area& areaData = mlvl.areas[i];
|
||||||
|
UniqueID32 mapaId;
|
||||||
|
mapaId.read(rs);
|
||||||
|
addTo[mapaId] = zeus::CMatrix4f(
|
||||||
|
areaData.transformMtx[0],
|
||||||
|
areaData.transformMtx[1],
|
||||||
|
areaData.transformMtx[2],
|
||||||
|
BottomRow).transposed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK& pak, const DNAMP1::PAK::Entry& entry)
|
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK& pak, const DNAMP1::PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
|
@ -38,6 +38,10 @@ public:
|
|||||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
||||||
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo,
|
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo,
|
||||||
std::unordered_map<UniqueID32, std::pair<UniqueID32, std::string>>& cskrCinfToAncs) const;
|
std::unordered_map<UniqueID32, std::pair<UniqueID32, std::string>>& cskrCinfToAncs) const;
|
||||||
|
|
||||||
|
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "../DNACommon/FONT.hpp"
|
#include "../DNACommon/FONT.hpp"
|
||||||
#include "../DNACommon/FSM2.hpp"
|
#include "../DNACommon/FSM2.hpp"
|
||||||
#include "../DNACommon/DGRP.hpp"
|
#include "../DNACommon/DGRP.hpp"
|
||||||
|
#include "Runtime/GCNTypes.hpp"
|
||||||
|
|
||||||
namespace DataSpec
|
namespace DataSpec
|
||||||
{
|
{
|
||||||
@ -127,13 +128,7 @@ void PAKBridge::build()
|
|||||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||||
|
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
|
||||||
while (areaDeps.name.size() && iswspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#else
|
|
||||||
while (areaDeps.name.size() && isspace(areaDeps.name.back()))
|
|
||||||
areaDeps.name.pop_back();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (areaDeps.name.empty())
|
if (areaDeps.name.empty())
|
||||||
{
|
{
|
||||||
@ -218,6 +213,63 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const atVec4f BottomRow = {0.f, 0.f, 0.f, 1.f};
|
||||||
|
|
||||||
|
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID64, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID64, hecl::ProjectPath>& pathOverrides) const
|
||||||
|
{
|
||||||
|
for (const std::pair<UniqueID64, PAK::Entry*>& entry : m_pak.m_idMap)
|
||||||
|
{
|
||||||
|
if (entry.second->type == FOURCC('MLVL'))
|
||||||
|
{
|
||||||
|
MLVL mlvl;
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
|
||||||
|
mlvl.read(rs);
|
||||||
|
}
|
||||||
|
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(entry.second).getParentPath();
|
||||||
|
|
||||||
|
if (mlvl.worldNameId)
|
||||||
|
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _S("!name.yaml"));
|
||||||
|
|
||||||
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
|
{
|
||||||
|
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||||
|
if (area.areaNameId)
|
||||||
|
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _S("!name.yaml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mlvl.worldMap)
|
||||||
|
{
|
||||||
|
const nod::Node* mapNode;
|
||||||
|
const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
|
||||||
|
if (mapEntry)
|
||||||
|
{
|
||||||
|
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
|
||||||
|
u32 magic = rs.readUint32Big();
|
||||||
|
if (magic == 0xDEADF00D)
|
||||||
|
{
|
||||||
|
rs.readUint32Big();
|
||||||
|
u32 count = rs.readUint32Big();
|
||||||
|
for (u32 i=0 ; i<count && i<mlvl.areas.size() ; ++i)
|
||||||
|
{
|
||||||
|
MLVL::Area& areaData = mlvl.areas[i];
|
||||||
|
UniqueID64 mapaId;
|
||||||
|
mapaId.read(rs);
|
||||||
|
addTo[mapaId] = zeus::CMatrix4f(
|
||||||
|
areaData.transformMtx[0],
|
||||||
|
areaData.transformMtx[1],
|
||||||
|
areaData.transformMtx[2],
|
||||||
|
BottomRow).transposed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK& pak, const PAK::Entry& entry)
|
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK& pak, const PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
|
@ -38,6 +38,10 @@ public:
|
|||||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
|
||||||
std::unordered_map<UniqueID64, std::pair<UniqueID64, UniqueID64>>& addTo,
|
std::unordered_map<UniqueID64, std::pair<UniqueID64, UniqueID64>>& addTo,
|
||||||
std::unordered_map<UniqueID64, std::pair<UniqueID64, std::string>>& cskrCinfToChar) const;
|
std::unordered_map<UniqueID64, std::pair<UniqueID64, std::string>>& cskrCinfToChar) const;
|
||||||
|
|
||||||
|
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||||
|
std::unordered_map<UniqueID64, zeus::CMatrix4f>& addTo,
|
||||||
|
std::unordered_map<UniqueID64, hecl::ProjectPath>& pathOverrides) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::BlenderToken& btok)
|
|||||||
|
|
||||||
const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(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)
|
hecl::BlenderToken& btok) const
|
||||||
{
|
{
|
||||||
if (!checkPathPrefix(path))
|
if (!checkPathPrefix(path))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -20,7 +20,7 @@ struct SpecBase : hecl::Database::IDataSpec
|
|||||||
bool canCook(const hecl::ProjectPath& path, hecl::BlenderToken& btok);
|
bool canCook(const hecl::ProjectPath& path, hecl::BlenderToken& btok);
|
||||||
const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path,
|
const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path,
|
||||||
const hecl::Database::DataSpecEntry* oldEntry,
|
const hecl::Database::DataSpecEntry* oldEntry,
|
||||||
hecl::BlenderToken& btok);
|
hecl::BlenderToken& btok) const;
|
||||||
void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath,
|
void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath,
|
||||||
bool fast, hecl::BlenderToken& btok, FCookProgress progress);
|
bool fast, hecl::BlenderToken& btok, FCookProgress progress);
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ struct SpecBase : hecl::Database::IDataSpec
|
|||||||
virtual const hecl::Database::DataSpecEntry* getOriginalSpec() const=0;
|
virtual const hecl::Database::DataSpecEntry* getOriginalSpec() const=0;
|
||||||
|
|
||||||
/* Basic path check (game directory matching) */
|
/* Basic path check (game directory matching) */
|
||||||
virtual bool checkPathPrefix(const hecl::ProjectPath& path)=0;
|
virtual bool checkPathPrefix(const hecl::ProjectPath& path) const=0;
|
||||||
|
|
||||||
/* Pre-cook handlers */
|
/* Pre-cook handlers */
|
||||||
virtual bool validateYAMLDNAType(athena::io::IStreamReader& fp) const=0;
|
virtual bool validateYAMLDNAType(athena::io::IStreamReader& fp) const=0;
|
||||||
|
@ -324,7 +324,7 @@ struct SpecMP1 : SpecBase
|
|||||||
return m_pakRouter.getWorking(id);
|
return m_pakRouter.getWorking(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPathPrefix(const hecl::ProjectPath& path)
|
bool checkPathPrefix(const hecl::ProjectPath& path) const
|
||||||
{
|
{
|
||||||
return path.getRelativePath().compare(0, 4, _S("MP1/")) == 0;
|
return path.getRelativePath().compare(0, 4, _S("MP1/")) == 0;
|
||||||
}
|
}
|
||||||
@ -449,7 +449,7 @@ struct SpecMP1 : SpecBase
|
|||||||
FCookProgress progress)
|
FCookProgress progress)
|
||||||
{
|
{
|
||||||
BlendStream::World world = ds.compileWorld();
|
BlendStream::World world = ds.compileWorld();
|
||||||
|
DNAMP1::MLVL::Cook(out, in, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
||||||
|
@ -282,7 +282,7 @@ struct SpecMP2 : SpecBase
|
|||||||
return m_pakRouter.getWorking(id);
|
return m_pakRouter.getWorking(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPathPrefix(const hecl::ProjectPath& path)
|
bool checkPathPrefix(const hecl::ProjectPath& path) const
|
||||||
{
|
{
|
||||||
return path.getRelativePath().compare(0, 4, _S("MP2/")) == 0;
|
return path.getRelativePath().compare(0, 4, _S("MP2/")) == 0;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +473,7 @@ struct SpecMP3 : SpecBase
|
|||||||
return m_pakRouter.getWorking(id);
|
return m_pakRouter.getWorking(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPathPrefix(const hecl::ProjectPath& path)
|
bool checkPathPrefix(const hecl::ProjectPath& path) const
|
||||||
{
|
{
|
||||||
return path.getRelativePath().compare(0, 4, _S("MP3/")) == 0;
|
return path.getRelativePath().compare(0, 4, _S("MP3/")) == 0;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveCatalogs(const hecl::Pr
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Read catalog.yaml for .pak directory if exists */
|
/* Read catalog.yaml for .pak directory if exists */
|
||||||
if (level == 1 && !ent.m_name.compare(_S("catalog.yaml")))
|
if (level == 1 && !ent.m_name.compare(_S("!catalog.yaml")))
|
||||||
{
|
{
|
||||||
ReadCatalog(path, nameWriter);
|
ReadCatalog(path, nameWriter);
|
||||||
continue;
|
continue;
|
||||||
@ -228,6 +228,14 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
|||||||
#if DUMP_CACHE_FILL
|
#if DUMP_CACHE_FILL
|
||||||
DumpCacheAdd(pathTag, subPath);
|
DumpCacheAdd(pathTag, subPath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
subPath = asGlob.ensureAuxInfo(_S(".SAVW"));
|
||||||
|
pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
||||||
|
m_tagToPath[pathTag] = subPath;
|
||||||
|
m_pathToTag[subPath.hash()] = pathTag;
|
||||||
|
#if DUMP_CACHE_FILL
|
||||||
|
DumpCacheAdd(pathTag, subPath);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache in-memory */
|
/* Cache in-memory */
|
||||||
@ -264,7 +272,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Read catalog.yaml for .pak directory if exists */
|
/* Read catalog.yaml for .pak directory if exists */
|
||||||
if (level == 1 && !ent.m_name.compare(_S("catalog.yaml")))
|
if (level == 1 && !ent.m_name.compare(_S("!catalog.yaml")))
|
||||||
{
|
{
|
||||||
ReadCatalog(path, nameWriter);
|
ReadCatalog(path, nameWriter);
|
||||||
continue;
|
continue;
|
||||||
|
@ -96,8 +96,12 @@ SObjectTag ProjectResourceFactoryMP1::BuildTagFromPath(const hecl::ProjectPath&
|
|||||||
case hecl::BlenderConnection::BlendType::World:
|
case hecl::BlenderConnection::BlendType::World:
|
||||||
{
|
{
|
||||||
if (path.getAuxInfo().size())
|
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()};
|
return {SBIG('MAPW'), path.hash().val32()};
|
||||||
|
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".SAVW")))
|
||||||
|
return {SBIG('SAVW'), path.hash().val32()};
|
||||||
|
}
|
||||||
return {SBIG('MLVL'), path.hash().val32()};
|
return {SBIG('MLVL'), path.hash().val32()};
|
||||||
}
|
}
|
||||||
case hecl::BlenderConnection::BlendType::MapArea:
|
case hecl::BlenderConnection::BlendType::MapArea:
|
||||||
|
2
hecl
2
hecl
@ -1 +1 @@
|
|||||||
Subproject commit b513ed1ded026067d9ba1ff6908783a0b678ba34
|
Subproject commit 471385dd4a8cad60bd65211f7b17f118d961ef94
|
2
specter
2
specter
@ -1 +1 @@
|
|||||||
Subproject commit f6318521f9f28de34051f8e519f7ba8069501468
|
Subproject commit b9877633b0774cd85557696228bfa8e7505ec153
|
Loading…
x
Reference in New Issue
Block a user