Initial migration to URDE-hashed object tags

This commit is contained in:
Jack Andersen 2016-02-29 17:08:25 -10:00
parent c1af78e7ed
commit 2a614215c8
14 changed files with 189 additions and 283 deletions

View File

@ -21,7 +21,6 @@ add_library(DNACommon
ParticleCommon.cpp ParticleCommon.cpp
DeafBabe.hpp DeafBabe.hpp
BabeDead.hpp BabeDead.hpp
NamedResourceCatalog.hpp
Tweaks/ITweakGame.hpp Tweaks/ITweakGame.hpp
Tweaks/ITweakParticle.hpp Tweaks/ITweakParticle.hpp
Tweaks/ITweakPlayer.hpp Tweaks/ITweakPlayer.hpp

View File

@ -1,9 +1,11 @@
#include "DNACommon.hpp" #include "DNACommon.hpp"
#include "PAK.hpp"
namespace DataSpec namespace DataSpec
{ {
LogVisor::LogModule LogDNACommon("Retro::DNACommon"); LogVisor::LogModule LogDNACommon("Retro::DNACommon");
SpecBase* g_curSpec = nullptr; SpecBase* g_curSpec = nullptr;
PAKRouterBase* g_PakRouter = nullptr;
} }

View File

@ -13,6 +13,7 @@ namespace DataSpec
extern LogVisor::LogModule LogDNACommon; extern LogVisor::LogModule LogDNACommon;
extern SpecBase* g_curSpec; extern SpecBase* g_curSpec;
extern class PAKRouterBase* g_PakRouter;
/* This comes up a great deal */ /* This comes up a great deal */
typedef Athena::io::DNA<Athena::BigEndian> BigDNA; typedef Athena::io::DNA<Athena::BigEndian> BigDNA;
@ -44,6 +45,64 @@ public:
}; };
using FourCC = HECL::FourCC; using FourCC = HECL::FourCC;
class UniqueID32;
class UniqueID64;
class UniqueID128;
/** Common virtual interface for runtime ambiguity resolution */
class PAKRouterBase
{
protected:
const SpecBase& m_dataSpec;
public:
PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {}
HECL::Database::Project& getProject() const {return m_dataSpec.getProject();}
virtual HECL::ProjectPath getWorking(const UniqueID32&) const
{
LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID32 specialization");
return HECL::ProjectPath();
}
virtual HECL::ProjectPath getWorking(const UniqueID64&) const
{
LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID64 specialization");
return HECL::ProjectPath();
}
virtual HECL::ProjectPath getWorking(const UniqueID128&) const
{
LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID128 specialization");
return HECL::ProjectPath();
}
};
/** Globally-accessed manager allowing UniqueID* classes to directly
* lookup destination paths of resources */
class UniqueIDBridge
{
friend class UniqueID32;
friend class UniqueID64;
public:
template <class IDType>
static HECL::ProjectPath TranslatePakIdToPath(const IDType& id)
{
if (!g_PakRouter)
LogDNACommon.report(LogVisor::FatalError,
"UniqueIDBridge::setPakRouter must be called before translatePakIdToPath");
HECL::ProjectPath res = g_PakRouter->getWorking(id);
if (!res)
LogDNACommon.report(LogVisor::FatalError,
"unable to translate %s to path", id.toString().c_str());
return res;
}
static HECL::ProjectPath MakePathFromString(const std::string& str)
{
return HECL::ProjectPath(g_PakRouter->getProject(), str);
}
template <class IDType>
static void TransformOldHashToNewHash(IDType& id)
{
id = TranslatePakIdToPath(id);
}
};
/** PAK 32-bit Unique ID */ /** PAK 32-bit Unique ID */
class UniqueID32 : public BigYAML class UniqueID32 : public BigYAML
@ -57,9 +116,13 @@ public:
void write(Athena::io::IStreamWriter& writer) const void write(Athena::io::IStreamWriter& writer) const
{writer.writeUint32Big(m_id);} {writer.writeUint32Big(m_id);}
void read(Athena::io::YAMLDocReader& reader) void read(Athena::io::YAMLDocReader& reader)
{m_id = reader.readUint32(nullptr);} {
*this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
}
void write(Athena::io::YAMLDocWriter& writer) const void write(Athena::io::YAMLDocWriter& writer) const
{writer.writeUint32(nullptr, m_id);} {
writer.writeString(nullptr, UniqueIDBridge::TranslatePakIdToPath(*this).getRelativePathUTF8());
}
size_t binarySize(size_t __isz) const size_t binarySize(size_t __isz) const
{return __isz + 4;} {return __isz + 4;}
@ -110,9 +173,13 @@ public:
void write(Athena::io::IStreamWriter& writer) const void write(Athena::io::IStreamWriter& writer) const
{writer.writeUint64Big(m_id);} {writer.writeUint64Big(m_id);}
void read(Athena::io::YAMLDocReader& reader) void read(Athena::io::YAMLDocReader& reader)
{m_id = reader.readUint64(nullptr);} {
*this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
}
void write(Athena::io::YAMLDocWriter& writer) const void write(Athena::io::YAMLDocWriter& writer) const
{writer.writeUint64(nullptr, m_id);} {
writer.writeString(nullptr, UniqueIDBridge::TranslatePakIdToPath(*this).getRelativePathUTF8());
}
size_t binarySize(size_t __isz) const size_t binarySize(size_t __isz) const
{return __isz + 8;} {return __isz + 8;}
@ -186,21 +253,22 @@ public:
} }
void read(Athena::io::YAMLDocReader& reader) void read(Athena::io::YAMLDocReader& reader)
{ {
std::string str = reader.readString(nullptr); *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
while (str.size() < 32)
str += '0';
std::string hStr(str.begin(), str.begin() + 16);
std::string lStr(str.begin() + 16, str.begin() + 32);
m_id[0] = strtoull(hStr.c_str(), nullptr, 16);
m_id[1] = strtoull(lStr.c_str(), nullptr, 16);
} }
void write(Athena::io::YAMLDocWriter& writer) const void write(Athena::io::YAMLDocWriter& writer) const
{ {
writer.writeString(nullptr, toString().c_str()); writer.writeString(nullptr, UniqueIDBridge::TranslatePakIdToPath(*this).getRelativePathUTF8());
} }
size_t binarySize(size_t __isz) const size_t binarySize(size_t __isz) const
{return __isz + 16;} {return __isz + 16;}
UniqueID128& operator=(const HECL::ProjectPath& path)
{
m_id[0] = path.hash().val64();
m_id[1] = 0;
return *this;
}
bool operator!=(const UniqueID128& other) const bool operator!=(const UniqueID128& other) const
{ {
#if __SSE__ #if __SSE__
@ -234,61 +302,6 @@ public:
static constexpr size_t BinarySize() {return 16;} static constexpr size_t BinarySize() {return 16;}
}; };
/** Class that automatically converts between hash and path for DNA usage */
template <class IDTYPE>
class PAKPath : public BigYAML
{
HECL::ProjectPath m_path;
IDTYPE m_id;
public:
HECL::ProjectPath getPath() const
{
if (m_path)
return m_path;
if (!g_curSpec)
LogDNACommon.report(LogVisor::FatalError, "current DataSpec not set for PAKPath");
if (m_id)
return g_curSpec->getWorking(m_id);
return HECL::ProjectPath();
}
operator HECL::ProjectPath() const {return getPath();}
operator const IDTYPE&() const {return m_id;}
Delete _d;
void read(Athena::io::IStreamReader& reader)
{m_id.read(reader);}
void write(Athena::io::IStreamWriter& writer) const
{m_id.write(writer);}
void read(Athena::io::YAMLDocReader& reader)
{
if (!g_curSpec)
LogDNACommon.report(LogVisor::FatalError, "current DataSpec not set for PAKPath");
std::string path = reader.readString(nullptr);
if (path.empty())
{
m_path.clear();
m_id.clear();
return;
}
m_path.assign(g_curSpec->getProject(), path);
m_id = m_path;
}
void write(Athena::io::YAMLDocWriter& writer) const
{
if (m_path)
{
writer.writeString(nullptr, m_path.getRelativePathUTF8());
return;
}
writer.writeString(nullptr, getPath().getRelativePathUTF8());
}
size_t binarySize(size_t __isz) const
{return __isz + IDTYPE::BinarySize();}
};
using PAKPath32 = PAKPath<UniqueID32>;
using PAKPath64 = PAKPath<UniqueID64>;
/** Word Bitmap reader/writer */ /** Word Bitmap reader/writer */
class WordBitmap class WordBitmap
{ {

View File

@ -24,14 +24,6 @@ bool ReadMLVLToBlender(HECL::BlenderConnection& conn,
if (!force && mlvlPath.getPathType() == HECL::ProjectPath::Type::File) if (!force && mlvlPath.getPathType() == HECL::ProjectPath::Type::File)
return true; return true;
/* Link Skybox CMDL */
const typename PAKRouter::EntryType* skyboxEntry = pakRouter.lookupEntry(mlvl.worldSkyboxId);
if (skyboxEntry)
{
HECL::ProjectPath skyboxPath = pakRouter.getWorking(skyboxEntry);
HECL::ProjectPath(outPath.getParentPath(), _S("!skybox.blend")).makeLinkTo(skyboxPath);
}
/* Create World Blend */ /* Create World Blend */
if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::BlendType::World)) if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::BlendType::World))
return false; return false;

