mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +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>
|
#include <cassert>
|
||||||
|
|
||||||
voidpf Wrapper_Zlib_FileOpen(voidpf opaque, const char*, int)
|
voidpf Wrapper_Zlib_FileOpen(voidpf opaque, const char*, int)
|
||||||
@ -71,7 +71,7 @@ int Wrapper_Zlib_FileError(voidpf opaque, voidpf stream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
zlib_filefunc_def ZlibFileWrapper::CreateFunctions32ForFile(FileAPI::IFile* file)
|
zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(FileAPI::IFile* file)
|
||||||
{
|
{
|
||||||
return zlib_filefunc_def_s
|
return zlib_filefunc_def_s
|
||||||
{
|
{
|
@ -3,7 +3,7 @@
|
|||||||
#include <ioapi.h>
|
#include <ioapi.h>
|
||||||
#include "Utils/FileAPI.h"
|
#include "Utils/FileAPI.h"
|
||||||
|
|
||||||
class ZlibFileWrapper
|
class FileToZlibWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static zlib_filefunc_def CreateFunctions32ForFile(FileAPI::IFile* file);
|
static zlib_filefunc_def CreateFunctions32ForFile(FileAPI::IFile* file);
|
@ -1,27 +1,141 @@
|
|||||||
#include "IWD.h"
|
#include "IWD.h"
|
||||||
|
|
||||||
#include <unzip.h>
|
|
||||||
#include <cassert>
|
|
||||||
#include "Utils/PathUtils.h"
|
#include "Utils/PathUtils.h"
|
||||||
#include "Utils/ZlibFileWrapper.h"
|
|
||||||
#include <filesystem>
|
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
|
#include "Utils/FileToZlibWrapper.h"
|
||||||
|
|
||||||
|
#include <unzip.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
ObjContainerRepository<IWD, ISearchPath> IWD::Repository;
|
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
|
class IWDEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
unz_file_pos m_file_pos;
|
size_t m_size;
|
||||||
|
unz_file_pos m_file_pos{};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
FileAPI::IFile* m_file;
|
FileAPI::IFile* m_file;
|
||||||
unzFile m_unz_file;
|
unzFile m_unz_file;
|
||||||
|
|
||||||
|
IWDFile* m_last_file;
|
||||||
|
|
||||||
std::vector<IWDEntry> m_entries;
|
std::vector<IWDEntry> m_entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -30,6 +144,7 @@ public:
|
|||||||
m_unz_file = nullptr;
|
m_unz_file = nullptr;
|
||||||
m_path = std::move(path);
|
m_path = std::move(path);
|
||||||
m_file = file;
|
m_file = file;
|
||||||
|
m_last_file = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl()
|
~Impl()
|
||||||
@ -49,7 +164,7 @@ public:
|
|||||||
|
|
||||||
bool Initialize()
|
bool Initialize()
|
||||||
{
|
{
|
||||||
auto ioFunctions = ZlibFileWrapper::CreateFunctions32ForFile(m_file);
|
auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_file);
|
||||||
m_unz_file = unzOpen2("", &ioFunctions);
|
m_unz_file = unzOpen2("", &ioFunctions);
|
||||||
|
|
||||||
if (m_unz_file == nullptr)
|
if (m_unz_file == nullptr)
|
||||||
@ -72,6 +187,7 @@ public:
|
|||||||
{
|
{
|
||||||
IWDEntry entry;
|
IWDEntry entry;
|
||||||
entry.m_name = std::move(fileName);
|
entry.m_name = std::move(fileName);
|
||||||
|
entry.m_size = info.uncompressed_size;
|
||||||
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
||||||
m_entries.push_back(entry);
|
m_entries.push_back(entry);
|
||||||
}
|
}
|
||||||
@ -79,7 +195,7 @@ public:
|
|||||||
ret = unzGoToNextFile(m_unz_file);
|
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());
|
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entries.size());
|
||||||
}
|
}
|
||||||
@ -94,7 +210,29 @@ public:
|
|||||||
return nullptr;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -111,7 +249,28 @@ public:
|
|||||||
|
|
||||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override
|
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()
|
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)
|
||||||
@ -81,7 +79,14 @@ void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath)
|
|||||||
IWD::Repository.RemoveContainerReferences(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 "Zone/Zone.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
#include "SearchPath/SearchPaths.h"
|
||||||
|
|
||||||
class ObjLoading
|
class ObjLoading
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ public:
|
|||||||
|
|
||||||
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
|
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
|
||||||
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
|
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
|
||||||
static ISearchPath* GetIWDSearchPaths();
|
static SearchPaths GetIWDSearchPaths();
|
||||||
|
|
||||||
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user