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
DeafBabe.hpp
BabeDead.hpp
NamedResourceCatalog.hpp
Tweaks/ITweakGame.hpp
Tweaks/ITweakParticle.hpp
Tweaks/ITweakPlayer.hpp

View File

@ -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;
}

View File

@ -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
{

View File

@ -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;

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__
#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)
{

View File

@ -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:

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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

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

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