mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
ObjLoading: Be able to load and index IWD files
This commit is contained in:
parent
a4d55ffae7
commit
0abdb64832
@ -2,6 +2,7 @@ ObjCommon = {}
|
|||||||
|
|
||||||
function ObjCommon:include()
|
function ObjCommon:include()
|
||||||
ZoneCommon:include()
|
ZoneCommon:include()
|
||||||
|
minizip:include()
|
||||||
includedirs {
|
includedirs {
|
||||||
path.join(ProjectFolder(), "ObjCommon")
|
path.join(ProjectFolder(), "ObjCommon")
|
||||||
}
|
}
|
||||||
@ -10,6 +11,7 @@ end
|
|||||||
function ObjCommon:link()
|
function ObjCommon:link()
|
||||||
Utils:link()
|
Utils:link()
|
||||||
ZoneCommon:link()
|
ZoneCommon:link()
|
||||||
|
minizip:link()
|
||||||
links {
|
links {
|
||||||
"ObjCommon"
|
"ObjCommon"
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,5 @@ class IObjContainer
|
|||||||
public:
|
public:
|
||||||
virtual ~IObjContainer() = default;
|
virtual ~IObjContainer() = default;
|
||||||
|
|
||||||
virtual const std::string& GetName() = 0;
|
virtual std::string GetName() = 0;
|
||||||
};
|
};
|
87
src/ObjCommon/Utils/ZlibFileWrapper.cpp
Normal file
87
src/ObjCommon/Utils/ZlibFileWrapper.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "ZlibFileWrapper.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
voidpf Wrapper_Zlib_FileOpen(voidpf opaque, const char*, int)
|
||||||
|
{
|
||||||
|
return opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong Wrapper_Zlib_FileRead(voidpf, voidpf stream, void* buf, const uLong size)
|
||||||
|
{
|
||||||
|
auto* file = reinterpret_cast<FileAPI::IFile*>(stream);
|
||||||
|
|
||||||
|
return file->Read(buf, 1, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong Wrapper_Zlib_FileWrite(voidpf opaque, voidpf stream, const void* buf, const uLong size)
|
||||||
|
{
|
||||||
|
auto* file = reinterpret_cast<FileAPI::IFile*>(stream);
|
||||||
|
|
||||||
|
return file->Write(buf, 1, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
long Wrapper_Zlib_FileTell(voidpf opaque, voidpf stream)
|
||||||
|
{
|
||||||
|
auto* file = reinterpret_cast<FileAPI::IFile*>(stream);
|
||||||
|
|
||||||
|
return static_cast<long>(file->Pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
long Wrapper_Zlib_FileSeek(voidpf opaque, voidpf stream, const uLong offset, const int origin)
|
||||||
|
{
|
||||||
|
auto* file = reinterpret_cast<FileAPI::IFile*>(stream);
|
||||||
|
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||||
|
file->Skip(offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZLIB_FILEFUNC_SEEK_END:
|
||||||
|
assert(offset == 0);
|
||||||
|
file->GotoEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZLIB_FILEFUNC_SEEK_SET:
|
||||||
|
file->Goto(offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Wrapper_Zlib_FileClose(voidpf opaque, voidpf stream)
|
||||||
|
{
|
||||||
|
auto* file = reinterpret_cast<FileAPI::IFile*>(stream);
|
||||||
|
|
||||||
|
if (file->IsOpen())
|
||||||
|
{
|
||||||
|
file->Close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Wrapper_Zlib_FileError(voidpf opaque, voidpf stream)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
zlib_filefunc_def ZlibFileWrapper::CreateFunctions32ForFile(FileAPI::IFile* file)
|
||||||
|
{
|
||||||
|
return zlib_filefunc_def_s
|
||||||
|
{
|
||||||
|
Wrapper_Zlib_FileOpen,
|
||||||
|
Wrapper_Zlib_FileRead,
|
||||||
|
Wrapper_Zlib_FileWrite,
|
||||||
|
Wrapper_Zlib_FileTell,
|
||||||
|
Wrapper_Zlib_FileSeek,
|
||||||
|
Wrapper_Zlib_FileClose,
|
||||||
|
Wrapper_Zlib_FileError,
|
||||||
|
file
|
||||||
|
};
|
||||||
|
}
|
10
src/ObjCommon/Utils/ZlibFileWrapper.h
Normal file
10
src/ObjCommon/Utils/ZlibFileWrapper.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ioapi.h>
|
||||||
|
#include "Utils/FileAPI.h"
|
||||||
|
|
||||||
|
class ZlibFileWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static zlib_filefunc_def CreateFunctions32ForFile(FileAPI::IFile* file);
|
||||||
|
};
|
@ -1,9 +1,10 @@
|
|||||||
#include "ObjLoaderT6.h"
|
#include "ObjLoaderT6.h"
|
||||||
#include "Game/T6/GameT6.h"
|
#include "Game/T6/GameT6.h"
|
||||||
#include "Game/T6/GameAssetPoolT6.h"
|
#include "Game/T6/GameAssetPoolT6.h"
|
||||||
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
|
|
||||||
const int ObjLoaderT6::IPAK_READ_HASH = ObjLoaderT6::Com_HashKey("ipak_read", 64);
|
const int ObjLoaderT6::IPAK_READ_HASH = Com_HashKey("ipak_read", 64);
|
||||||
const int ObjLoaderT6::GLOBAL_HASH = ObjLoaderT6::Com_HashKey("GLOBAL", 64);
|
const int ObjLoaderT6::GLOBAL_HASH = Com_HashKey("GLOBAL", 64);
|
||||||
|
|
||||||
int ObjLoaderT6::Com_HashKey(const char* str, const int maxLen)
|
int ObjLoaderT6::Com_HashKey(const char* str, const int maxLen)
|
||||||
{
|
{
|
||||||
@ -27,10 +28,18 @@ bool ObjLoaderT6::SupportsZone(Zone* zone)
|
|||||||
return zone->m_game == &g_GameT6;
|
return zone->m_game == &g_GameT6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadIPakForZone(const std::string& ipakName, Zone* zone)
|
void ObjLoaderT6::LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone)
|
||||||
{
|
{
|
||||||
printf("Loading ipak '%s' for zone '%s'\n", ipakName.c_str(), zone->m_name.c_str());
|
printf("Loading ipak '%s' for zone '%s'\n", ipakName.c_str(), zone->m_name.c_str());
|
||||||
// TODO
|
|
||||||
|
const std::string ipakFilename = ipakName + ".ipak";
|
||||||
|
|
||||||
|
auto* file = searchPath->Open(ipakFilename);
|
||||||
|
|
||||||
|
if(file && file->IsOpen())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
void ObjLoaderT6::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
@ -48,13 +57,18 @@ void ObjLoaderT6::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone*
|
|||||||
|
|
||||||
if(variable->namespaceHash == zoneNameHash && variable->keyHash == IPAK_READ_HASH)
|
if(variable->namespaceHash == zoneNameHash && variable->keyHash == IPAK_READ_HASH)
|
||||||
{
|
{
|
||||||
LoadIPakForZone(variable->value, zone);
|
LoadIPakForZone(searchPath, variable->value, zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjLoaderT6::UnloadContainersOfZone(Zone* zone)
|
||||||
|
{
|
||||||
|
IPak::Repository.RemoveContainerReferences(zone);
|
||||||
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
void ObjLoaderT6::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
class ObjLoaderT6 final : public IObjLoader
|
class ObjLoaderT6 final : public IObjLoader
|
||||||
{
|
{
|
||||||
@ -8,10 +9,13 @@ class ObjLoaderT6 final : public IObjLoader
|
|||||||
static const int GLOBAL_HASH;
|
static const int GLOBAL_HASH;
|
||||||
static int Com_HashKey(const char* str, int maxLen);
|
static int Com_HashKey(const char* str, int maxLen);
|
||||||
|
|
||||||
static void LoadIPakForZone(const std::string& ipakName, Zone* zone);
|
static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool SupportsZone(Zone* zone) override;
|
bool SupportsZone(Zone* zone) override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) override;
|
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) override;
|
||||||
|
void UnloadContainersOfZone(Zone* zone) override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) override;
|
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) override;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,9 @@ public:
|
|||||||
virtual ~IObjLoader() = default;
|
virtual ~IObjLoader() = default;
|
||||||
|
|
||||||
virtual bool SupportsZone(Zone* zone) = 0;
|
virtual bool SupportsZone(Zone* zone) = 0;
|
||||||
|
|
||||||
virtual void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
virtual void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
||||||
|
virtual void UnloadContainersOfZone(Zone* zone) = 0;
|
||||||
|
|
||||||
virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
||||||
};
|
};
|
@ -3,10 +3,13 @@
|
|||||||
#include "Exception/IPakLoadException.h"
|
#include "Exception/IPakLoadException.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "Utils/PathUtils.h"
|
||||||
|
|
||||||
const uint32_t IPak::MAGIC = 'IPAK';
|
const uint32_t IPak::MAGIC = 'IPAK';
|
||||||
const uint32_t IPak::VERSION = 0x50000;
|
const uint32_t IPak::VERSION = 0x50000;
|
||||||
|
|
||||||
|
ObjContainerRepository<IPak, Zone> IPak::Repository;
|
||||||
|
|
||||||
uint32_t IPak::R_HashString(const char* str, uint32_t hash)
|
uint32_t IPak::R_HashString(const char* str, uint32_t hash)
|
||||||
{
|
{
|
||||||
for (const char* pos = str; *pos; pos++)
|
for (const char* pos = str; *pos; pos++)
|
||||||
@ -17,8 +20,9 @@ uint32_t IPak::R_HashString(const char* str, uint32_t hash)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPak::IPak(FileAPI::IFile* file)
|
IPak::IPak(std::string path, FileAPI::IFile* file)
|
||||||
{
|
{
|
||||||
|
m_path = std::move(path);
|
||||||
m_file = file;
|
m_file = file;
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
m_index_section = nullptr;
|
m_index_section = nullptr;
|
||||||
@ -34,6 +38,11 @@ IPak::~IPak()
|
|||||||
m_data_section = nullptr;
|
m_data_section = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string IPak::GetName()
|
||||||
|
{
|
||||||
|
return utils::Path::GetFilename(m_path);
|
||||||
|
}
|
||||||
|
|
||||||
void IPak::ReadSection()
|
void IPak::ReadSection()
|
||||||
{
|
{
|
||||||
IPakSection section{};
|
IPakSection section{};
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "Utils/FileAPI.h"
|
#include "Utils/FileAPI.h"
|
||||||
#include "ObjContainer/IPak/IPakTypes.h"
|
#include "ObjContainer/IPak/IPakTypes.h"
|
||||||
#include "ObjContainer/ObjContainerReferenceable.h"
|
#include "ObjContainer/ObjContainerReferenceable.h"
|
||||||
|
#include "ObjContainer/ObjContainerRepository.h"
|
||||||
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -11,6 +13,7 @@ class IPak final : public ObjContainerReferenceable
|
|||||||
static const uint32_t MAGIC;
|
static const uint32_t MAGIC;
|
||||||
static const uint32_t VERSION;
|
static const uint32_t VERSION;
|
||||||
|
|
||||||
|
std::string m_path;
|
||||||
FileAPI::IFile* m_file;
|
FileAPI::IFile* m_file;
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
@ -26,9 +29,13 @@ class IPak final : public ObjContainerReferenceable
|
|||||||
void ReadHeader();
|
void ReadHeader();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IPak(FileAPI::IFile* file);
|
static ObjContainerRepository<IPak, Zone> Repository;
|
||||||
|
|
||||||
|
IPak(std::string path, FileAPI::IFile* file);
|
||||||
~IPak();
|
~IPak();
|
||||||
|
|
||||||
|
std::string GetName() override;
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
FileAPI::IFile* GetEntryData(IPakHash nameHash, IPakHash dataHash);
|
FileAPI::IFile* GetEntryData(IPakHash nameHash, IPakHash dataHash);
|
||||||
|
|
||||||
|
@ -1,32 +1,166 @@
|
|||||||
#include "IWD.h"
|
#include "IWD.h"
|
||||||
|
|
||||||
IWD::IWD(std::string path)
|
#include <unzip.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include "Utils/PathUtils.h"
|
||||||
|
#include "Utils/ZlibFileWrapper.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#include "ObjLoading.h"
|
||||||
|
|
||||||
|
ObjContainerRepository<IWD, ISearchPath> IWD::Repository;
|
||||||
|
|
||||||
|
class IWD::Impl : public ISearchPath, IObjContainer
|
||||||
{
|
{
|
||||||
m_path = std::move(path);
|
class IWDEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string m_name;
|
||||||
|
unz_file_pos m_file_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string m_path;
|
||||||
|
FileAPI::IFile* m_file;
|
||||||
|
unzFile m_unz_file;
|
||||||
|
|
||||||
|
std::vector<IWDEntry> m_entries;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Impl(std::string path, FileAPI::IFile* file)
|
||||||
|
{
|
||||||
|
m_unz_file = nullptr;
|
||||||
|
m_path = std::move(path);
|
||||||
|
m_file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Impl()
|
||||||
|
{
|
||||||
|
if (m_unz_file != nullptr)
|
||||||
|
{
|
||||||
|
unzClose(m_unz_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_file)
|
||||||
|
{
|
||||||
|
m_file->Close();
|
||||||
|
delete m_file;
|
||||||
|
m_file = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialize()
|
||||||
|
{
|
||||||
|
auto ioFunctions = ZlibFileWrapper::CreateFunctions32ForFile(m_file);
|
||||||
|
m_unz_file = unzOpen2("", &ioFunctions);
|
||||||
|
|
||||||
|
if (m_unz_file == nullptr)
|
||||||
|
{
|
||||||
|
printf("Could not open IWD \"%s\"\n", m_path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = unzGoToFirstFile(m_unz_file);
|
||||||
|
while (ret == Z_OK)
|
||||||
|
{
|
||||||
|
unz_file_info info;
|
||||||
|
char fileNameBuffer[256];
|
||||||
|
unzGetCurrentFileInfo(m_unz_file, &info, fileNameBuffer, sizeof fileNameBuffer, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
|
std::string fileName(fileNameBuffer);
|
||||||
|
std::filesystem::path path(fileName);
|
||||||
|
|
||||||
|
if (path.has_filename())
|
||||||
|
{
|
||||||
|
IWDEntry entry;
|
||||||
|
entry.m_name = std::move(fileName);
|
||||||
|
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
||||||
|
m_entries.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = unzGoToNextFile(m_unz_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ObjLoading::Configuration.Verbose)
|
||||||
|
{
|
||||||
|
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entries.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAPI::IFile* Open(const std::string& fileName) override
|
||||||
|
{
|
||||||
|
if (m_unz_file == nullptr)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetPath() override
|
||||||
|
{
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetName() override
|
||||||
|
{
|
||||||
|
return utils::Path::GetFilename(m_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IWD::IWD(std::string path, FileAPI::IFile* file)
|
||||||
|
{
|
||||||
|
m_impl = new Impl(std::move(path), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
IWD::~IWD()
|
||||||
|
{
|
||||||
|
delete m_impl;
|
||||||
|
m_impl = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWD::IWD(IWD&& other) noexcept
|
||||||
|
{
|
||||||
|
m_impl = other.m_impl;
|
||||||
|
other.m_impl = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWD& IWD::operator=(IWD&& other) noexcept
|
||||||
|
{
|
||||||
|
m_impl = other.m_impl;
|
||||||
|
other.m_impl = nullptr;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IWD::Initialize() const
|
||||||
|
{
|
||||||
|
return m_impl->Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAPI::IFile* IWD::Open(const std::string& fileName)
|
FileAPI::IFile* IWD::Open(const std::string& fileName)
|
||||||
{
|
{
|
||||||
// TODO
|
return m_impl->Open(fileName);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWD::FindAll(std::function<void(const std::string&)> callback)
|
std::string IWD::GetPath()
|
||||||
{
|
{
|
||||||
// TODO
|
return m_impl->GetPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWD::FindAllOnDisk(std::function<void(const std::string&)> callback)
|
std::string IWD::GetName()
|
||||||
{
|
{
|
||||||
// Files inside an IWD are not on the disk's file system directly. Therefore do nothing here.
|
return m_impl->GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWD::FindByExtension(const std::string& extension, std::function<void(const std::string&)> callback)
|
void IWD::Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback)
|
||||||
{
|
{
|
||||||
// TODO
|
return m_impl->Find(options, callback);
|
||||||
}
|
|
||||||
|
|
||||||
void IWD::FindOnDiskByExtension(const std::string& extension, std::function<void(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
// Files inside an IWD are not on the disk's file system directly. Therefore do nothing here.
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
#include "ObjContainer/ObjContainerRepository.h"
|
||||||
|
|
||||||
class IWD final : public ISearchPath
|
class IWD final : public ISearchPath, IObjContainer
|
||||||
{
|
{
|
||||||
std::string m_path;
|
class Impl;
|
||||||
|
Impl* m_impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IWD(std::string path);
|
static ObjContainerRepository<IWD, ISearchPath> Repository;
|
||||||
|
|
||||||
|
IWD(std::string path, FileAPI::IFile* file);
|
||||||
|
~IWD();
|
||||||
|
|
||||||
|
IWD(const IWD& other) = delete;
|
||||||
|
IWD(IWD&& other) noexcept;
|
||||||
|
IWD& operator=(const IWD& other) = delete;
|
||||||
|
IWD& operator=(IWD&& other) noexcept;
|
||||||
|
|
||||||
|
bool Initialize() const;
|
||||||
|
|
||||||
FileAPI::IFile* Open(const std::string& fileName) override;
|
FileAPI::IFile* Open(const std::string& fileName) override;
|
||||||
void FindAll(std::function<void(const std::string&)> callback) override;
|
std::string GetPath() override;
|
||||||
void FindAllOnDisk(std::function<void(const std::string&)> callback) override;
|
std::string GetName() override;
|
||||||
void FindByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||||
void FindOnDiskByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
|
||||||
};
|
};
|
@ -1,52 +0,0 @@
|
|||||||
#include "ObjContainerRegistry.h"
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
ObjContainerRegistry g_ObjContainerRegistry;
|
|
||||||
|
|
||||||
IObjContainer* ObjContainerRegistry::GetContainerByName(const std::string& name)
|
|
||||||
{
|
|
||||||
for (auto* container : m_containers)
|
|
||||||
{
|
|
||||||
if (container->GetName() == name)
|
|
||||||
{
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjContainerRegistry::AddContainer(IObjContainer* container)
|
|
||||||
{
|
|
||||||
assert(dynamic_cast<ObjContainerReferenceable*>(container) == nullptr);
|
|
||||||
|
|
||||||
m_containers.push_back(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjContainerRegistry::AddContainerWithReference(ObjContainerReferenceable* container, Zone* referencer)
|
|
||||||
{
|
|
||||||
container->AddReference(referencer);
|
|
||||||
m_containers.push_back(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjContainerRegistry::RemoveContainerReferences(Zone* referencer)
|
|
||||||
{
|
|
||||||
auto iContainer = m_containers.begin();
|
|
||||||
|
|
||||||
while (iContainer != m_containers.end())
|
|
||||||
{
|
|
||||||
auto* container = *iContainer;
|
|
||||||
|
|
||||||
if (auto* referenceableContainer = dynamic_cast<ObjContainerReferenceable*>(container))
|
|
||||||
{
|
|
||||||
if (referenceableContainer->RemoveReference(referencer) && !referenceableContainer->IsReferenced())
|
|
||||||
{
|
|
||||||
delete container;
|
|
||||||
iContainer = m_containers.erase(iContainer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++iContainer;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ObjContainer/IObjContainer.h"
|
|
||||||
#include "ObjContainer/ObjContainerReferenceable.h"
|
|
||||||
#include "Zone/Zone.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class ObjContainerRegistry
|
|
||||||
{
|
|
||||||
std::vector<IObjContainer*> m_containers;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void AddContainer(IObjContainer* container);
|
|
||||||
void AddContainerWithReference(ObjContainerReferenceable* container, Zone* referencer);
|
|
||||||
void RemoveContainerReferences(Zone* referencer);
|
|
||||||
|
|
||||||
IObjContainer* GetContainerByName(const std::string& name);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ObjContainerRegistry g_ObjContainerRegistry;
|
|
93
src/ObjLoading/ObjContainer/ObjContainerRepository.h
Normal file
93
src/ObjLoading/ObjContainer/ObjContainerRepository.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ObjContainer/IObjContainer.h"
|
||||||
|
#include "Utils/TransformIterator.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
template <typename ContainerType, typename ReferencerType>
|
||||||
|
class ObjContainerRepository
|
||||||
|
{
|
||||||
|
class ObjContainerEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContainerType* m_container;
|
||||||
|
std::set<ReferencerType*> m_references;
|
||||||
|
|
||||||
|
explicit ObjContainerEntry(ContainerType* container)
|
||||||
|
{
|
||||||
|
m_container = container;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ObjContainerEntry> m_containers;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void AddContainer(ContainerType* container, ReferencerType* referencer)
|
||||||
|
{
|
||||||
|
auto firstEntry = std::find_if(m_containers.begin(), m_containers.end(),
|
||||||
|
[container](ObjContainerEntry& entry) -> bool
|
||||||
|
{
|
||||||
|
return entry.m_container == container;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(firstEntry != m_containers.end())
|
||||||
|
{
|
||||||
|
firstEntry->m_references.insert(referencer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjContainerEntry entry(container);
|
||||||
|
entry.m_references.insert(referencer);
|
||||||
|
m_containers.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveContainerReferences(ReferencerType* referencer)
|
||||||
|
{
|
||||||
|
for(auto iEntry = m_containers.begin(); iEntry != m_containers.end(); ++iEntry)
|
||||||
|
{
|
||||||
|
auto foundReference = iEntry->m_references.find(referencer);
|
||||||
|
|
||||||
|
if(foundReference != iEntry->m_references.end())
|
||||||
|
{
|
||||||
|
iEntry->m_references.erase(foundReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(iEntry->m_references.empty())
|
||||||
|
{
|
||||||
|
delete iEntry->m_container;
|
||||||
|
m_containers.erase(iEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IObjContainer* GetContainerByName(const std::string& name)
|
||||||
|
{
|
||||||
|
auto foundEntry = std::find_if(m_containers.begin(), m_containers.end(), [name](ObjContainerEntry& entry) -> bool
|
||||||
|
{
|
||||||
|
return entry.m_container->GetName() == name;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(foundEntry != m_containers.end())
|
||||||
|
{
|
||||||
|
return foundEntry->m_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransformIterator<typename std::vector<ObjContainerEntry>::iterator, ObjContainerEntry&, ContainerType*> begin()
|
||||||
|
{
|
||||||
|
return TransformIterator<typename std::vector<ObjContainerEntry>::iterator, ObjContainerEntry&, ContainerType*>(
|
||||||
|
m_containers.begin(), [](ObjContainerEntry& entry) -> ContainerType* { return entry.m_container; });
|
||||||
|
}
|
||||||
|
|
||||||
|
TransformIterator<typename std::vector<ObjContainerEntry>::iterator, ObjContainerEntry&, ContainerType*> end()
|
||||||
|
{
|
||||||
|
return TransformIterator<typename std::vector<ObjContainerEntry>::iterator, ObjContainerEntry&, ContainerType*>(
|
||||||
|
m_containers.end(), [](ObjContainerEntry& entry) -> ContainerType* { return entry.m_container; });
|
||||||
|
}
|
||||||
|
};
|
@ -1,13 +1,18 @@
|
|||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
#include "Game/T6/ObjLoaderT6.h"
|
#include "Game/T6/ObjLoaderT6.h"
|
||||||
#include "ObjContainer/ObjContainerRegistry.h"
|
#include "ObjContainer/IWD/IWD.h"
|
||||||
|
#include "SearchPath/SearchPaths.h"
|
||||||
|
|
||||||
|
ObjLoading::Configuration_t ObjLoading::Configuration;
|
||||||
|
|
||||||
IObjLoader* objLoaders[]
|
IObjLoader* objLoaders[]
|
||||||
{
|
{
|
||||||
new ObjLoaderT6()
|
new ObjLoaderT6()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SearchPaths iwdSearchPaths;
|
||||||
|
|
||||||
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
for (auto* loader : objLoaders)
|
for (auto* loader : objLoaders)
|
||||||
@ -34,5 +39,49 @@ void ObjLoading::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
|||||||
|
|
||||||
void ObjLoading::UnloadContainersOfZone(Zone* zone)
|
void ObjLoading::UnloadContainersOfZone(Zone* zone)
|
||||||
{
|
{
|
||||||
g_ObjContainerRegistry.RemoveContainerReferences(zone);
|
for (auto* loader : objLoaders)
|
||||||
|
{
|
||||||
|
if (loader->SupportsZone(zone))
|
||||||
|
{
|
||||||
|
loader->UnloadContainersOfZone(zone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjLoading::LoadIWDsInSearchPath(ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
searchPath->Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
|
||||||
|
[searchPath](const std::string& path) -> void
|
||||||
|
{
|
||||||
|
auto file = FileAPI::Open(path, FileAPI::Mode::MODE_READ);
|
||||||
|
|
||||||
|
if (file.IsOpen())
|
||||||
|
{
|
||||||
|
const auto fileP = new FileAPI::File(std::move(file));
|
||||||
|
IWD* iwd = new IWD(path, fileP);
|
||||||
|
|
||||||
|
if (iwd->Initialize())
|
||||||
|
{
|
||||||
|
IWD::Repository.AddContainer(iwd, searchPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete iwd;
|
||||||
|
|
||||||
|
fileP->Close();
|
||||||
|
delete fileP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
IWD::Repository.RemoveContainerReferences(searchPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISearchPath* ObjLoading::GetIWDSearchPaths()
|
||||||
|
{
|
||||||
|
return &iwdSearchPaths;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,18 @@
|
|||||||
class ObjLoading
|
class ObjLoading
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static class Configuration_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Verbose = false;
|
||||||
|
} Configuration;
|
||||||
|
|
||||||
static void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone);
|
static void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone);
|
||||||
static void UnloadContainersOfZone(Zone* zone);
|
static void UnloadContainersOfZone(Zone* zone);
|
||||||
|
|
||||||
|
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
|
||||||
|
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
|
||||||
|
static ISearchPath* GetIWDSearchPaths();
|
||||||
|
|
||||||
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "SearchPathSearchOptions.h"
|
||||||
#include "Utils/FileAPI.h"
|
#include "Utils/FileAPI.h"
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class ISearchPath
|
class ISearchPath
|
||||||
@ -16,29 +16,25 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual FileAPI::IFile* Open(const std::string& fileName) = 0;
|
virtual FileAPI::IFile* Open(const std::string& fileName) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns the path to the search path.
|
||||||
|
* \return The path to the search path.
|
||||||
|
*/
|
||||||
|
virtual std::string GetPath() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Iterates through all files of the search path.
|
||||||
|
* \param callback The callback to call for each found file with it's path relative to the search path.
|
||||||
|
* \param options Options that modify the search.
|
||||||
|
*/
|
||||||
|
virtual void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Iterates through all files of the search path.
|
* \brief Iterates through all files of the search path.
|
||||||
* \param callback The callback to call for each found file with it's path relative to the search path.
|
* \param callback The callback to call for each found file with it's path relative to the search path.
|
||||||
*/
|
*/
|
||||||
virtual void FindAll(std::function<void(const std::string&)> callback) = 0;
|
void Find(const std::function<void(const std::string&)>& callback)
|
||||||
|
{
|
||||||
/**
|
Find(SearchPathSearchOptions(), callback);
|
||||||
* \brief Iterates through all files available through the OS file system.
|
}
|
||||||
* \param callback The callback to call for each found file with it's full path.
|
|
||||||
*/
|
|
||||||
virtual void FindAllOnDisk(std::function<void(const std::string&)> callback) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Iterates through all files of the search path with the specified extension.
|
|
||||||
* \param extension The extension of all files to find.
|
|
||||||
* \param callback The callback to call for each found file with it's path relative to the search path.
|
|
||||||
*/
|
|
||||||
virtual void FindByExtension(const std::string& extension, std::function<void(const std::string&)> callback) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Iterates through all files available through the OS file system with the specified extension.
|
|
||||||
* \param extension The extension of all files to find.
|
|
||||||
* \param callback The callback to call for each found file with it's full path.
|
|
||||||
*/
|
|
||||||
virtual void FindOnDiskByExtension(const std::string& extension, std::function<void(const std::string&)> callback) = 0;
|
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ SearchPathFilesystem::SearchPathFilesystem(std::string path)
|
|||||||
m_path = std::move(path);
|
m_path = std::move(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& SearchPathFilesystem::GetPath() const
|
std::string SearchPathFilesystem::GetPath()
|
||||||
{
|
{
|
||||||
return m_path;
|
return m_path;
|
||||||
}
|
}
|
||||||
@ -25,55 +25,28 @@ FileAPI::IFile* SearchPathFilesystem::Open(const std::string& fileName)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchPathFilesystem::Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback)
|
||||||
void SearchPathFilesystem::FindAll(const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
{
|
||||||
std::filesystem::recursive_directory_iterator iterator(m_path);
|
if (options.m_should_include_subdirectories)
|
||||||
|
|
||||||
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
|
||||||
{
|
{
|
||||||
callback(entry->path().string());
|
std::filesystem::recursive_directory_iterator iterator(m_path);
|
||||||
}
|
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
||||||
}
|
|
||||||
|
|
||||||
void SearchPathFilesystem::FindAllOnDisk(const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
std::filesystem::recursive_directory_iterator iterator(m_path);
|
|
||||||
|
|
||||||
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
|
||||||
{
|
|
||||||
callback(absolute(entry->path()).string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchPathFilesystem::FindByExtension(const std::string& extension,
|
|
||||||
const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
std::filesystem::recursive_directory_iterator iterator(m_path);
|
|
||||||
|
|
||||||
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
|
||||||
{
|
|
||||||
auto entryPath = entry->path();
|
|
||||||
|
|
||||||
if (entryPath.extension().string() == extension)
|
|
||||||
{
|
{
|
||||||
callback(entryPath.string());
|
auto path = entry->path();
|
||||||
}
|
if (options.m_filter_extensions && path.extension().string() != options.m_extension)
|
||||||
}
|
continue;
|
||||||
}
|
callback(options.m_absolute_paths ? absolute(path).string() : path.string());
|
||||||
|
}
|
||||||
void SearchPathFilesystem::FindOnDiskByExtension(const std::string& extension,
|
}
|
||||||
const std::function<void(const std::string&)> callback)
|
else
|
||||||
{
|
{
|
||||||
std::filesystem::recursive_directory_iterator iterator(m_path);
|
std::filesystem::directory_iterator iterator(m_path);
|
||||||
|
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
||||||
for (const auto entry = begin(iterator); iterator != end(iterator); ++iterator)
|
{
|
||||||
{
|
auto path = entry->path();
|
||||||
auto entryPath = entry->path();
|
if (options.m_filter_extensions && path.extension().string() != options.m_extension)
|
||||||
|
continue;
|
||||||
if (entryPath.extension().string() == extension)
|
callback(options.m_absolute_paths ? absolute(path).string() : path.string());
|
||||||
{
|
|
||||||
callback(absolute(entryPath).string());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,8 @@ class SearchPathFilesystem final : public ISearchPath
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SearchPathFilesystem(std::string path);
|
explicit SearchPathFilesystem(std::string path);
|
||||||
const std::string& GetPath() const;
|
|
||||||
|
|
||||||
FileAPI::IFile* Open(const std::string& fileName) override;
|
FileAPI::IFile* Open(const std::string& fileName) override;
|
||||||
void FindAll(std::function<void(const std::string&)> callback) override;
|
std::string GetPath() override;
|
||||||
void FindAllOnDisk(std::function<void(const std::string&)> callback) override;
|
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||||
void FindByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
|
||||||
void FindOnDiskByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
|
||||||
};
|
};
|
41
src/ObjLoading/SearchPath/SearchPathSearchOptions.cpp
Normal file
41
src/ObjLoading/SearchPath/SearchPathSearchOptions.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "SearchPathSearchOptions.h"
|
||||||
|
|
||||||
|
SearchPathSearchOptions::SearchPathSearchOptions()
|
||||||
|
{
|
||||||
|
m_should_include_subdirectories = true;
|
||||||
|
m_disk_files_only = false;
|
||||||
|
m_absolute_paths = false;
|
||||||
|
m_filter_extensions = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchPathSearchOptions& SearchPathSearchOptions::IncludeSubdirectories(const bool value)
|
||||||
|
{
|
||||||
|
m_should_include_subdirectories = value;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchPathSearchOptions& SearchPathSearchOptions::OnlyDiskFiles(const bool value)
|
||||||
|
{
|
||||||
|
m_disk_files_only = value;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchPathSearchOptions& SearchPathSearchOptions::AbsolutePaths(const bool value)
|
||||||
|
{
|
||||||
|
m_absolute_paths = value;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchPathSearchOptions& SearchPathSearchOptions::FilterExtensions(std::string extension)
|
||||||
|
{
|
||||||
|
m_extension = std::move(extension);
|
||||||
|
m_filter_extensions = true;
|
||||||
|
|
||||||
|
if(m_extension[0] != '.')
|
||||||
|
m_extension = "." + m_extension;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
21
src/ObjLoading/SearchPath/SearchPathSearchOptions.h
Normal file
21
src/ObjLoading/SearchPath/SearchPathSearchOptions.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SearchPathSearchOptions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool m_should_include_subdirectories;
|
||||||
|
bool m_disk_files_only;
|
||||||
|
bool m_absolute_paths;
|
||||||
|
|
||||||
|
bool m_filter_extensions;
|
||||||
|
std::string m_extension;
|
||||||
|
|
||||||
|
SearchPathSearchOptions();
|
||||||
|
|
||||||
|
SearchPathSearchOptions& IncludeSubdirectories(bool value);
|
||||||
|
SearchPathSearchOptions& OnlyDiskFiles(bool value);
|
||||||
|
SearchPathSearchOptions& AbsolutePaths(bool value);
|
||||||
|
SearchPathSearchOptions& FilterExtensions(std::string extension);
|
||||||
|
};
|
@ -56,36 +56,16 @@ FileAPI::IFile* SearchPaths::Open(const std::string& fileName)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SearchPaths::GetPath()
|
||||||
void SearchPaths::FindAll(const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
{
|
||||||
for (auto searchPathEntry : m_search_paths)
|
return "SearchPaths: " + std::to_string(m_search_paths.size()) + " entries";
|
||||||
{
|
|
||||||
searchPathEntry->FindAll(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchPaths::FindAllOnDisk(const std::function<void(const std::string&)> callback)
|
void SearchPaths::Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback)
|
||||||
{
|
{
|
||||||
for (auto searchPathEntry : m_search_paths)
|
for (auto searchPathEntry : m_search_paths)
|
||||||
{
|
{
|
||||||
searchPathEntry->FindAllOnDisk(callback);
|
searchPathEntry->Find(options, callback);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchPaths::FindByExtension(const std::string& extension, const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
for (auto searchPathEntry : m_search_paths)
|
|
||||||
{
|
|
||||||
searchPathEntry->FindByExtension(extension, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchPaths::FindOnDiskByExtension(const std::string& extension, const std::function<void(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
for (auto searchPathEntry : m_search_paths)
|
|
||||||
{
|
|
||||||
searchPathEntry->FindOnDiskByExtension(extension, callback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,10 +15,8 @@ public:
|
|||||||
~SearchPaths() override;
|
~SearchPaths() override;
|
||||||
|
|
||||||
FileAPI::IFile* Open(const std::string& fileName) override;
|
FileAPI::IFile* Open(const std::string& fileName) override;
|
||||||
void FindAll(std::function<void(const std::string&)> callback) override;
|
std::string GetPath() override;
|
||||||
void FindAllOnDisk(std::function<void(const std::string&)> callback) override;
|
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||||
void FindByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
|
||||||
void FindOnDiskByExtension(const std::string& extension, std::function<void(const std::string&)> callback) override;
|
|
||||||
|
|
||||||
SearchPaths(const SearchPaths& other);
|
SearchPaths(const SearchPaths& other);
|
||||||
SearchPaths(SearchPaths&& other) noexcept;
|
SearchPaths(SearchPaths&& other) noexcept;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include "ObjContainer/IWD/IWD.h"
|
||||||
|
|
||||||
const CommandLineOption* optionHelp = CommandLineOption::Builder::Create()
|
const CommandLineOption* optionHelp = CommandLineOption::Builder::Create()
|
||||||
.WithShortName("?")
|
.WithShortName("?")
|
||||||
@ -80,14 +81,16 @@ class Unlinker::Impl
|
|||||||
* \brief Loads a search path.
|
* \brief Loads a search path.
|
||||||
* \param searchPath The search path to load.
|
* \param searchPath The search path to load.
|
||||||
*/
|
*/
|
||||||
void LoadSearchPath(SearchPathFilesystem* searchPath)
|
void LoadSearchPath(ISearchPath* searchPath) const
|
||||||
{
|
{
|
||||||
if(m_should_load_obj)
|
if (m_should_load_obj)
|
||||||
{
|
{
|
||||||
if(m_verbose)
|
if (m_verbose)
|
||||||
{
|
{
|
||||||
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,14 +98,16 @@ class Unlinker::Impl
|
|||||||
* \brief Unloads a search path.
|
* \brief Unloads a search path.
|
||||||
* \param searchPath The search path to unload.
|
* \param searchPath The search path to unload.
|
||||||
*/
|
*/
|
||||||
void UnloadSearchPath(SearchPathFilesystem* searchPath)
|
void UnloadSearchPath(ISearchPath* searchPath) const
|
||||||
{
|
{
|
||||||
if(m_should_load_obj)
|
if (m_should_load_obj)
|
||||||
{
|
{
|
||||||
if(m_verbose)
|
if (m_verbose)
|
||||||
{
|
{
|
||||||
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +225,12 @@ class Unlinker::Impl
|
|||||||
{
|
{
|
||||||
std::string absolutePath = std::filesystem::absolute(path).string();
|
std::string absolutePath = std::filesystem::absolute(path).string();
|
||||||
|
|
||||||
|
if (!FileAPI::DirectoryExists(absolutePath))
|
||||||
|
{
|
||||||
|
printf("Could not find directory of search path: \"%s\"\n", path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SearchPathFilesystem* searchPath = new SearchPathFilesystem(absolutePath);
|
SearchPathFilesystem* searchPath = new SearchPathFilesystem(absolutePath);
|
||||||
LoadSearchPath(searchPath);
|
LoadSearchPath(searchPath);
|
||||||
m_search_paths.CommitSearchPath(searchPath);
|
m_search_paths.CommitSearchPath(searchPath);
|
||||||
@ -327,6 +338,12 @@ class Unlinker::Impl
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetVerbose(const bool verbose)
|
||||||
|
{
|
||||||
|
m_verbose = verbose;
|
||||||
|
ObjLoading::Configuration.Verbose = verbose;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Impl()
|
Impl()
|
||||||
: m_argument_parser(commandLineOptions, _countof(commandLineOptions))
|
: m_argument_parser(commandLineOptions, _countof(commandLineOptions))
|
||||||
@ -347,7 +364,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_verbose = m_argument_parser.IsOptionSpecified(optionVerbose);
|
SetVerbose(m_argument_parser.IsOptionSpecified(optionVerbose));
|
||||||
m_should_load_obj = !m_argument_parser.IsOptionSpecified(optionList);
|
m_should_load_obj = !m_argument_parser.IsOptionSpecified(optionList);
|
||||||
|
|
||||||
// Check if the user requested help
|
// Check if the user requested help
|
||||||
@ -385,7 +402,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_verbose)
|
if (m_verbose)
|
||||||
{
|
{
|
||||||
printf("Loaded zone \"%s\"\n", zone->m_name.c_str());
|
printf("Loaded zone \"%s\"\n", zone->m_name.c_str());
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ bool FileAPI::DirectoryExists(const std::string& directoryName)
|
|||||||
FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode)
|
FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode)
|
||||||
{
|
{
|
||||||
const char* modeStr;
|
const char* modeStr;
|
||||||
switch(mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case Mode::MODE_READ:
|
case Mode::MODE_READ:
|
||||||
@ -39,13 +39,13 @@ FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* handle;
|
FILE* handle;
|
||||||
if (fopen_s(&handle, filename.c_str(), modeStr) != 0)
|
if (fopen_s(&handle, filename.c_str(), modeStr) != 0)
|
||||||
{
|
{
|
||||||
return File(nullptr);
|
return File(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return File(handle);
|
return File(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAPI::File::File()
|
FileAPI::File::File()
|
||||||
@ -55,7 +55,7 @@ FileAPI::File::File()
|
|||||||
|
|
||||||
FileAPI::File::File(void* handle)
|
FileAPI::File::File(void* handle)
|
||||||
{
|
{
|
||||||
this->m_handle = handle;
|
this->m_handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAPI::File::File(File&& f) noexcept
|
FileAPI::File::File(File&& f) noexcept
|
||||||
@ -66,7 +66,7 @@ FileAPI::File::File(File&& f) noexcept
|
|||||||
|
|
||||||
FileAPI::File::~File()
|
FileAPI::File::~File()
|
||||||
{
|
{
|
||||||
this->Close();
|
this->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAPI::File& FileAPI::File::operator=(File&& f) noexcept
|
FileAPI::File& FileAPI::File::operator=(File&& f) noexcept
|
||||||
@ -79,43 +79,48 @@ FileAPI::File& FileAPI::File::operator=(File&& f) noexcept
|
|||||||
|
|
||||||
bool FileAPI::File::IsOpen()
|
bool FileAPI::File::IsOpen()
|
||||||
{
|
{
|
||||||
return this->m_handle != nullptr;
|
return this->m_handle != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileAPI::File::Read(void* buffer, const size_t elementSize, const size_t elementCount)
|
size_t FileAPI::File::Read(void* buffer, const size_t elementSize, const size_t elementCount)
|
||||||
{
|
{
|
||||||
if (!this->IsOpen())
|
if (!this->IsOpen())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return fread(buffer, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
return fread(buffer, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileAPI::File::Write(const void* data, const size_t elementSize, const size_t elementCount)
|
size_t FileAPI::File::Write(const void* data, const size_t elementSize, const size_t elementCount)
|
||||||
{
|
{
|
||||||
if (!this->IsOpen())
|
if (!this->IsOpen())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return fwrite(data, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
return fwrite(data, elementSize, elementCount, static_cast<FILE*>(m_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileAPI::File::Skip(const size_t amount)
|
void FileAPI::File::Skip(const int64_t amount)
|
||||||
{
|
{
|
||||||
if(!this->IsOpen())
|
if (!this->IsOpen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fseek(static_cast<FILE*>(m_handle), amount, SEEK_CUR);
|
_fseeki64(static_cast<FILE*>(m_handle), amount, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAPI::File::GotoEnd()
|
||||||
|
{
|
||||||
|
_fseeki64(static_cast<FILE*>(m_handle), 0, SEEK_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileAPI::File::Printf(const char* fmt, ...)
|
size_t FileAPI::File::Printf(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (!this->IsOpen())
|
if (!this->IsOpen())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
const int result = vfprintf(static_cast<FILE*>(m_handle), fmt, ap);
|
const int result = vfprintf(static_cast<FILE*>(m_handle), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -132,9 +137,9 @@ void FileAPI::File::Goto(const int64_t pos)
|
|||||||
|
|
||||||
void FileAPI::File::Close()
|
void FileAPI::File::Close()
|
||||||
{
|
{
|
||||||
if (this->m_handle != nullptr)
|
if (this->m_handle != nullptr)
|
||||||
{
|
{
|
||||||
fclose(static_cast<FILE*>(m_handle));
|
fclose(static_cast<FILE*>(m_handle));
|
||||||
this->m_handle = nullptr;
|
this->m_handle = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,10 +20,11 @@ public:
|
|||||||
virtual bool IsOpen() = 0;
|
virtual bool IsOpen() = 0;
|
||||||
virtual size_t Read(void* buffer, size_t elementSize, size_t elementCount) = 0;
|
virtual size_t Read(void* buffer, size_t elementSize, size_t elementCount) = 0;
|
||||||
virtual size_t Write(const void* data, size_t elementSize, size_t elementCount) = 0;
|
virtual size_t Write(const void* data, size_t elementSize, size_t elementCount) = 0;
|
||||||
virtual void Skip(size_t amount) = 0;
|
virtual void Skip(int64_t amount) = 0;
|
||||||
virtual size_t Printf(const char* fmt, ...) = 0;
|
virtual size_t Printf(const char* fmt, ...) = 0;
|
||||||
virtual int64_t Pos() = 0;
|
virtual int64_t Pos() = 0;
|
||||||
virtual void Goto(int64_t pos) = 0;
|
virtual void Goto(int64_t pos) = 0;
|
||||||
|
virtual void GotoEnd() = 0;
|
||||||
virtual void Close() = 0;
|
virtual void Close() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,10 +45,11 @@ public:
|
|||||||
bool IsOpen() override;
|
bool IsOpen() override;
|
||||||
size_t Read(void* buffer, size_t elementSize, size_t elementCount) override;
|
size_t Read(void* buffer, size_t elementSize, size_t elementCount) override;
|
||||||
size_t Write(const void* data, size_t elementSize, size_t elementCount) override;
|
size_t Write(const void* data, size_t elementSize, size_t elementCount) override;
|
||||||
void Skip(size_t amount) override;
|
void Skip(int64_t amount) override;
|
||||||
size_t Printf(const char* fmt, ...) override;
|
size_t Printf(const char* fmt, ...) override;
|
||||||
int64_t Pos() override;
|
int64_t Pos() override;
|
||||||
void Goto(int64_t pos) override;
|
void Goto(int64_t pos) override;
|
||||||
|
void GotoEnd() override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
src/Utils/Utils/TransformIterator.h
Normal file
26
src/Utils/Utils/TransformIterator.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
template <typename BaseIteratorType, typename SourceType, typename TargetType>
|
||||||
|
class TransformIterator
|
||||||
|
{
|
||||||
|
BaseIteratorType m_base;
|
||||||
|
std::function<TargetType(SourceType)> m_transform;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TransformIterator(BaseIteratorType base, std::function<TargetType(SourceType)> transform)
|
||||||
|
: m_base(base), m_transform(transform)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransformIterator& operator++()
|
||||||
|
{
|
||||||
|
++m_base;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(TransformIterator other) const { return m_base == other.m_base; }
|
||||||
|
bool operator!=(TransformIterator other) const { return !(m_base == other.m_base); }
|
||||||
|
TargetType operator*() { return m_transform(*m_base); }
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user