View File

@ -1,132 +0,0 @@
#ifndef __DNACOMMON_NAMEDRESOURCECATALOG_HPP__
#define __DNACOMMON_NAMEDRESOURCECATALOG_HPP__
#include "DNACommon.hpp"
namespace DataSpec
{
template <class IDType>
struct NamedResourceCatalog : BigYAML
{
Delete _d;
Value<atUint32> namedResCount = 0;
struct NamedResource : BigYAML
{
Delete _d;
DNAFourCC type;
String<-1> name;
IDType uid;
void read(Athena::io::IStreamReader& __dna_reader)
{
/* type */
type.read(__dna_reader);
/* name */
name = __dna_reader.readString(-1);
/* uid */
uid.read(__dna_reader);
}
void write(Athena::io::IStreamWriter& __dna_writer) const
{
/* type */
type.write(__dna_writer);
/* name */
__dna_writer.writeString(name, -1);
/* uid */
uid.write(__dna_writer);
}
void read(Athena::io::YAMLDocReader& __dna_docin)
{
/* type */
__dna_docin.enumerate("type", type);
/* name */
name = __dna_docin.readString("name");
/* uid */
__dna_docin.enumerate("uid", uid);
}
void write(Athena::io::YAMLDocWriter& __dna_docout) const
{
/* type */
__dna_docout.enumerate("type", type);
/* name */
__dna_docout.writeString("name", name);
/* uid */
__dna_docout.enumerate("uid", uid);
}
static const char* DNAType() { return "DataSpec::DNACommon::NameResourceCatalog::NamedResource"; }
size_t binarySize(size_t __isz) const
{
__isz = type.binarySize(__isz);
__isz += name.size() + 1;
__isz = uid.binarySize(__isz);
return __isz;
}
};
Vector<NamedResource, DNA_COUNT(namedResCount)> namedResources;
void read(Athena::io::IStreamReader& __dna_reader)
{
/* namedResCount */
namedResCount = __dna_reader.readUint32Big();
/* namedResources */
__dna_reader.enumerate(namedResources, namedResCount);
}
void write(Athena::io::IStreamWriter& __dna_writer) const
{
/* namedResCount */
__dna_writer.writeUint32Big(namedResCount);
/* namedResources */
__dna_writer.enumerate(namedResources);
}
void read(Athena::io::YAMLDocReader& __dna_docin)
{
/* namedResCount */
namedResCount = __dna_docin.readUint32("namedResCount");
/* namedResources */
__dna_docin.enumerate("namedResources", namedResources, namedResCount);
}
void write(Athena::io::YAMLDocWriter& __dna_docout) const
{
/* namedResCount */
__dna_docout.writeUint32("namedResCount", namedResCount);
/* namedResources */
__dna_docout.enumerate("namedResources", namedResources);
}
static const char* DNAType()
{
return "DataSpec::DNACommon::NameResourceCatalog";
}
size_t binarySize(size_t __isz) const
{
__isz = __EnumerateSize(__isz, namedResources);
return __isz + 4;
}
void addNamedResource(const std::string& name, const IDType& id, const DNAFourCC& type)
{
NamedResource res;
res.type = type;
res.name = name;
res.uid = id;
auto it = std::find_if(namedResources.begin(), namedResources.end(), [res](const NamedResource& a)->bool
{ return (a.name == res.name && a.type == res.type && a.uid == res.uid); });
if (it != namedResources.end())
return;
namedResources.push_back(std::move(res));
namedResCount++;
}
};
}
#endif // NAMEDRESOURCECATALOG_HPP

