2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-06-28 07:11:52 +00:00

ObjLoading: Be able to load and index IWD files

This commit is contained in:
Jan
2020-01-01 18:46:33 +01:00
parent a4d55ffae7
commit 0abdb64832
27 changed files with 667 additions and 252 deletions

View File

@ -3,10 +3,13 @@
#include "Exception/IPakLoadException.h"
#include <sstream>
#include "Utils/PathUtils.h"
const uint32_t IPak::MAGIC = 'IPAK';
const uint32_t IPak::VERSION = 0x50000;
ObjContainerRepository<IPak, Zone> IPak::Repository;
uint32_t IPak::R_HashString(const char* str, uint32_t hash)
{
for (const char* pos = str; *pos; pos++)
@ -17,8 +20,9 @@ uint32_t IPak::R_HashString(const char* str, uint32_t 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_initialized = false;
m_index_section = nullptr;
@ -34,6 +38,11 @@ IPak::~IPak()
m_data_section = nullptr;
}
std::string IPak::GetName()
{
return utils::Path::GetFilename(m_path);
}
void IPak::ReadSection()
{
IPakSection section{};

View File

@ -3,6 +3,8 @@
#include "Utils/FileAPI.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include "ObjContainer/ObjContainerReferenceable.h"
#include "ObjContainer/ObjContainerRepository.h"
#include "Zone/Zone.h"
#include <vector>
@ -11,6 +13,7 @@ class IPak final : public ObjContainerReferenceable
static const uint32_t MAGIC;
static const uint32_t VERSION;
std::string m_path;
FileAPI::IFile* m_file;
bool m_initialized;
@ -26,9 +29,13 @@ class IPak final : public ObjContainerReferenceable
void ReadHeader();
public:
explicit IPak(FileAPI::IFile* file);
static ObjContainerRepository<IPak, Zone> Repository;
IPak(std::string path, FileAPI::IFile* file);
~IPak();
std::string GetName() override;
void Initialize();
FileAPI::IFile* GetEntryData(IPakHash nameHash, IPakHash dataHash);

View File

@ -1,32 +1,166 @@
#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)
{
// TODO
return nullptr;
return m_impl->Open(fileName);
}
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
}
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.
return m_impl->Find(options, callback);
}

View File

@ -1,17 +1,28 @@
#pragma once
#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:
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;
void FindAll(std::function<void(const std::string&)> callback) override;
void FindAllOnDisk(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;
std::string GetPath() override;
std::string GetName() override;
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
};

View File

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

View File

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

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