mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Unlinker/ObjLoading: Add skeleton for dynamically loading search paths based on current zone
This commit is contained in:
parent
5f833969f9
commit
153f8f2e89
@ -27,13 +27,13 @@ bool ObjLoaderT6::SupportsZone(Zone* zone)
|
|||||||
return zone->m_game == &g_GameT6;
|
return zone->m_game == &g_GameT6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadIPakForZone(std::string ipakName, Zone* zone)
|
void ObjLoaderT6::LoadIPakForZone(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
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadReferencedContainersForZone(Zone* zone)
|
void ObjLoaderT6::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->GetPools());
|
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->GetPools());
|
||||||
const int zoneNameHash = Com_HashKey(zone->m_name.c_str(), 64);
|
const int zoneNameHash = Com_HashKey(zone->m_name.c_str(), 64);
|
||||||
@ -55,6 +55,7 @@ void ObjLoaderT6::LoadReferencedContainersForZone(Zone* zone)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoaderT6::LoadObjDataForZone(Zone* zone)
|
void ObjLoaderT6::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ 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(std::string ipakName, Zone* zone);
|
static void LoadIPakForZone(const std::string& ipakName, Zone* zone);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool SupportsZone(Zone* zone) override;
|
bool SupportsZone(Zone* zone) override;
|
||||||
void LoadReferencedContainersForZone(Zone* zone) override;
|
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) override;
|
||||||
void LoadObjDataForZone(Zone* zone) override;
|
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) override;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
#include "Zone/Zone.h"
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
class IObjLoader
|
class IObjLoader
|
||||||
@ -8,6 +9,6 @@ public:
|
|||||||
virtual ~IObjLoader() = default;
|
virtual ~IObjLoader() = default;
|
||||||
|
|
||||||
virtual bool SupportsZone(Zone* zone) = 0;
|
virtual bool SupportsZone(Zone* zone) = 0;
|
||||||
virtual void LoadReferencedContainersForZone(Zone* zone) = 0;
|
virtual void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
||||||
virtual void LoadObjDataForZone(Zone* zone) = 0;
|
virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) = 0;
|
||||||
};
|
};
|
@ -0,0 +1,32 @@
|
|||||||
|
#include "IWD.h"
|
||||||
|
|
||||||
|
IWD::IWD(std::string path)
|
||||||
|
{
|
||||||
|
m_path = std::move(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAPI::IFile* IWD::Open(const std::string& fileName)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IWD::FindAll(std::function<void(const std::string&)> callback)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void IWD::FindAllOnDisk(std::function<void(const std::string&)> callback)
|
||||||
|
{
|
||||||
|
// Files inside an IWD are not on the disk's file system directly. Therefore do nothing here.
|
||||||
|
}
|
||||||
|
|
||||||
|
void IWD::FindByExtension(const std::string& extension, 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.
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
|
class IWD final : public ISearchPath
|
||||||
|
{
|
||||||
|
std::string m_path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IWD(std::string path);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
@ -8,25 +8,25 @@ IObjLoader* objLoaders[]
|
|||||||
new ObjLoaderT6()
|
new ObjLoaderT6()
|
||||||
};
|
};
|
||||||
|
|
||||||
void ObjLoading::LoadReferencedContainersForZone(Zone* zone)
|
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
for (auto* loader : objLoaders)
|
for (auto* loader : objLoaders)
|
||||||
{
|
{
|
||||||
if (loader->SupportsZone(zone))
|
if (loader->SupportsZone(zone))
|
||||||
{
|
{
|
||||||
loader->LoadReferencedContainersForZone(zone);
|
loader->LoadReferencedContainersForZone(searchPath, zone);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoading::LoadObjDataForZone(Zone* zone)
|
void ObjLoading::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
||||||
{
|
{
|
||||||
for (auto* loader : objLoaders)
|
for (auto* loader : objLoaders)
|
||||||
{
|
{
|
||||||
if (loader->SupportsZone(zone))
|
if (loader->SupportsZone(zone))
|
||||||
{
|
{
|
||||||
loader->LoadObjDataForZone(zone);
|
loader->LoadObjDataForZone(searchPath, zone);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Zone/Zone.h"
|
#include "Zone/Zone.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
class ObjLoading
|
class ObjLoading
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void LoadReferencedContainersForZone(Zone* zone);
|
static void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone);
|
||||||
static void LoadObjDataForZone(Zone* zone);
|
|
||||||
static void UnloadContainersOfZone(Zone* zone);
|
static void UnloadContainersOfZone(Zone* zone);
|
||||||
|
|
||||||
|
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
||||||
};
|
};
|
@ -2,11 +2,43 @@
|
|||||||
|
|
||||||
#include "Utils/FileAPI.h"
|
#include "Utils/FileAPI.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class ISearchPath
|
class ISearchPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ISearchPath() = default;
|
virtual ~ISearchPath() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Opens a file relative to the search path.
|
||||||
|
* \param fileName The relative path to the file to open.
|
||||||
|
* \return A pointer to an \c IFile object to read the found file or \c nullptr when no file could be found.
|
||||||
|
*/
|
||||||
virtual FileAPI::IFile* Open(const std::string& fileName) = 0;
|
virtual FileAPI::IFile* Open(const std::string& fileName) = 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.
|
||||||
|
*/
|
||||||
|
virtual void FindAll(std::function<void(const std::string&)> callback) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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;
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
#include "SearchPathFilesystem.h"
|
||||||
|
#include "Utils/PathUtils.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
SearchPathFilesystem::SearchPathFilesystem(std::string path)
|
||||||
|
{
|
||||||
|
m_path = std::move(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& SearchPathFilesystem::GetPath() const
|
||||||
|
{
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAPI::IFile* SearchPathFilesystem::Open(const std::string& fileName)
|
||||||
|
{
|
||||||
|
FileAPI::File file = FileAPI::Open(utils::Path::Combine(m_path, fileName), FileAPI::Mode::MODE_READ);
|
||||||
|
|
||||||
|
if (file.IsOpen())
|
||||||
|
{
|
||||||
|
return new FileAPI::File(std::move(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SearchPathFilesystem::FindAll(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(entry->path().string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPathFilesystem::FindOnDiskByExtension(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(absolute(entryPath).string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ISearchPath.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SearchPathFilesystem final : public ISearchPath
|
||||||
|
{
|
||||||
|
std::string m_path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SearchPathFilesystem(std::string path);
|
||||||
|
const std::string& GetPath() 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;
|
||||||
|
};
|
@ -1,11 +1,17 @@
|
|||||||
#include "SearchPaths.h"
|
#include "SearchPaths.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
SearchPaths::SearchPaths() = default;
|
||||||
|
|
||||||
SearchPaths::~SearchPaths()
|
SearchPaths::~SearchPaths()
|
||||||
{
|
{
|
||||||
for(auto searchPath : m_search_paths)
|
for(auto searchPathToFree : m_to_free)
|
||||||
{
|
{
|
||||||
delete searchPath;
|
delete searchPathToFree;
|
||||||
}
|
}
|
||||||
|
m_to_free.clear();
|
||||||
|
|
||||||
m_search_paths.clear();
|
m_search_paths.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +43,9 @@ SearchPaths& SearchPaths::operator=(SearchPaths&& other) noexcept
|
|||||||
|
|
||||||
FileAPI::IFile* SearchPaths::Open(const std::string& fileName)
|
FileAPI::IFile* SearchPaths::Open(const std::string& fileName)
|
||||||
{
|
{
|
||||||
for(auto searchPath : m_search_paths)
|
for(auto searchPathEntry : m_search_paths)
|
||||||
{
|
{
|
||||||
auto* file = searchPath->Open(fileName);
|
auto* file = searchPathEntry->Open(fileName);
|
||||||
|
|
||||||
if(file != nullptr)
|
if(file != nullptr)
|
||||||
{
|
{
|
||||||
@ -50,7 +56,46 @@ FileAPI::IFile* SearchPaths::Open(const std::string& fileName)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchPaths::AddSearchPath(ISearchPath* searchPath)
|
|
||||||
|
void SearchPaths::FindAll(const std::function<void(const std::string&)> callback)
|
||||||
|
{
|
||||||
|
for (auto searchPathEntry : m_search_paths)
|
||||||
|
{
|
||||||
|
searchPathEntry->FindAll(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPaths::FindAllOnDisk(const std::function<void(const std::string&)> callback)
|
||||||
|
{
|
||||||
|
for (auto searchPathEntry : m_search_paths)
|
||||||
|
{
|
||||||
|
searchPathEntry->FindAllOnDisk(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPaths::CommitSearchPath(ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
m_search_paths.push_back(searchPath);
|
||||||
|
m_to_free.push_back(searchPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPaths::IncludeSearchPath(ISearchPath* searchPath)
|
||||||
{
|
{
|
||||||
m_search_paths.push_back(searchPath);
|
m_search_paths.push_back(searchPath);
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,41 @@
|
|||||||
class SearchPaths final : public ISearchPath
|
class SearchPaths final : public ISearchPath
|
||||||
{
|
{
|
||||||
std::vector<ISearchPath*> m_search_paths;
|
std::vector<ISearchPath*> m_search_paths;
|
||||||
|
std::vector<ISearchPath*> m_to_free;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using iterator = std::vector<ISearchPath*>::iterator;
|
using iterator = std::vector<ISearchPath*>::iterator;
|
||||||
|
|
||||||
|
SearchPaths();
|
||||||
~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;
|
||||||
|
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;
|
||||||
|
|
||||||
SearchPaths(const SearchPaths& other);
|
SearchPaths(const SearchPaths& other);
|
||||||
SearchPaths(SearchPaths&& other) noexcept;
|
SearchPaths(SearchPaths&& other) noexcept;
|
||||||
SearchPaths& operator=(const SearchPaths& other);
|
SearchPaths& operator=(const SearchPaths& other);
|
||||||
SearchPaths& operator=(SearchPaths&& other) noexcept;
|
SearchPaths& operator=(SearchPaths&& other) noexcept;
|
||||||
|
|
||||||
void AddSearchPath(ISearchPath* searchPath);
|
/**
|
||||||
|
* \brief Adds a search path that gets deleted upon destruction of the \c SearchPaths object.
|
||||||
|
* \param searchPath The search path to add.
|
||||||
|
*/
|
||||||
|
void CommitSearchPath(ISearchPath* searchPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a search path that does \b NOT get deleted upon destruction of the \c SearchPaths object.
|
||||||
|
* \param searchPath The search path to add.
|
||||||
|
*/
|
||||||
|
void IncludeSearchPath(ISearchPath* searchPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Removes a search path from the \c SearchPaths object. If the search path was committed then it will \b NOT be deleted when destructing the \c SearchPaths object.
|
||||||
|
* \param searchPath The search path to remove.
|
||||||
|
*/
|
||||||
void RemoveSearchPath(ISearchPath* searchPath);
|
void RemoveSearchPath(ISearchPath* searchPath);
|
||||||
|
|
||||||
iterator begin();
|
iterator begin();
|
||||||
|
430
src/Unlinker/Unlinker.cpp
Normal file
430
src/Unlinker/Unlinker.cpp
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
#include "Unlinker.h"
|
||||||
|
|
||||||
|
#include "Utils/Arguments/ArgumentParser.h"
|
||||||
|
#include "Utils/Arguments/UsageInformation.h"
|
||||||
|
#include "ZoneLoading.h"
|
||||||
|
#include "ObjWriting.h"
|
||||||
|
#include "ContentPrinter.h"
|
||||||
|
#include "Utils/PathUtils.h"
|
||||||
|
#include "Utils/FileAPI.h"
|
||||||
|
#include "ObjLoading.h"
|
||||||
|
#include "SearchPath/SearchPaths.h"
|
||||||
|
#include "SearchPath/SearchPathFilesystem.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <regex>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
const CommandLineOption* optionHelp = CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("?")
|
||||||
|
.WithLongName("help")
|
||||||
|
.WithDescription("Displays usage information.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* optionVerbose = CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("v")
|
||||||
|
.WithLongName("verbose")
|
||||||
|
.WithDescription("Outputs a lot more and more detailed messages.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* optionMinimalZoneFile = CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("min")
|
||||||
|
.WithLongName("minimal-zone")
|
||||||
|
.WithDescription(
|
||||||
|
"Minimizes the size of the zone file output by only including assets that are not a dependency of another asset.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* optionList = CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("l")
|
||||||
|
.WithLongName("list")
|
||||||
|
.WithDescription(
|
||||||
|
"Lists the contents of a zone instead of writing them to the disk.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* optionOutputFolder = CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("o")
|
||||||
|
.WithLongName("output-folder")
|
||||||
|
.WithDescription(
|
||||||
|
"Specifies the output folder containing the contents of the unlinked zones. Defaults to ./%zoneName%")
|
||||||
|
.WithParameter("outputFolderPath")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* optionSearchPath = CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("search-path")
|
||||||
|
.WithDescription(
|
||||||
|
"Specifies a semi-colon separated list of paths to search for additional game files.")
|
||||||
|
.WithParameter("searchPathString")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* commandLineOptions[]
|
||||||
|
{
|
||||||
|
optionHelp,
|
||||||
|
optionVerbose,
|
||||||
|
optionMinimalZoneFile,
|
||||||
|
optionList,
|
||||||
|
optionOutputFolder,
|
||||||
|
optionSearchPath
|
||||||
|
};
|
||||||
|
|
||||||
|
class Unlinker::Impl
|
||||||
|
{
|
||||||
|
SearchPaths m_search_paths;
|
||||||
|
SearchPathFilesystem* m_last_zone_search_path;
|
||||||
|
std::set<std::string> m_absolute_search_paths;
|
||||||
|
|
||||||
|
ArgumentParser m_argument_parser;
|
||||||
|
bool m_verbose;
|
||||||
|
bool m_should_load_obj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Loads a search path.
|
||||||
|
* \param searchPath The search path to load.
|
||||||
|
*/
|
||||||
|
void LoadSearchPath(SearchPathFilesystem* searchPath)
|
||||||
|
{
|
||||||
|
if(m_should_load_obj)
|
||||||
|
{
|
||||||
|
if(m_verbose)
|
||||||
|
{
|
||||||
|
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Unloads a search path.
|
||||||
|
* \param searchPath The search path to unload.
|
||||||
|
*/
|
||||||
|
void UnloadSearchPath(SearchPathFilesystem* searchPath)
|
||||||
|
{
|
||||||
|
if(m_should_load_obj)
|
||||||
|
{
|
||||||
|
if(m_verbose)
|
||||||
|
{
|
||||||
|
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Loads all search paths that are valid for the specified zone and returns them.
|
||||||
|
* \param zonePath The path to the zone file that should be prepared for.
|
||||||
|
* \return A \c SearchPaths object that contains all search paths that should be considered when loading the specified zone.
|
||||||
|
*/
|
||||||
|
SearchPaths GetSearchPathsForZone(const std::string& zonePath)
|
||||||
|
{
|
||||||
|
SearchPaths searchPathsForZone;
|
||||||
|
const std::string absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string();
|
||||||
|
|
||||||
|
if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory)
|
||||||
|
{
|
||||||
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
||||||
|
}
|
||||||
|
else if (m_absolute_search_paths.find(absoluteZoneDirectory) == m_absolute_search_paths.end())
|
||||||
|
{
|
||||||
|
if (m_last_zone_search_path != nullptr)
|
||||||
|
{
|
||||||
|
UnloadSearchPath(m_last_zone_search_path);
|
||||||
|
delete m_last_zone_search_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_last_zone_search_path = new SearchPathFilesystem(absoluteZoneDirectory);
|
||||||
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
||||||
|
LoadSearchPath(m_last_zone_search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchPathsForZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Splits a path string as user input into a list of paths.
|
||||||
|
* \param pathsString The path string that was taken as user input.
|
||||||
|
* \param output A set for strings to save the output to.
|
||||||
|
* \return \c true if the user input was valid and could be processed successfully, otherwise \c false.
|
||||||
|
*/
|
||||||
|
static bool ParsePathsString(const std::string& pathsString, std::set<std::string>& output)
|
||||||
|
{
|
||||||
|
std::ostringstream currentPath;
|
||||||
|
bool pathStart = true;
|
||||||
|
int quotationPos = 0; // 0 = before quotations, 1 = in quotations, 2 = after quotations
|
||||||
|
|
||||||
|
for (auto character : pathsString)
|
||||||
|
{
|
||||||
|
switch (character)
|
||||||
|
{
|
||||||
|
case '"':
|
||||||
|
if (quotationPos == 0 && pathStart)
|
||||||
|
{
|
||||||
|
quotationPos = 1;
|
||||||
|
}
|
||||||
|
else if (quotationPos == 1)
|
||||||
|
{
|
||||||
|
quotationPos = 2;
|
||||||
|
pathStart = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
if (quotationPos != 1)
|
||||||
|
{
|
||||||
|
std::string path = currentPath.str();
|
||||||
|
if (!path.empty())
|
||||||
|
{
|
||||||
|
output.insert(path);
|
||||||
|
currentPath = std::ostringstream();
|
||||||
|
}
|
||||||
|
|
||||||
|
pathStart = true;
|
||||||
|
quotationPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentPath << character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
currentPath << character;
|
||||||
|
pathStart = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPath.tellp() > 0)
|
||||||
|
{
|
||||||
|
output.insert(currentPath.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes the Unlinker object's search paths based on the user's input.
|
||||||
|
* \return \c true if building the search paths was successful, otherwise \c false.
|
||||||
|
*/
|
||||||
|
bool BuildSearchPaths()
|
||||||
|
{
|
||||||
|
if (m_argument_parser.IsOptionSpecified(optionSearchPath))
|
||||||
|
{
|
||||||
|
std::set<std::string> pathList;
|
||||||
|
if (!ParsePathsString(m_argument_parser.GetValueForOption(optionSearchPath), pathList))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& path : pathList)
|
||||||
|
{
|
||||||
|
std::string absolutePath = std::filesystem::absolute(path).string();
|
||||||
|
|
||||||
|
SearchPathFilesystem* searchPath = new SearchPathFilesystem(absolutePath);
|
||||||
|
LoadSearchPath(searchPath);
|
||||||
|
m_search_paths.CommitSearchPath(searchPath);
|
||||||
|
|
||||||
|
m_absolute_search_paths.insert(absolutePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_verbose)
|
||||||
|
{
|
||||||
|
printf("%u SearchPaths%s\n", m_absolute_search_paths.size(), !m_absolute_search_paths.empty() ? ":" : "");
|
||||||
|
for (const auto& absoluteSearchPath : m_absolute_search_paths)
|
||||||
|
{
|
||||||
|
printf(" \"%s\"\n", absoluteSearchPath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_absolute_search_paths.empty())
|
||||||
|
{
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Prints a command line usage help text for the Unlinker tool to stdout.
|
||||||
|
*/
|
||||||
|
static void PrintUsage()
|
||||||
|
{
|
||||||
|
UsageInformation usage("unlinker.exe");
|
||||||
|
|
||||||
|
for (auto commandLineOption : commandLineOptions)
|
||||||
|
{
|
||||||
|
usage.AddCommandLineOption(commandLineOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
usage.AddArgument("pathToZone");
|
||||||
|
usage.SetVariableArguments(true);
|
||||||
|
|
||||||
|
usage.Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Converts the output path specified by command line arguments to a path applies for the specified zone.
|
||||||
|
* \param path The path that was specified as user input.
|
||||||
|
* \param zone The zone to resolve the path input for.
|
||||||
|
* \return An output path for the zone based on the user input.
|
||||||
|
*/
|
||||||
|
std::string ResolveOutputFolderPath(const std::string& path, Zone* zone) const
|
||||||
|
{
|
||||||
|
return std::regex_replace(path, std::regex("%zoneName%"), zone->m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Performs the tasks specified by the command line arguments on the specified zone.
|
||||||
|
* \param zone The zone to handle.
|
||||||
|
* \return \c true if handling the zone was successful, otherwise \c false.
|
||||||
|
*/
|
||||||
|
bool HandleZone(Zone* zone)
|
||||||
|
{
|
||||||
|
if (m_argument_parser.IsOptionSpecified(optionList))
|
||||||
|
{
|
||||||
|
const ContentPrinter printer(zone);
|
||||||
|
printer.PrintContent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const bool minimalisticZoneDefinition = m_argument_parser.IsOptionSpecified(optionMinimalZoneFile);
|
||||||
|
|
||||||
|
std::string outputFolderPath;
|
||||||
|
if (m_argument_parser.IsOptionSpecified(optionOutputFolder))
|
||||||
|
{
|
||||||
|
outputFolderPath = ResolveOutputFolderPath(m_argument_parser.GetValueForOption(optionOutputFolder),
|
||||||
|
zone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputFolderPath = ResolveOutputFolderPath("./%zoneName%", zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAPI::DirectoryCreate(outputFolderPath);
|
||||||
|
|
||||||
|
const std::string zoneDefinitionFileFolder = utils::Path::Combine(outputFolderPath, "zone_source");
|
||||||
|
FileAPI::DirectoryCreate(zoneDefinitionFileFolder);
|
||||||
|
|
||||||
|
FileAPI::File zoneDefinitionFile = FileAPI::Open(
|
||||||
|
utils::Path::Combine(zoneDefinitionFileFolder, zone->m_name + ".zone"),
|
||||||
|
FileAPI::Mode::MODE_WRITE);
|
||||||
|
|
||||||
|
if (zoneDefinitionFile.IsOpen())
|
||||||
|
{
|
||||||
|
ObjWriting::WriteZoneDefinition(zone, &zoneDefinitionFile, minimalisticZoneDefinition);
|
||||||
|
ObjWriting::DumpZone(zone, outputFolderPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Failed to open file for zone definition file of zone \"%s\".\n", zone->m_name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneDefinitionFile.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Impl()
|
||||||
|
: m_argument_parser(commandLineOptions, _countof(commandLineOptions))
|
||||||
|
{
|
||||||
|
m_last_zone_search_path = nullptr;
|
||||||
|
m_verbose = false;
|
||||||
|
m_should_load_obj = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \copydoc Unlinker::Start
|
||||||
|
*/
|
||||||
|
bool Start(const int argc, const char** argv)
|
||||||
|
{
|
||||||
|
if (!m_argument_parser.ParseArguments(argc, argv))
|
||||||
|
{
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_verbose = m_argument_parser.IsOptionSpecified(optionVerbose);
|
||||||
|
m_should_load_obj = !m_argument_parser.IsOptionSpecified(optionList);
|
||||||
|
|
||||||
|
// Check if the user requested help
|
||||||
|
if (m_argument_parser.IsOptionSpecified(optionHelp))
|
||||||
|
{
|
||||||
|
PrintUsage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> arguments = m_argument_parser.GetArguments();
|
||||||
|
const size_t argCount = arguments.size();
|
||||||
|
if (argCount <= 1)
|
||||||
|
{
|
||||||
|
// No zones to load specified...
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BuildSearchPaths())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned argIndex = 1; argIndex < argCount; argIndex++)
|
||||||
|
{
|
||||||
|
const std::string& zonePath = arguments[argIndex];
|
||||||
|
std::string absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string();
|
||||||
|
|
||||||
|
SearchPaths searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory);
|
||||||
|
|
||||||
|
Zone* zone = ZoneLoading::LoadZone(zonePath);
|
||||||
|
if (zone == nullptr)
|
||||||
|
{
|
||||||
|
printf("Failed to load zone \"%s\".\n", zonePath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_verbose)
|
||||||
|
{
|
||||||
|
printf("Loaded zone \"%s\"\n", zone->m_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_should_load_obj)
|
||||||
|
{
|
||||||
|
ObjLoading::LoadReferencedContainersForZone(&searchPathsForZone, zone);
|
||||||
|
ObjLoading::LoadObjDataForZone(&searchPathsForZone, zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HandleZone(zone))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_should_load_obj)
|
||||||
|
{
|
||||||
|
ObjLoading::UnloadContainersOfZone(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Unlinker::Unlinker()
|
||||||
|
{
|
||||||
|
m_impl = new Impl();
|
||||||
|
}
|
||||||
|
|
||||||
|
Unlinker::~Unlinker()
|
||||||
|
{
|
||||||
|
delete m_impl;
|
||||||
|
m_impl = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Unlinker::Start(const int argc, const char** argv) const
|
||||||
|
{
|
||||||
|
return m_impl->Start(argc, argv);
|
||||||
|
}
|
24
src/Unlinker/Unlinker.h
Normal file
24
src/Unlinker/Unlinker.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Unlinker
|
||||||
|
{
|
||||||
|
class Impl;
|
||||||
|
Impl* m_impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Unlinker();
|
||||||
|
~Unlinker();
|
||||||
|
|
||||||
|
Unlinker(const Unlinker& other) = delete;
|
||||||
|
Unlinker(Unlinker&& other) noexcept = delete;
|
||||||
|
Unlinker& operator=(const Unlinker& other) = delete;
|
||||||
|
Unlinker& operator=(Unlinker&& other) noexcept = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Starts the Unlinker application logic.
|
||||||
|
* \param argc The amount of command line arguments specified.
|
||||||
|
* \param argv The command line arguments.
|
||||||
|
* \return \c true if the application was successful or \c false if an error occurred.
|
||||||
|
*/
|
||||||
|
bool Start(int argc, const char** argv) const;
|
||||||
|
};
|
@ -1,163 +1,8 @@
|
|||||||
#include "Utils/Arguments/ArgumentParser.h"
|
#include "Unlinker.h"
|
||||||
#include "Utils/Arguments/UsageInformation.h"
|
|
||||||
#include "ZoneLoading.h"
|
|
||||||
#include "ObjWriting.h"
|
|
||||||
#include "ContentPrinter.h"
|
|
||||||
#include "Utils/PathUtils.h"
|
|
||||||
#include "Utils/FileAPI.h"
|
|
||||||
|
|
||||||
#include <regex>
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
const CommandLineOption* optionHelp = CommandLineOption::Builder::Create()
|
|
||||||
.WithShortName("?")
|
|
||||||
.WithLongName("help")
|
|
||||||
.WithDescription("Displays usage information.")
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
const CommandLineOption* optionMinimalZoneFile = CommandLineOption::Builder::Create()
|
|
||||||
.WithShortName("min")
|
|
||||||
.WithLongName("minimal-zone")
|
|
||||||
.WithDescription(
|
|
||||||
"Minimizes the size of the zone file output by only including assets that are not a dependency of another asset.")
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
const CommandLineOption* optionList = CommandLineOption::Builder::Create()
|
|
||||||
.WithShortName("l")
|
|
||||||
.WithLongName("list")
|
|
||||||
.WithDescription(
|
|
||||||
"Lists the contents of a zone instead of writing them to the disk.")
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
const CommandLineOption* optionOutputFolder = CommandLineOption::Builder::Create()
|
|
||||||
.WithShortName("o")
|
|
||||||
.WithLongName("output-folder")
|
|
||||||
.WithDescription(
|
|
||||||
"Specifies the output folder containing the contents of the unlinked zones. Defaults to ./%zoneName%")
|
|
||||||
.WithParameter("outputFolderPath")
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
const CommandLineOption* commandLineOptions[]
|
|
||||||
{
|
|
||||||
optionHelp,
|
|
||||||
optionMinimalZoneFile,
|
|
||||||
optionList,
|
|
||||||
optionOutputFolder
|
|
||||||
};
|
|
||||||
|
|
||||||
void PrintUsage()
|
|
||||||
{
|
|
||||||
UsageInformation usage("unlinker.exe");
|
|
||||||
|
|
||||||
for (auto commandLineOption : commandLineOptions)
|
|
||||||
{
|
|
||||||
usage.AddCommandLineOption(commandLineOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.AddArgument("pathToZone");
|
|
||||||
usage.SetVariableArguments(true);
|
|
||||||
|
|
||||||
usage.Print();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ResolveOutputFolderPath(const std::string& path, Zone* zone)
|
|
||||||
{
|
|
||||||
return std::regex_replace(path, std::regex("%zoneName%"), zone->m_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HandleZone(Zone* zone, ArgumentParser* argumentParser)
|
|
||||||
{
|
|
||||||
if (argumentParser->IsOptionSpecified(optionList))
|
|
||||||
{
|
|
||||||
const ContentPrinter printer(zone);
|
|
||||||
printer.PrintContent();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool minimalisticZoneDefinition = argumentParser->IsOptionSpecified(optionMinimalZoneFile);
|
|
||||||
|
|
||||||
std::string outputFolderPath;
|
|
||||||
|
|
||||||
if (argumentParser->IsOptionSpecified(optionOutputFolder))
|
|
||||||
{
|
|
||||||
outputFolderPath = ResolveOutputFolderPath(argumentParser->GetValueForOption(optionOutputFolder), zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outputFolderPath = ResolveOutputFolderPath("./%zoneName%", zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAPI::DirectoryCreate(outputFolderPath);
|
|
||||||
|
|
||||||
const std::string zoneDefinitionFileFolder = utils::Path::Combine(outputFolderPath, "zone_source");
|
|
||||||
FileAPI::DirectoryCreate(zoneDefinitionFileFolder);
|
|
||||||
|
|
||||||
FileAPI::File zoneDefinitionFile = FileAPI::Open(
|
|
||||||
utils::Path::Combine(zoneDefinitionFileFolder, zone->m_name + ".zone"),
|
|
||||||
FileAPI::Mode::MODE_WRITE);
|
|
||||||
|
|
||||||
if (zoneDefinitionFile.IsOpen())
|
|
||||||
{
|
|
||||||
ObjWriting::WriteZoneDefinition(zone, &zoneDefinitionFile, minimalisticZoneDefinition);
|
|
||||||
ObjWriting::DumpZone(zone, outputFolderPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Failed to open file for zone definition file of zone '%s'.\n", zone->m_name.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneDefinitionFile.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(const int argc, const char** argv)
|
int main(const int argc, const char** argv)
|
||||||
{
|
{
|
||||||
ArgumentParser argumentParser(commandLineOptions, _countof(commandLineOptions));
|
Unlinker unlinker;
|
||||||
|
|
||||||
if (!argumentParser.ParseArguments(argc, argv))
|
return unlinker.Start(argc, argv) ? 0 : 1;
|
||||||
{
|
|
||||||
PrintUsage();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentParser.IsOptionSpecified(optionHelp))
|
|
||||||
{
|
|
||||||
PrintUsage();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<std::string> arguments = argumentParser.GetArguments();
|
|
||||||
const size_t argCount = arguments.size();
|
|
||||||
if (argCount <= 1)
|
|
||||||
{
|
|
||||||
PrintUsage();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned argIndex = 1; argIndex < argCount; argIndex++)
|
|
||||||
{
|
|
||||||
const std::string& zonePath = arguments[argIndex];
|
|
||||||
|
|
||||||
Zone* zone = ZoneLoading::LoadZone(zonePath);
|
|
||||||
if (zone == nullptr)
|
|
||||||
{
|
|
||||||
printf("Failed to load zone '%s'.\n", zonePath.c_str());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjLoading::LoadReferencedContainersForZone(zone);
|
|
||||||
ObjLoading::LoadObjDataForZone(zone);
|
|
||||||
|
|
||||||
if(!HandleZone(zone, &argumentParser))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user