Much more reliable CMDL with CINF/CSKR extract

This commit is contained in:
Jack Andersen 2015-09-05 19:34:30 -10:00
parent 4ede471d1e
commit cf7836fc9a
14 changed files with 151 additions and 82 deletions

View File

@ -26,46 +26,10 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
const HECL::ProjectPath& outPath,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
std::function<void(const HECL::SystemChar*)> fileChanged,
bool force=false)
{
/* Extract character CMDL/CSKR first */
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
ancs.getCharacterResInfo(chResInfo);
for (const auto& info : chResInfo)
{
const NOD::DiscBase::IPartition::Node* node;
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node);
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
if (!conn.createBlend(cmdlPath.getAbsolutePath()))
return false;
HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(*cmdlE));
fileChanged(bestNameView.sys_str().c_str());
typename ANCSDNA::CSKRType cskr;
pakRouter.lookupAndReadDNA(info.cskr, cskr);
typename ANCSDNA::CINFType cinf;
pakRouter.lookupAndReadDNA(info.cinf, cinf);
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
RIGPair rigPair(&cskr, &cinf);
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion>
(conn, rs, pakRouter, *cmdlE, dataspec, &rigPair);
conn.saveBlend();
}
}
}
HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(entry));
fileChanged(bestNameView.sys_str().c_str());
/* Establish ANCS blend */
if (!conn.createBlend(outPath.getAbsolutePath()))

View File

@ -310,7 +310,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR* rp=nullptr)
const RIGPAIR& rp)
{
Header head;
head.read(reader);
@ -411,7 +411,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
"bm = bmesh.new()\n"
"\n", pakRouter.getBestEntryName(entry).c_str());
if (rp)
if (rp.first)
os << "dvert_lay = bm.verts.layers.deform.verify()\n";
/* Link master shader library */
@ -535,8 +535,8 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
atVec3f pos = reader.readVec3fBig();
os.format("vert = bm.verts.new((%f,%f,%f))\n",
pos.vec[0], pos.vec[1], pos.vec[2]);
if (rp)
rp->first->weightVertex(os, *rp->second, i);
if (rp.first)
rp.first->weightVertex(os, *rp.second, i);
}
break;
}
@ -832,8 +832,8 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
"bm.free()\n"
"\n", head.matSetCount);
if (rp)
rp->second->sendVertexGroupsToBlender(os);
if (rp.first)
rp.second->sendVertexGroupsToBlender(os);
return true;
}

View File