View File

@ -2,12 +2,11 @@
#define __DNACOMMON_PAK_HPP__ #define __DNACOMMON_PAK_HPP__
#include "DNACommon.hpp" #include "DNACommon.hpp"
#include "NamedResourceCatalog.hpp"
namespace DataSpec namespace DataSpec
{ {
/* PAK entry stream reader */ /** PAK entry stream reader */
class PAKEntryReadStream : public Athena::io::IStreamReader class PAKEntryReadStream : public Athena::io::IStreamReader
{ {
std::unique_ptr<atUint8[]> m_buf; std::unique_ptr<atUint8[]> m_buf;
@ -197,7 +196,7 @@ struct UniqueResult
template <class BRIDGETYPE> template <class BRIDGETYPE>
class PAKRouter; class PAKRouter;
/* Resource extractor type */ /** Resource extractor type */
template <class PAKBRIDGE> template <class PAKBRIDGE>
struct ResExtractor struct ResExtractor
{ {
@ -211,7 +210,7 @@ struct ResExtractor
typename PAKBRIDGE::PAKType::Entry&)> func_name; typename PAKBRIDGE::PAKType::Entry&)> func_name;
}; };
/* Level hierarchy representation */ /** Level hierarchy representation */
template <class IDType> template <class IDType>
struct Level struct Level
{ {
@ -231,9 +230,9 @@ struct Level
std::unordered_map<IDType, Area> areas; std::unordered_map<IDType, Area> areas;
}; };
/* PAKRouter (for detecting shared entry locations) */ /** PAKRouter (for detecting shared entry locations) */
template <class BRIDGETYPE> template <class BRIDGETYPE>
class PAKRouter class PAKRouter : public PAKRouterBase
{ {
public: public:
using PAKType = typename BRIDGETYPE::PAKType; using PAKType = typename BRIDGETYPE::PAKType;
@ -241,8 +240,6 @@ public:
using EntryType = typename PAKType::Entry; using EntryType = typename PAKType::Entry;
using RigPair = std::pair<IDType, IDType>; using RigPair = std::pair<IDType, IDType>;
private: private:
NamedResourceCatalog<IDType> m_catalog;
const SpecBase& m_dataSpec;
const std::vector<BRIDGETYPE>* m_bridges = nullptr; const std::vector<BRIDGETYPE>* m_bridges = nullptr;
std::vector<std::pair<HECL::ProjectPath,HECL::ProjectPath>> m_bridgePaths; std::vector<std::pair<HECL::ProjectPath,HECL::ProjectPath>> m_bridgePaths;
size_t m_curBridgeIdx = 0; size_t m_curBridgeIdx = 0;
@ -257,12 +254,13 @@ private:
std::unordered_map<IDType, RigPair> m_cmdlRigs; std::unordered_map<IDType, RigPair> m_cmdlRigs;
public: public:
PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked) PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
: m_dataSpec(dataSpec), : PAKRouterBase(dataSpec),
m_gameWorking(working), m_gameCooked(cooked), m_gameWorking(working), m_gameCooked(cooked),
m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {} m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {}
void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress) void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress)
{ {
g_PakRouter = this;
m_bridges = &bridges; m_bridges = &bridges;
m_bridgePaths.clear(); m_bridgePaths.clear();
@ -311,21 +309,29 @@ public:
/* Add RigPairs to global map */ /* Add RigPairs to global map */
bridge.addCMDLRigPairs(*this, m_cmdlRigs); bridge.addCMDLRigPairs(*this, m_cmdlRigs);
/* Add named resources to catalog */
for (const auto& namedEntry : pak.m_nameEntries)
m_catalog.addNamedResource(namedEntry.name, namedEntry.id, namedEntry.type);
progress(++count / bridgesSz); progress(++count / bridgesSz);
++bridgeIdx; ++bridgeIdx;
} }
HECL::SystemString catalogPath = HECL::ProjectPath(m_gameCooked, "catalog.yaml").getAbsolutePath(); /* Add named resources to catalog YAML */
FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("wb")); Athena::io::YAMLDocWriter catalogWriter(nullptr);
if (catalog) for (BRIDGETYPE& bridge : bridges)
{ {
m_catalog.toYAMLFile(catalog); const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
fclose(catalog); for (const auto& namedEntry : pak.m_nameEntries)
{
catalogWriter.enterSubRecord(namedEntry.name.c_str());
catalogWriter.writeString(nullptr, getWorking(namedEntry.id).getRelativePathUTF8().c_str());
catalogWriter.leaveSubRecord();
}
} }
/* Write catalog */
HECL::SystemString catalogPath = HECL::ProjectPath(m_gameWorking, "catalog.yaml").getAbsolutePath();
FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("w"));
yaml_emitter_set_output_file(catalogWriter.getEmitter(), catalog);
catalogWriter.finish();
fclose(catalog);
} }
void enterPAKBridge(const BRIDGETYPE& pakBridge) void enterPAKBridge(const BRIDGETYPE& pakBridge)
@ -347,6 +353,7 @@ public:
++bridgeIdx; ++bridgeIdx;
} }
LogDNACommon.report(LogVisor::FatalError, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"); LogDNACommon.report(LogVisor::FatalError, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()");
g_PakRouter = this;
} }
HECL::ProjectPath getWorking(const EntryType* entry, HECL::ProjectPath getWorking(const EntryType* entry,
@ -362,11 +369,11 @@ public:
{ {
const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first;
pakPath.makeDir(); pakPath.makeDir();
#if HECL_UCS2 #if HECL_UCS2
HECL::SystemString entName = HECL::UTF8ToWide(m_pak->bestEntryName(*entry)); HECL::SystemString entName = HECL::UTF8ToWide(m_pak->bestEntryName(*entry));
#else #else
HECL::SystemString entName = m_pak->bestEntryName(*entry); HECL::SystemString entName = m_pak->bestEntryName(*entry);
#endif #endif
if (extractor.fileExts[0] && !extractor.fileExts[1]) if (extractor.fileExts[0] && !extractor.fileExts[1])
entName += extractor.fileExts[0]; entName += extractor.fileExts[0];
return HECL::ProjectPath(pakPath, entName); return HECL::ProjectPath(pakPath, entName);
@ -393,7 +400,6 @@ public:
if (sharedSearch != m_sharedEntries.end()) if (sharedSearch != m_sharedEntries.end())
{ {
const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first;
HECL::ProjectPath uniquePathPre = entry->unique.uniquePath(pakPath);
#if HECL_UCS2 #if HECL_UCS2
HECL::SystemString entBase = HECL::UTF8ToWide(m_pak->bestEntryName(*entry)); HECL::SystemString entBase = HECL::UTF8ToWide(m_pak->bestEntryName(*entry));
#else #else
@ -403,24 +409,6 @@ public:
if (extractor.fileExts[0] && !extractor.fileExts[1]) if (extractor.fileExts[0] && !extractor.fileExts[1])
entName += extractor.fileExts[0]; entName += extractor.fileExts[0];
HECL::ProjectPath sharedPath(m_sharedWorking, entName); HECL::ProjectPath sharedPath(m_sharedWorking, entName);
HECL::ProjectPath uniquePath(uniquePathPre, entName);
if (extractor.func_a || extractor.func_b)
{
if (extractor.fileExts[0] && !extractor.fileExts[1])
uniquePath.makeLinkTo(sharedPath);
else
{
for (int e=0 ; e<4 ; ++e)
{
if (!extractor.fileExts[e])
break;
HECL::SystemString entName = entBase + extractor.fileExts[e];
HECL::ProjectPath sharedPath(m_sharedWorking, entName);
HECL::ProjectPath uniquePath(uniquePathPre, entName);
uniquePath.makeLinkTo(sharedPath);
}
}
}
m_sharedWorking.makeDir(); m_sharedWorking.makeDir();
return sharedPath; return sharedPath;
} }
@ -527,13 +515,13 @@ public:
ResExtractor<BRIDGETYPE> extractor = BRIDGETYPE::LookupExtractor(*item); ResExtractor<BRIDGETYPE> extractor = BRIDGETYPE::LookupExtractor(*item);
if (extractor.weight != w) if (extractor.weight != w)
continue; continue;
std::string bestName = getBestEntryName(*item); std::string bestName = getBestEntryName(*item);
HECL::SystemStringView bestNameView(bestName); HECL::SystemStringView bestNameView(bestName);
float thisFac = ++count / fsz; float thisFac = ++count / fsz;
progress(bestNameView.sys_str().c_str(), thisFac); progress(bestNameView.sys_str().c_str(), thisFac);
/* TODO: Position after extracted item */ /* Extract first, so they start out invalid */
HECL::ProjectPath cooked = getCooked(item); HECL::ProjectPath cooked = getCooked(item);
if (force || cooked.getPathType() == HECL::ProjectPath::Type::None) if (force || cooked.getPathType() == HECL::ProjectPath::Type::None)
{ {

View File

@ -60,7 +60,7 @@ struct SpecBase : HECL::Database::IDataSpec
virtual HECL::ProjectPath getWorking(class UniqueID64&) {return HECL::ProjectPath();} virtual HECL::ProjectPath getWorking(class UniqueID64&) {return HECL::ProjectPath();}
/* Project accessor */ /* Project accessor */
HECL::Database::Project& getProject() {return m_project;} HECL::Database::Project& getProject() const {return m_project;}
SpecBase(HECL::Database::Project& project); SpecBase(HECL::Database::Project& project);
protected: protected:

View File

@ -19,10 +19,24 @@ ProjectResourceFactory::ProjectResourceFactory()
void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::ProjectDataSpec &spec) void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::ProjectDataSpec &spec)
{ {
m_resPaths.clear(); m_tagToPath.clear();
m_namedResources.clear(); m_catalogNameToTag.clear();
HECL::SystemString catalogPath = HECL::ProjectPath(spec.cookedPath, HECL::SystemString(spec.spec.m_name) + _S("/catalog.yaml")).getAbsolutePath(); HECL::SystemString catalogPath = HECL::ProjectPath(spec.cookedPath, HECL::SystemString(spec.spec.m_name) + _S("/catalog.yaml")).getAbsolutePath();
FILE* catalogFile = HECL::Fopen(catalogPath.c_str(), _S("r")); FILE* catalogFile = HECL::Fopen(catalogPath.c_str(), _S("r"));
Athena::io::YAMLDocReader reader;
yaml_parser_set_input_file(reader.getParser(), catalogFile);
reader.parse();
const Athena::io::YAMLNode* catalogRoot = reader.getRootNode();
if (catalogRoot)
{
m_catalogNameToPath.reserve(catalogRoot->m_mapChildren.size());
for (const std::pair<std::string, std::unique_ptr<Athena::io::YAMLNode>>& ch : catalogRoot->m_mapChildren)
{
if (ch.second->m_type == YAML_SCALAR_NODE)
m_catalogNameToPath[ch.first] = HECL::ProjectPath(spec.cookedPath, HECL::SystemString(ch.second->m_scalarString));
}
}
if (!HECL::StrCmp(spec.spec.m_name, _S("MP3"))) if (!HECL::StrCmp(spec.spec.m_name, _S("MP3")))
{ {
DataSpec::NamedResourceCatalog<DataSpec::UniqueID64> catalog; DataSpec::NamedResourceCatalog<DataSpec::UniqueID64> catalog;
@ -42,8 +56,8 @@ void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::Proje
std::unique_ptr<pshag::IObj> ProjectResourceFactory::Build(const pshag::SObjectTag& tag, std::unique_ptr<pshag::IObj> ProjectResourceFactory::Build(const pshag::SObjectTag& tag,
const pshag::CVParamTransfer& paramXfer) const pshag::CVParamTransfer& paramXfer)
{ {
auto search = m_resPaths.find(tag); auto search = m_tagToPath.find(tag);
if (search == m_resPaths.end()) if (search == m_tagToPath.end())
return {}; return {};
fprintf(stderr, "Loading resource %s\n", search->second.getRelativePath().c_str()); fprintf(stderr, "Loading resource %s\n", search->second.getRelativePath().c_str());
@ -68,8 +82,8 @@ void ProjectResourceFactory::CancelBuild(const pshag::SObjectTag&)
bool ProjectResourceFactory::CanBuild(const pshag::SObjectTag& tag) bool ProjectResourceFactory::CanBuild(const pshag::SObjectTag& tag)
{ {
auto search = m_resPaths.find(tag); auto search = m_tagToPath.find(tag);
if (search == m_resPaths.end()) if (search == m_tagToPath.end())
return false; return false;
Athena::io::FileReader fr(search->second.getAbsolutePath(), 32 * 1024, false); Athena::io::FileReader fr(search->second.getAbsolutePath(), 32 * 1024, false);
@ -81,9 +95,9 @@ bool ProjectResourceFactory::CanBuild(const pshag::SObjectTag& tag)
const pshag::SObjectTag* ProjectResourceFactory::GetResourceIdByName(const char* name) const const pshag::SObjectTag* ProjectResourceFactory::GetResourceIdByName(const char* name) const
{ {
if (m_namedResources.find(name) == m_namedResources.end()) if (m_catalogNameToTag.find(name) == m_catalogNameToTag.end())
return nullptr; return nullptr;
const pshag::SObjectTag& tag = m_namedResources.at(name); const pshag::SObjectTag& tag = m_catalogNameToTag.at(name);
return &tag; return &tag;
} }

View File

@ -3,15 +3,15 @@
#include "Runtime/IFactory.hpp" #include "Runtime/IFactory.hpp"
#include "Runtime/CFactoryMgr.hpp" #include "Runtime/CFactoryMgr.hpp"
#include "DataSpec/DNACommon/NamedResourceCatalog.hpp"
namespace URDE namespace URDE
{ {
class ProjectResourceFactory : public pshag::IFactory class ProjectResourceFactory : public pshag::IFactory
{ {
std::unordered_map<pshag::SObjectTag, HECL::ProjectPath> m_resPaths; std::unordered_map<pshag::SObjectTag, HECL::ProjectPath> m_tagToPath;
std::unordered_map<std::string, pshag::SObjectTag> m_namedResources; std::unordered_map<std::string, pshag::SObjectTag> m_catalogNameToTag;
std::unordered_map<std::string, HECL::ProjectPath> m_catalogNameToPath;
pshag::CFactoryMgr m_factoryMgr; pshag::CFactoryMgr m_factoryMgr;
template <class IDType> template <class IDType>
void RecursiveAddDirObjects(const HECL::ProjectPath& path, const DataSpec::NamedResourceCatalog<IDType>& catalog) void RecursiveAddDirObjects(const HECL::ProjectPath& path, const DataSpec::NamedResourceCatalog<IDType>& catalog)
@ -34,8 +34,8 @@ class ProjectResourceFactory : public pshag::IFactory
if (id) if (id)
{ {
pshag::SObjectTag objTag = {HECL::FourCC(entu8.c_str()), id}; pshag::SObjectTag objTag = {HECL::FourCC(entu8.c_str()), id};
if (m_resPaths.find(objTag) == m_resPaths.end()) if (m_tagToPath.find(objTag) == m_tagToPath.end())
m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name); m_tagToPath[objTag] = HECL::ProjectPath(path, ent.m_name);
} }
} }
else else
@ -50,8 +50,8 @@ class ProjectResourceFactory : public pshag::IFactory
const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& nr = *it; const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& nr = *it;
pshag::SObjectTag objTag = GetTag<IDType>(nr); pshag::SObjectTag objTag = GetTag<IDType>(nr);
m_namedResources[nr.name.c_str()] = objTag; m_catalogNameToTag[nr.name.c_str()] = objTag;
m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name); m_tagToPath[objTag] = HECL::ProjectPath(path, ent.m_name);
} }
} }
} }

View File

@ -16,16 +16,17 @@ bool ResourceBrowser::navigateToPath(const HECL::ProjectPath& pathIn)
HECL::DirectoryEnumerator dEnum(m_path.getAbsolutePath(), HECL::DirectoryEnumerator dEnum(m_path.getAbsolutePath(),
HECL::DirectoryEnumerator::Mode::DirsThenFilesSorted, HECL::DirectoryEnumerator::Mode::DirsThenFilesSorted,
m_state.sortColumn==State::SortColumn::Size, m_state.sortColumn==State::SortColumn::Size,
m_state.sortDir==Specter::SortDirection::Descending, m_state.sortDir==Specter::SortDirection::Descending &&
(m_state.sortColumn == State::SortColumn::Name || m_state.sortColumn == State::SortColumn::Size),
true); true);
m_fileListingBind.updateListing(dEnum); m_resListingBind.updateListing(dEnum);
if (m_pathButtons) if (m_pathButtons)
m_pathButtons->setButtons(m_comps); m_pathButtons->setButtons(m_comps);
if (m_view) if (m_view)
{ {
m_view->m_fileListing.m_view->selectRow(-1); m_view->m_resListing.m_view->selectRow(-1);
m_view->m_fileListing.m_view->updateData(); m_view->m_resListing.m_view->updateData();
m_view->updateSize(); m_view->updateSize();
} }
@ -55,32 +56,32 @@ void ResourceBrowser::pathButtonActivated(size_t idx)
void ResourceBrowser::View::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void ResourceBrowser::View::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{ {
m_fileListing.mouseDown(coord, button, mod); m_resListing.mouseDown(coord, button, mod);
} }
void ResourceBrowser::View::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void ResourceBrowser::View::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{ {
m_fileListing.mouseUp(coord, button, mod); m_resListing.mouseUp(coord, button, mod);
} }
void ResourceBrowser::View::mouseMove(const boo::SWindowCoord& coord) void ResourceBrowser::View::mouseMove(const boo::SWindowCoord& coord)
{ {
m_fileListing.mouseMove(coord); m_resListing.mouseMove(coord);
} }
void ResourceBrowser::View::mouseLeave(const boo::SWindowCoord& coord) void ResourceBrowser::View::mouseLeave(const boo::SWindowCoord& coord)
{ {
m_fileListing.mouseLeave(coord); m_resListing.mouseLeave(coord);
} }
void ResourceBrowser::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void ResourceBrowser::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{ {
Specter::View::resized(root, sub); Specter::View::resized(root, sub);
m_fileListing.m_view->resized(root, sub); m_resListing.m_view->resized(root, sub);
} }
void ResourceBrowser::View::draw(boo::IGraphicsCommandQueue* gfxQ) void ResourceBrowser::View::draw(boo::IGraphicsCommandQueue* gfxQ)
{ {
m_fileListing.m_view->draw(gfxQ); m_resListing.m_view->draw(gfxQ);
} }
} }

View File

@ -140,6 +140,7 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
void setSort(size_t cIdx, Specter::SortDirection dir) void setSort(size_t cIdx, Specter::SortDirection dir)
{ {
m_rb.m_state.sortDir = dir; m_rb.m_state.sortDir = dir;
m_rb.m_state.sortColumn = State::SortColumn(cIdx);
m_needsUpdate = true; m_needsUpdate = true;
} }
@ -162,18 +163,18 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
m_fileStr = vm.translateOr("file", "File"); m_fileStr = vm.translateOr("file", "File");
} }
} m_fileListingBind; } m_resListingBind;
struct View : Specter::View struct View : Specter::View
{ {
ResourceBrowser& m_ro; ResourceBrowser& m_ro;
Specter::ViewChild<std::unique_ptr<Specter::Table>> m_fileListing; Specter::ViewChild<std::unique_ptr<Specter::Table>> m_resListing;
View(ResourceBrowser& ro, Specter::ViewResources& res) View(ResourceBrowser& ro, Specter::ViewResources& res)
: Specter::View(res, ro.m_vm.rootView()), m_ro(ro) : Specter::View(res, ro.m_vm.rootView()), m_ro(ro)
{ {
commitResources(res); commitResources(res);
m_fileListing.m_view.reset(new Specter::Table(res, *this, &ro.m_fileListingBind, &ro.m_fileListingBind, 3)); m_resListing.m_view.reset(new Specter::Table(res, *this, &ro.m_resListingBind, &ro.m_resListingBind, 3));
} }
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
@ -191,7 +192,7 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
public: public:
ResourceBrowser(ViewManager& vm, Space* parent) ResourceBrowser(ViewManager& vm, Space* parent)
: Space(vm, Class::ResourceBrowser, parent), : Space(vm, Class::ResourceBrowser, parent),
m_fileListingBind(*this, vm) m_resListingBind(*this, vm)
{ {
reloadState(); reloadState();
} }
@ -220,6 +221,12 @@ public:
navigateToPath(pp); navigateToPath(pp);
} }
void think()
{
if (m_resListingBind.m_needsUpdate)
reloadState();
}
bool navigateToPath(const HECL::ProjectPath& path); bool navigateToPath(const HECL::ProjectPath& path);
Space* copy(Space* parent) const Space* copy(Space* parent) const
@ -230,7 +237,8 @@ public:
void buildToolbarView(Specter::ViewResources &res, Specter::Toolbar &tb) void buildToolbarView(Specter::ViewResources &res, Specter::Toolbar &tb)
{ {
m_pathButtons.reset(new Specter::PathButtons(res, tb, *this, true)); m_pathButtons.reset(new Specter::PathButtons(res, tb, *this, true));
tb.push_back(m_pathButtons.get(), 0); tb.push_back(m_pathButtons.get(), 1);
reloadState();
} }
Specter::View* buildContentView(Specter::ViewResources& res) Specter::View* buildContentView(Specter::ViewResources& res)

