mirror of https://github.com/AxioDL/metaforce.git
Initial migration to URDE-hashed object tags
This commit is contained in:
parent
c1af78e7ed
commit
2a614215c8
|
@ -21,7 +21,6 @@ add_library(DNACommon
|
|||
ParticleCommon.cpp
|
||||
DeafBabe.hpp
|
||||
BabeDead.hpp
|
||||
NamedResourceCatalog.hpp
|
||||
Tweaks/ITweakGame.hpp
|
||||
Tweaks/ITweakParticle.hpp
|
||||
Tweaks/ITweakPlayer.hpp
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "PAK.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
LogVisor::LogModule LogDNACommon("Retro::DNACommon");
|
||||
SpecBase* g_curSpec = nullptr;
|
||||
PAKRouterBase* g_PakRouter = nullptr;
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace DataSpec
|
|||
|
||||
extern LogVisor::LogModule LogDNACommon;
|
||||
extern SpecBase* g_curSpec;
|
||||
extern class PAKRouterBase* g_PakRouter;
|
||||
|
||||
/* This comes up a great deal */
|
||||
typedef Athena::io::DNA<Athena::BigEndian> BigDNA;
|
||||
|
@ -44,6 +45,64 @@ public:
|
|||
};
|
||||
|
||||
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 */
|
||||
class UniqueID32 : public BigYAML
|
||||
|
@ -57,9 +116,13 @@ public:
|
|||
void write(Athena::io::IStreamWriter& writer) const
|
||||
{writer.writeUint32Big(m_id);}
|
||||
void read(Athena::io::YAMLDocReader& reader)
|
||||
{m_id = reader.readUint32(nullptr);}
|
||||
{
|
||||
*this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
|
||||
}
|
||||
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
|
||||
{return __isz + 4;}
|
||||
|
||||
|
@ -110,9 +173,13 @@ public:
|
|||
void write(Athena::io::IStreamWriter& writer) const
|
||||
{writer.writeUint64Big(m_id);}
|
||||
void read(Athena::io::YAMLDocReader& reader)
|
||||
{m_id = reader.readUint64(nullptr);}
|
||||
{
|
||||
*this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
|
||||
}
|
||||
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
|
||||
{return __isz + 8;}
|
||||
|
||||
|
@ -186,21 +253,22 @@ public:
|
|||
}
|
||||
void read(Athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
std::string str = 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);
|
||||
*this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr));
|
||||
}
|
||||
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
|
||||
{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
|
||||
{
|
||||
#if __SSE__
|
||||
|
@ -234,61 +302,6 @@ public:
|
|||
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 */
|
||||
class WordBitmap
|
||||
{
|
||||
|
|
|
@ -24,14 +24,6 @@ bool ReadMLVLToBlender(HECL::BlenderConnection& conn,
|
|||
if (!force && mlvlPath.getPathType() == HECL::ProjectPath::Type::File)
|
||||
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 */
|
||||
if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::BlendType::World))
|
||||
return false;
|
||||
|
|
|
@ -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
|
|
@ -2,12 +2,11 @@
|
|||
#define __DNACOMMON_PAK_HPP__
|
||||
|
||||
#include "DNACommon.hpp"
|
||||
#include "NamedResourceCatalog.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
/* PAK entry stream reader */
|
||||
/** PAK entry stream reader */
|
||||
class PAKEntryReadStream : public Athena::io::IStreamReader
|
||||
{
|
||||
std::unique_ptr<atUint8[]> m_buf;
|
||||
|
@ -197,7 +196,7 @@ struct UniqueResult
|
|||
template <class BRIDGETYPE>
|
||||
class PAKRouter;
|
||||
|
||||
/* Resource extractor type */
|
||||
/** Resource extractor type */
|
||||
template <class PAKBRIDGE>
|
||||
struct ResExtractor
|
||||
{
|
||||
|
@ -211,7 +210,7 @@ struct ResExtractor
|
|||
typename PAKBRIDGE::PAKType::Entry&)> func_name;
|
||||
};
|
||||
|
||||
/* Level hierarchy representation */
|
||||
/** Level hierarchy representation */
|
||||
template <class IDType>
|
||||
struct Level
|
||||
{
|
||||
|
@ -231,9 +230,9 @@ struct Level
|
|||
std::unordered_map<IDType, Area> areas;
|
||||
};
|
||||
|
||||
/* PAKRouter (for detecting shared entry locations) */
|
||||
/** PAKRouter (for detecting shared entry locations) */
|
||||
template <class BRIDGETYPE>
|
||||
class PAKRouter
|
||||
class PAKRouter : public PAKRouterBase
|
||||
{
|
||||
public:
|
||||
using PAKType = typename BRIDGETYPE::PAKType;
|
||||
|
@ -241,8 +240,6 @@ public:
|
|||
using EntryType = typename PAKType::Entry;
|
||||
using RigPair = std::pair<IDType, IDType>;
|
||||
private:
|
||||
NamedResourceCatalog<IDType> m_catalog;
|
||||
const SpecBase& m_dataSpec;
|
||||
const std::vector<BRIDGETYPE>* m_bridges = nullptr;
|
||||
std::vector<std::pair<HECL::ProjectPath,HECL::ProjectPath>> m_bridgePaths;
|
||||
size_t m_curBridgeIdx = 0;
|
||||
|
@ -257,12 +254,13 @@ private:
|
|||
std::unordered_map<IDType, RigPair> m_cmdlRigs;
|
||||
public:
|
||||
PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
|
||||
: m_dataSpec(dataSpec),
|
||||
: PAKRouterBase(dataSpec),
|
||||
m_gameWorking(working), m_gameCooked(cooked),
|
||||
m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {}
|
||||
|
||||
void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress)
|
||||
{
|
||||
g_PakRouter = this;
|
||||
m_bridges = &bridges;
|
||||
m_bridgePaths.clear();
|
||||
|
||||
|
@ -311,21 +309,29 @@ public:
|
|||
/* Add RigPairs to global map */
|
||||
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);
|
||||
++bridgeIdx;
|
||||
}
|
||||
|
||||
HECL::SystemString catalogPath = HECL::ProjectPath(m_gameCooked, "catalog.yaml").getAbsolutePath();
|
||||
FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("wb"));
|
||||
if (catalog)
|
||||
/* Add named resources to catalog YAML */
|
||||
Athena::io::YAMLDocWriter catalogWriter(nullptr);
|
||||
for (BRIDGETYPE& bridge : bridges)
|
||||
{
|
||||
m_catalog.toYAMLFile(catalog);
|
||||
fclose(catalog);
|
||||
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
|
||||
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)
|
||||
|
@ -347,6 +353,7 @@ public:
|
|||
++bridgeIdx;
|
||||
}
|
||||
LogDNACommon.report(LogVisor::FatalError, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()");
|
||||
g_PakRouter = this;
|
||||
}
|
||||
|
||||
HECL::ProjectPath getWorking(const EntryType* entry,
|
||||
|
@ -362,11 +369,11 @@ public:
|
|||
{
|
||||
const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first;
|
||||
pakPath.makeDir();
|
||||
#if HECL_UCS2
|
||||
#if HECL_UCS2
|
||||
HECL::SystemString entName = HECL::UTF8ToWide(m_pak->bestEntryName(*entry));
|
||||
#else
|
||||
#else
|
||||
HECL::SystemString entName = m_pak->bestEntryName(*entry);
|
||||
#endif
|
||||
#endif
|
||||
if (extractor.fileExts[0] && !extractor.fileExts[1])
|
||||
entName += extractor.fileExts[0];
|
||||
return HECL::ProjectPath(pakPath, entName);
|
||||
|
@ -393,7 +400,6 @@ public:
|
|||
if (sharedSearch != m_sharedEntries.end())
|
||||
{
|
||||
const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first;
|
||||
HECL::ProjectPath uniquePathPre = entry->unique.uniquePath(pakPath);
|
||||
#if HECL_UCS2
|
||||
HECL::SystemString entBase = HECL::UTF8ToWide(m_pak->bestEntryName(*entry));
|
||||
#else
|
||||
|
@ -403,24 +409,6 @@ public:
|
|||
if (extractor.fileExts[0] && !extractor.fileExts[1])
|
||||
entName += extractor.fileExts[0];
|
||||
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();
|
||||
return sharedPath;
|
||||
}
|
||||
|
@ -527,13 +515,13 @@ public:
|
|||
ResExtractor<BRIDGETYPE> extractor = BRIDGETYPE::LookupExtractor(*item);
|
||||
if (extractor.weight != w)
|
||||
continue;
|
||||
|
||||
|
||||
std::string bestName = getBestEntryName(*item);
|
||||
HECL::SystemStringView bestNameView(bestName);
|
||||
float thisFac = ++count / fsz;
|
||||
progress(bestNameView.sys_str().c_str(), thisFac);
|
||||
|
||||
/* TODO: Position after extracted item */
|
||||
/* Extract first, so they start out invalid */
|
||||
HECL::ProjectPath cooked = getCooked(item);
|
||||
if (force || cooked.getPathType() == HECL::ProjectPath::Type::None)
|
||||
{
|
||||
|
|
|
@ -60,7 +60,7 @@ struct SpecBase : HECL::Database::IDataSpec
|
|||
virtual HECL::ProjectPath getWorking(class UniqueID64&) {return HECL::ProjectPath();}
|
||||
|
||||
/* Project accessor */
|
||||
HECL::Database::Project& getProject() {return m_project;}
|
||||
HECL::Database::Project& getProject() const {return m_project;}
|
||||
|
||||
SpecBase(HECL::Database::Project& project);
|
||||
protected:
|
||||
|
|
|
@ -19,10 +19,24 @@ ProjectResourceFactory::ProjectResourceFactory()
|
|||
|
||||
void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::ProjectDataSpec &spec)
|
||||
{
|
||||
m_resPaths.clear();
|
||||
m_namedResources.clear();
|
||||
m_tagToPath.clear();
|
||||
m_catalogNameToTag.clear();
|
||||
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"));
|
||||
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")))
|
||||
{
|
||||
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,
|
||||
const pshag::CVParamTransfer& paramXfer)
|
||||
{
|
||||
auto search = m_resPaths.find(tag);
|
||||
if (search == m_resPaths.end())
|
||||
auto search = m_tagToPath.find(tag);
|
||||
if (search == m_tagToPath.end())
|
||||
return {};
|
||||
|
||||
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)
|
||||
{
|
||||
auto search = m_resPaths.find(tag);
|
||||
if (search == m_resPaths.end())
|
||||
auto search = m_tagToPath.find(tag);
|
||||
if (search == m_tagToPath.end())
|
||||
return 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
|
||||
{
|
||||
if (m_namedResources.find(name) == m_namedResources.end())
|
||||
if (m_catalogNameToTag.find(name) == m_catalogNameToTag.end())
|
||||
return nullptr;
|
||||
const pshag::SObjectTag& tag = m_namedResources.at(name);
|
||||
const pshag::SObjectTag& tag = m_catalogNameToTag.at(name);
|
||||
return &tag;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
|
||||
#include "Runtime/IFactory.hpp"
|
||||
#include "Runtime/CFactoryMgr.hpp"
|
||||
#include "DataSpec/DNACommon/NamedResourceCatalog.hpp"
|
||||
|
||||
namespace URDE
|
||||
{
|
||||
|
||||
class ProjectResourceFactory : public pshag::IFactory
|
||||
{
|
||||
std::unordered_map<pshag::SObjectTag, HECL::ProjectPath> m_resPaths;
|
||||
std::unordered_map<std::string, pshag::SObjectTag> m_namedResources;
|
||||
std::unordered_map<pshag::SObjectTag, HECL::ProjectPath> m_tagToPath;
|
||||
std::unordered_map<std::string, pshag::SObjectTag> m_catalogNameToTag;
|
||||
std::unordered_map<std::string, HECL::ProjectPath> m_catalogNameToPath;
|
||||
pshag::CFactoryMgr m_factoryMgr;
|
||||
template <class IDType>
|
||||
void RecursiveAddDirObjects(const HECL::ProjectPath& path, const DataSpec::NamedResourceCatalog<IDType>& catalog)
|
||||
|
@ -34,8 +34,8 @@ class ProjectResourceFactory : public pshag::IFactory
|
|||
if (id)
|
||||
{
|
||||
pshag::SObjectTag objTag = {HECL::FourCC(entu8.c_str()), id};
|
||||
if (m_resPaths.find(objTag) == m_resPaths.end())
|
||||
m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name);
|
||||
if (m_tagToPath.find(objTag) == m_tagToPath.end())
|
||||
m_tagToPath[objTag] = HECL::ProjectPath(path, ent.m_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -50,8 +50,8 @@ class ProjectResourceFactory : public pshag::IFactory
|
|||
const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& nr = *it;
|
||||
pshag::SObjectTag objTag = GetTag<IDType>(nr);
|
||||
|
||||
m_namedResources[nr.name.c_str()] = objTag;
|
||||
m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name);
|
||||
m_catalogNameToTag[nr.name.c_str()] = objTag;
|
||||
m_tagToPath[objTag] = HECL::ProjectPath(path, ent.m_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,17 @@ bool ResourceBrowser::navigateToPath(const HECL::ProjectPath& pathIn)
|
|||
HECL::DirectoryEnumerator dEnum(m_path.getAbsolutePath(),
|
||||
HECL::DirectoryEnumerator::Mode::DirsThenFilesSorted,
|
||||
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);
|
||||
m_fileListingBind.updateListing(dEnum);
|
||||
m_resListingBind.updateListing(dEnum);
|
||||
if (m_pathButtons)
|
||||
m_pathButtons->setButtons(m_comps);
|
||||
|
||||
if (m_view)
|
||||
{
|
||||
m_view->m_fileListing.m_view->selectRow(-1);
|
||||
m_view->m_fileListing.m_view->updateData();
|
||||
m_view->m_resListing.m_view->selectRow(-1);
|
||||
m_view->m_resListing.m_view->updateData();
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_fileListing.mouseUp(coord, button, mod);
|
||||
m_resListing.mouseUp(coord, button, mod);
|
||||
}
|
||||
|
||||
void ResourceBrowser::View::mouseMove(const boo::SWindowCoord& coord)
|
||||
{
|
||||
m_fileListing.mouseMove(coord);
|
||||
m_resListing.mouseMove(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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_fileListing.m_view->draw(gfxQ);
|
||||
m_resListing.m_view->draw(gfxQ);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
|
|||
void setSort(size_t cIdx, Specter::SortDirection dir)
|
||||
{
|
||||
m_rb.m_state.sortDir = dir;
|
||||
m_rb.m_state.sortColumn = State::SortColumn(cIdx);
|
||||
m_needsUpdate = true;
|
||||
}
|
||||
|
||||
|
@ -162,18 +163,18 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
|
|||
m_fileStr = vm.translateOr("file", "File");
|
||||
}
|
||||
|
||||
} m_fileListingBind;
|
||||
} m_resListingBind;
|
||||
|
||||
struct View : Specter::View
|
||||
{
|
||||
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)
|
||||
: Specter::View(res, ro.m_vm.rootView()), m_ro(ro)
|
||||
{
|
||||
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);
|
||||
|
@ -191,7 +192,7 @@ class ResourceBrowser : public Space, public Specter::IPathButtonsBinding
|
|||
public:
|
||||
ResourceBrowser(ViewManager& vm, Space* parent)
|
||||
: Space(vm, Class::ResourceBrowser, parent),
|
||||
m_fileListingBind(*this, vm)
|
||||
m_resListingBind(*this, vm)
|
||||
{
|
||||
reloadState();
|
||||
}
|
||||
|
@ -220,6 +221,12 @@ public:
|
|||
navigateToPath(pp);
|
||||
}
|
||||
|
||||
void think()
|
||||
{
|
||||
if (m_resListingBind.m_needsUpdate)
|
||||
reloadState();
|
||||
}
|
||||
|
||||
bool navigateToPath(const HECL::ProjectPath& path);
|
||||
|
||||
Space* copy(Space* parent) const
|
||||
|
@ -230,7 +237,8 @@ public:
|
|||
void buildToolbarView(Specter::ViewResources &res, Specter::Toolbar &tb)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -181,6 +181,12 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
void think()
|
||||
{
|
||||
if (m_spaceTree)
|
||||
m_spaceTree->think();
|
||||
}
|
||||
|
||||
void saveState(Athena::io::IStreamWriter& w) const
|
||||
{
|
||||
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
|
||||
{
|
||||
w.writeUint32Big(atUint32(m_class));
|
||||
|
@ -360,6 +374,13 @@ public:
|
|||
: Space(vm, cls, parent) {}
|
||||
};
|
||||
|
||||
class GameSpace : public Space
|
||||
{
|
||||
public:
|
||||
GameSpace(ViewManager& vm, Class cls, Space* parent)
|
||||
: Space(vm, cls, parent) {}
|
||||
};
|
||||
|
||||
class TestSpace : public Space
|
||||
{
|
||||
std::unique_ptr<Specter::Button> m_button;
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit d7ba6810af60bccd41d42d1c06112c2f414b3f98
|
||||
Subproject commit 82333be06ce889bdb78986ba0137f17832366c45
|
|
@ -1 +1 @@
|
|||
Subproject commit c34050a3bb9a5c55cb26636d75e7d820d589e6a3
|
||||
Subproject commit a7c11c72d2d97e680b0f595fa57649545cc53d13
|
Loading…
Reference in New Issue