@ -106,6 +106,7 @@ public:
using PAKType = typename BRIDGETYPE::PAKType;
using IDType = typename PAKType::IDType;
using EntryType = typename PAKType::Entry;
using RigPair = std::pair<IDType, IDType>;
private:
const SpecBase& m_dataSpec;
const std::vector<BRIDGETYPE>* m_bridges = nullptr;
@ -119,6 +120,7 @@ private:
const NOD::DiscBase::IPartition::Node* m_node = nullptr;
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, RigPair> m_cmdlRigs;
public:
PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
: m_dataSpec(dataSpec),
@ -147,7 +149,10 @@ public:
m_bridgePaths.emplace_back(std::make_pair(HECL::ProjectPath(m_gameWorking, baseName),
HECL::ProjectPath(m_gameCooked, baseName)));
/* Index this PAK */
bridge.build();
/* Add to global enntry lookup */
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
for (const auto& entry : pak.m_idMap)
{
@ -163,6 +168,10 @@ public:
else
m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, entry.second);
}
/* Add RigPairs to global map */
bridge.addCMDLRigPairs(m_cmdlRigs);
progress(++count / bridgesSz);
++bridgeIdx;
}
@ -189,7 +198,7 @@ public:
LogDNACommon.report(LogVisor::FatalError, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()");
}
HECL::ProjectPath getWorking(const typename BRIDGETYPE::PAKType::Entry* entry,
HECL::ProjectPath getWorking(const EntryType* entry,
const ResExtractor<BRIDGETYPE>& extractor) const
{
if (!m_pak)
@ -249,17 +258,17 @@ public:
return HECL::ProjectPath();
}
HECL::ProjectPath getWorking(const typename BRIDGETYPE::PAKType::Entry* entry) const
HECL::ProjectPath getWorking(const EntryType* entry) const
{
return getWorking(entry, BRIDGETYPE::LookupExtractor(*entry));
}
HECL::ProjectPath getWorking(const typename BRIDGETYPE::PAKType::IDType& id) const
HECL::ProjectPath getWorking(const IDType& id) const
{
return getWorking(lookupEntry(id));
}
HECL::ProjectPath getCooked(const typename BRIDGETYPE::PAKType::Entry* entry) const
HECL::ProjectPath getCooked(const EntryType* entry) const
{
if (!m_pak)
LogDNACommon.report(LogVisor::FatalError,
@ -282,13 +291,12 @@ public:
return HECL::ProjectPath();
}
HECL::ProjectPath getCooked(const typename BRIDGETYPE::PAKType::IDType& id) const
HECL::ProjectPath getCooked(const IDType& id) const
{
return getCooked(lookupEntry(id));
}
HECL::SystemString getResourceRelativePath(const typename BRIDGETYPE::PAKType::Entry& a,
const typename BRIDGETYPE::PAKType::IDType& b) const
HECL::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const
{
if (!m_pak)
LogDNACommon.report(LogVisor::FatalError,
@ -305,7 +313,7 @@ public:
return ret;
}
std::string getBestEntryName(const typename BRIDGETYPE::PAKType::Entry& entry) const
std::string getBestEntryName(const EntryType& entry) const
{
if (!m_pak)
LogDNACommon.report(LogVisor::FatalError,
@ -313,7 +321,7 @@ public:
return m_pak->bestEntryName(entry);
}
std::string getBestEntryName(const typename BRIDGETYPE::PAKType::IDType& entry) const
std::string getBestEntryName(const IDType& entry) const
{
if (!m_pak)
LogDNACommon.report(LogVisor::FatalError,
@ -379,7 +387,7 @@ public:
return true;
}
const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const typename BRIDGETYPE::PAKType::IDType& entry,
const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry,
const NOD::DiscBase::IPartition::Node** nodeOut=nullptr) const
{
if (!m_bridges)
@ -387,7 +395,7 @@ public:
"PAKRouter::build() must be called before PAKRouter::lookupEntry()");
if (m_pak)
{
const typename BRIDGETYPE::PAKType::Entry* ent = m_pak->lookupEntry(entry);
const EntryType* ent = m_pak->lookupEntry(entry);
if (ent)
{
if (nodeOut)
@ -397,8 +405,8 @@ public:
}
for (const BRIDGETYPE& bridge : *m_bridges)
{
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
const typename BRIDGETYPE::PAKType::Entry* ent = pak.lookupEntry(entry);
const PAKType& pak = bridge.getPAK();
const EntryType* ent = pak.lookupEntry(entry);
if (ent)
{
if (nodeOut)
@ -413,16 +421,24 @@ public:
}
template <typename DNA>
bool lookupAndReadDNA(const typename BRIDGETYPE::PAKType::IDType& id, DNA& out)
bool lookupAndReadDNA(const IDType& id, DNA& out)
{
const NOD::DiscBase::IPartition::Node* node;
const typename BRIDGETYPE::PAKType::Entry* entry = lookupEntry(id, &node);
const EntryType* entry = lookupEntry(id, &node);
if (!entry)
return false;
PAKEntryReadStream rs = entry->beginReadStream(*node);
out.read(rs);
return true;
}
const RigPair* lookupCMDLRigPair(const IDType& id) const
{
auto search = m_cmdlRigs.find(id);
if (search == m_cmdlRigs.end())
return nullptr;
return &search->second;
}
};
}

View File

@ -371,13 +371,13 @@ struct ANCS : BigYAML
ai.metaAnim.m_anim->gatherPrimitives(out);
}
static bool Extract(const SpecBase& dataSpec,
static bool Extract(const SpecBase&,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
bool force,
std::function<void(const HECL::SystemChar*)> fileChanged)
std::function<void(const HECL::SystemChar*)>)
{
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
@ -402,7 +402,7 @@ struct ANCS : BigYAML
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
(conn, ancs, blendPath, pakRouter, entry, force);
}
}

View File

@ -23,11 +23,25 @@ struct CMDL
bool force,
std::function<void(const HECL::SystemChar*)> fileChanged)
{
/* Check for RigPair */
const PAKRouter<PAKBridge>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
CINF cinf;
CSKR cskr;
std::pair<CSKR*,CINF*> loadRp(nullptr, nullptr);
if (rp)
{
pakRouter.lookupAndReadDNA(rp->first, cskr);
pakRouter.lookupAndReadDNA(rp->second, cinf);
loadRp.first = &cskr;
loadRp.second = &cinf;
}
/* Do extract */
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 2>
(conn, rs, pakRouter, entry, dataSpec);
(conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend();
}
};

View File

@ -190,6 +190,21 @@ void PAKBridge::build()
}
}
void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const
{
for (const std::pair<UniqueID32, PAK::Entry*>& entry : m_pak.m_idMap)
{
if (entry.second->type == FOURCC('ANCS'))
{
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
ANCS ancs;
ancs.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
}
}
}
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
{
switch (entry.type)
@ -199,9 +214,9 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
case SBIG('TXTR'):
return {TXTR::Extract, nullptr, {_S(".png")}};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 2};
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
case SBIG('ANCS'):
return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 1};
return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 2};
case SBIG('MLVL'):
return {MLVL::Extract, nullptr, {_S(".yaml")}};
}