View File

@ -181,6 +181,12 @@ public:
#endif #endif
} }
void think()
{
if (m_spaceTree)
m_spaceTree->think();
}
void saveState(Athena::io::IStreamWriter& w) const void saveState(Athena::io::IStreamWriter& w) const
{ {
w.writeUint32Big(atUint32(m_class)); w.writeUint32Big(atUint32(m_class));
@ -272,6 +278,14 @@ public:
} }
} }
void think()
{
if (m_slots[0])
m_slots[0]->think();
if (m_slots[1])
m_slots[1]->think();
}
void saveState(Athena::io::IStreamWriter& w) const void saveState(Athena::io::IStreamWriter& w) const
{ {
w.writeUint32Big(atUint32(m_class)); w.writeUint32Big(atUint32(m_class));
@ -360,6 +374,13 @@ public:
: Space(vm, cls, parent) {} : Space(vm, cls, parent) {}
}; };
class GameSpace : public Space
{
public:
GameSpace(ViewManager& vm, Class cls, Space* parent)
: Space(vm, cls, parent) {}
};
class TestSpace : public Space class TestSpace : public Space
{ {
std::unique_ptr<Specter::Button> m_button; std::unique_ptr<Specter::Button> m_button;

2
hecl

@ -1 +1 @@
Subproject commit d7ba6810af60bccd41d42d1c06112c2f414b3f98 Subproject commit 82333be06ce889bdb78986ba0137f17832366c45

@ -1 +1 @@
Subproject commit c34050a3bb9a5c55cb26636d75e7d820d589e6a3 Subproject commit a7c11c72d2d97e680b0f595fa57649545cc53d13