mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
ObjLoading: Add indexing and reading of files in IWDs
This commit is contained in:
parent
0abdb64832
commit
c2f3bca268
@ -1,4 +1,4 @@
|
||||
#include "ZlibFileWrapper.h"
|
||||
#include "FileToZlibWrapper.h"
|
||||
#include <cassert>
|
||||
|
||||
voidpf Wrapper_Zlib_FileOpen(voidpf opaque, const char*, int)
|
||||
@ -71,7 +71,7 @@ int Wrapper_Zlib_FileError(voidpf opaque, voidpf stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
zlib_filefunc_def ZlibFileWrapper::CreateFunctions32ForFile(FileAPI::IFile* file)
|
||||
zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(FileAPI::IFile* file)
|
||||
{
|
||||
return zlib_filefunc_def_s
|
||||
{
|
@ -3,7 +3,7 @@
|
||||
#include <ioapi.h>
|
||||
#include "Utils/FileAPI.h"
|
||||
|
||||
class ZlibFileWrapper
|
||||
class FileToZlibWrapper
|
||||
{
|
||||
public:
|
||||
static zlib_filefunc_def CreateFunctions32ForFile(FileAPI::IFile* file);
|
@ -1,27 +1,141 @@
|
||||
#include "IWD.h"
|
||||
|
||||
#include <unzip.h>
|
||||
#include <cassert>
|
||||
#include "Utils/PathUtils.h"
|
||||
#include "Utils/ZlibFileWrapper.h"
|
||||
#include <filesystem>
|
||||
#include "ObjLoading.h"
|
||||
#include "Utils/FileToZlibWrapper.h"
|
||||
|
||||
#include <unzip.h>
|
||||
#include <filesystem>
|
||||
#include <cassert>
|
||||
|
||||
ObjContainerRepository<IWD, ISearchPath> IWD::Repository;
|
||||
|
||||
class IWD::Impl : public ISearchPath, IObjContainer
|
||||
class IWDFile final : public FileAPI::IFile
|
||||
{
|
||||
public:
|
||||
class IParent
|
||||
{
|
||||
public:
|
||||
virtual ~IParent() = default;
|
||||
|
||||
virtual void OnIWDFileClose() = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
IParent* m_parent;
|
||||
bool m_open;
|
||||
size_t m_size;
|
||||
unzFile m_container;
|
||||
|
||||
public:
|
||||
IWDFile(IParent* parent, const unzFile container, const size_t size)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_container = container;
|
||||
m_size = size;
|
||||
m_open = true;
|
||||
}
|
||||
|
||||
~IWDFile()
|
||||
{
|
||||
if(m_open)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOpen() override
|
||||
{
|
||||
return m_open;
|
||||
}
|
||||
|
||||
size_t Read(void* buffer, const size_t elementSize, const size_t elementCount) override
|
||||
{
|
||||
const auto result = unzReadCurrentFile(m_container, buffer, elementSize * elementCount);
|
||||
|
||||
return result >= 0 ? static_cast<size_t>(result) : 0;
|
||||
}
|
||||
|
||||
size_t Write(const void* data, size_t elementSize, size_t elementCount) override
|
||||
{
|
||||
// This is not meant for writing.
|
||||
assert(false);
|
||||
throw std::runtime_error("This is not a stream for output!");
|
||||
}
|
||||
|
||||
void Skip(int64_t amount) override
|
||||
{
|
||||
while (amount > 0)
|
||||
{
|
||||
char temp[1024];
|
||||
const size_t toRead = amount > sizeof temp ? sizeof temp : static_cast<size_t>(amount);
|
||||
unzReadCurrentFile(m_container, temp, toRead);
|
||||
amount -= toRead;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Printf(const char* fmt, ...) override
|
||||
{
|
||||
// This is not meant for writing.
|
||||
assert(false);
|
||||
throw std::runtime_error("This is not a stream for output!");
|
||||
}
|
||||
|
||||
int64_t Pos() override
|
||||
{
|
||||
return unztell(m_container);
|
||||
}
|
||||
|
||||
void Goto(const int64_t pos) override
|
||||
{
|
||||
const auto current = Pos();
|
||||
|
||||
if(pos > current)
|
||||
{
|
||||
Skip(pos - current);
|
||||
}
|
||||
else if(pos == current)
|
||||
{
|
||||
// This is fine.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported for zip entries
|
||||
assert(false);
|
||||
throw std::runtime_error("Going backwards is not supported in IWD files!");
|
||||
}
|
||||
}
|
||||
|
||||
void GotoEnd() override
|
||||
{
|
||||
Goto(m_size);
|
||||
}
|
||||
|
||||
void Close() override
|
||||
{
|
||||
unzClose(m_container);
|
||||
m_open = false;
|
||||
|
||||
m_parent->OnIWDFileClose();
|
||||
}
|
||||
};
|
||||
|
||||
class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IParent
|
||||
{
|
||||
class IWDEntry
|
||||
{
|
||||
public:
|
||||
std::string m_name;
|
||||
unz_file_pos m_file_pos;
|
||||
size_t m_size;
|
||||
unz_file_pos m_file_pos{};
|
||||
};
|
||||
|
||||
std::string m_path;
|
||||
FileAPI::IFile* m_file;
|
||||
unzFile m_unz_file;
|
||||
|
||||
IWDFile* m_last_file;
|
||||
|
||||
std::vector<IWDEntry> m_entries;
|
||||
|
||||
public:
|
||||
@ -30,6 +144,7 @@ public:
|
||||
m_unz_file = nullptr;
|
||||
m_path = std::move(path);
|
||||
m_file = file;
|
||||
m_last_file = nullptr;
|
||||
}
|
||||
|
||||
~Impl()
|
||||
@ -49,7 +164,7 @@ public:
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
auto ioFunctions = ZlibFileWrapper::CreateFunctions32ForFile(m_file);
|
||||
auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_file);
|
||||
m_unz_file = unzOpen2("", &ioFunctions);
|
||||
|
||||
if (m_unz_file == nullptr)
|
||||
@ -72,6 +187,7 @@ public:
|
||||
{
|
||||
IWDEntry entry;
|
||||
entry.m_name = std::move(fileName);
|
||||
entry.m_size = info.uncompressed_size;
|
||||
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
||||
m_entries.push_back(entry);
|
||||
}
|
||||
@ -79,7 +195,7 @@ public:
|
||||
ret = unzGoToNextFile(m_unz_file);
|
||||
}
|
||||
|
||||
if(ObjLoading::Configuration.Verbose)
|
||||
if (ObjLoading::Configuration.Verbose)
|
||||
{
|
||||
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entries.size());
|
||||
}
|
||||
@ -94,7 +210,29 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO
|
||||
std::string iwdFilename = fileName;
|
||||
std::replace(iwdFilename.begin(), iwdFilename.end(), '\\', '/');
|
||||
|
||||
const auto iwdEntry = std::find_if(m_entries.begin(), m_entries.end(), [&iwdFilename](IWDEntry& entry) -> bool
|
||||
{
|
||||
return entry.m_name == iwdFilename;
|
||||
});
|
||||
|
||||
if (iwdEntry != m_entries.end())
|
||||
{
|
||||
if(m_last_file != nullptr)
|
||||
{
|
||||
throw std::runtime_error("Trying to open new IWD file while last one was not yet closed.");
|
||||
}
|
||||
|
||||
auto pos = iwdEntry->m_file_pos;
|
||||
unzGoToFilePos(m_unz_file, &pos);
|
||||
|
||||
if (unzOpenCurrentFile(m_unz_file) == UNZ_OK)
|
||||
{
|
||||
m_last_file = new IWDFile(this, m_unz_file, iwdEntry->m_size);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -111,7 +249,28 @@ public:
|
||||
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override
|
||||
{
|
||||
// TODO
|
||||
if(options.m_disk_files_only)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto& entry : m_entries)
|
||||
{
|
||||
std::filesystem::path entryPath(entry.m_name);
|
||||
|
||||
if(!options.m_should_include_subdirectories && entryPath.has_parent_path())
|
||||
continue;
|
||||
|
||||
if(options.m_filter_extensions && options.m_extension != entryPath.extension().string())
|
||||
continue;
|
||||
|
||||
callback(entry.m_name);
|
||||
}
|
||||
}
|
||||
|
||||
void OnIWDFileClose() override
|
||||
{
|
||||
m_last_file = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,8 +11,6 @@ IObjLoader* objLoaders[]
|
||||
new ObjLoaderT6()
|
||||
};
|
||||
|
||||
SearchPaths iwdSearchPaths;
|
||||
|
||||
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
||||
{
|
||||
for (auto* loader : objLoaders)
|
||||
@ -81,7 +79,14 @@ void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath)
|
||||
IWD::Repository.RemoveContainerReferences(searchPath);
|
||||
}
|
||||
|
||||
ISearchPath* ObjLoading::GetIWDSearchPaths()
|
||||
SearchPaths ObjLoading::GetIWDSearchPaths()
|
||||
{
|
||||
return &iwdSearchPaths;
|
||||
SearchPaths iwdPaths;
|
||||
|
||||
for(auto iwd : IWD::Repository)
|
||||
{
|
||||
iwdPaths.IncludeSearchPath(iwd);
|
||||
}
|
||||
|
||||
return iwdPaths;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "SearchPath/ISearchPath.h"
|
||||
#include "SearchPath/SearchPaths.h"
|
||||
|
||||
class ObjLoading
|
||||
{
|
||||
@ -17,7 +18,7 @@ public:
|
||||
|
||||
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
|
||||
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
|
||||
static ISearchPath* GetIWDSearchPaths();
|
||||
static SearchPaths GetIWDSearchPaths();
|
||||
|
||||
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user