View File

@ -35,12 +35,14 @@ public:
PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node);
void build();
static ResExtractor<PAKBridge> LookupExtractor(const PAK::Entry& entry);
inline const std::string& getName() const {return m_node.getName();}
inline const HECL::SystemString& getLevelString() const {return m_levelString;}
const std::string& getName() const {return m_node.getName();}
const HECL::SystemString& getLevelString() const {return m_levelString;}
typedef PAK PAKType;
inline const PAKType& getPAK() const {return m_pak;}
inline const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}
using PAKType = PAK;
const PAKType& getPAK() const {return m_pak;}
const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}
void addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const;
};
}

View File

@ -208,13 +208,13 @@ struct ANCS : BigYAML
ai.metaAnim.m_anim->gatherPrimitives(out);
}
static bool Extract(const SpecBase& dataSpec,
static bool Extract(const SpecBase&,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
bool force,
std::function<void(const HECL::SystemChar*)> fileChanged)
std::function<void(const HECL::SystemChar*)>)
{
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
@ -239,7 +239,7 @@ struct ANCS : BigYAML
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
(conn, ancs, blendPath, pakRouter, entry, force);
}
}

View File

@ -20,14 +20,28 @@ struct CMDL
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
bool force,
std::function<void(const HECL::SystemChar*)> fileChanged)
bool,
std::function<void(const HECL::SystemChar*)>)
{
/* Check for RigPair */
const PAKRouter<PAKBridge>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
CINF cinf;
CSKR cskr;
std::pair<CSKR*,CINF*> loadRp(nullptr, nullptr);
if (rp)
{
pakRouter.lookupAndReadDNA(rp->first, cskr);
pakRouter.lookupAndReadDNA(rp->second, cinf);
loadRp.first = &cskr;
loadRp.second = &cinf;
}
/* Do extract */
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 4>
(conn, rs, pakRouter, entry, dataSpec);
(conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend();
}
};

View File

@ -197,6 +197,21 @@ void PAKBridge::build()
}
}
void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const
{
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry*>& entry : m_pak.m_idMap)
{
if (entry.second->type == FOURCC('ANCS'))
{
PAKEntryReadStream rs = entry.second->beginReadStream(m_node);
ANCS ancs;
ancs.read(rs);
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
addTo[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
}
}
}
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& entry)
{
switch (entry.type)
@ -206,9 +221,9 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
case SBIG('TXTR'):
return {TXTR::Extract, nullptr, {_S(".png")}};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 2};
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
case SBIG('ANCS'):
return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 1};
return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 2};
}
return {};
}

View File

@ -35,12 +35,15 @@ public:
PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node);
void build();
static ResExtractor<PAKBridge> LookupExtractor(const DNAMP1::PAK::Entry& entry);
inline const std::string& getName() const {return m_node.getName();}
inline const HECL::SystemString& getLevelString() const {return m_levelString;}
const std::string& getName() const {return m_node.getName();}
const HECL::SystemString& getLevelString() const {return m_levelString;}
typedef DNAMP1::PAK PAKType;
inline const PAKType& getPAK() const {return m_pak;}
inline const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}};
using PAKType = DNAMP1::PAK;
const PAKType& getPAK() const {return m_pak;}
const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}
void addCMDLRigPairs(std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const;
};
}
}

View File

@ -23,11 +23,25 @@ struct CMDL
bool force,
std::function<void(const HECL::SystemChar*)> fileChanged)
{
/* Check for RigPair */
const PAKRouter<PAKBridge>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
CINF cinf;
CSKR cskr;
std::pair<CSKR*,CINF*> loadRp(nullptr, nullptr);
if (rp)
{
pakRouter.lookupAndReadDNA(rp->first, cskr);
pakRouter.lookupAndReadDNA(rp->second, cinf);
loadRp.first = &cskr;
loadRp.second = &cinf;
}
/* Do extract */
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 5>
(conn, rs, pakRouter, entry, dataSpec);
(conn, rs, pakRouter, entry, dataSpec, loadRp);
return conn.saveBlend();
}
};

View File

@ -53,6 +53,16 @@ void PAKBridge::build()
{
}
void PAKBridge::addCMDLRigPairs(std::unordered_map<UniqueID64, std::pair<UniqueID64, UniqueID64>>& addTo) const
{
for (const std::pair<UniqueID64, PAK::Entry*>& entry : m_pak.m_idMap)
{
if (entry.second->type == FOURCC('CHAR'))
{
}
}
}
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
{
switch (entry.type)

View File

@ -28,6 +28,8 @@ public:
typedef PAK PAKType;
inline const PAKType& getPAK() const {return m_pak;}
inline const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}
void addCMDLRigPairs(std::unordered_map<UniqueID64, std::pair<UniqueID64, UniqueID64>>& addTo) const;
};
}