diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index 87d25422..205b315b 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -15,6 +15,7 @@ #include "SearchPath/SearchPathFilesystem.h" #include "ObjContainer/IWD/IWD.h" #include "LinkerArgs.h" +#include "LinkerSearchPaths.h" #include "ZoneWriting.h" #include "Game/IW3/ZoneCreatorIW3.h" #include "ZoneCreation/ZoneCreationContext.h" @@ -40,195 +41,16 @@ const IZoneCreator* const ZONE_CREATORS[] new T6::ZoneCreator() }; -class Linker::Impl +class LinkerImpl final : public Linker { static constexpr const char* METADATA_NAME = "name"; static constexpr const char* METADATA_GAME = "game"; static constexpr const char* METADATA_GDT = "gdt"; LinkerArgs m_args; - std::vector> m_loaded_project_search_paths; - SearchPaths m_asset_search_paths; - SearchPaths m_gdt_search_paths; - SearchPaths m_source_search_paths; + LinkerSearchPaths m_search_paths; std::vector> m_loaded_zones; - /** - * \brief Loads a search path. - * \param searchPath The search path to load. - */ - void LoadSearchPath(ISearchPath* searchPath) const - { - if (m_args.m_verbose) - { - printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str()); - } - - ObjLoading::LoadIWDsInSearchPath(searchPath); - } - - /** - * \brief Unloads a search path. - * \param searchPath The search path to unload. - */ - void UnloadSearchPath(ISearchPath* searchPath) const - { - if (m_args.m_verbose) - { - printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str()); - } - - ObjLoading::UnloadIWDsInSearchPath(searchPath); - } - - SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) - { - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetAssetSearchPathsForProject(gameName, projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Adding asset search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding asset search path: " << absolutePath.string() << std::endl; - - auto searchPath = std::make_unique(searchPathStr); - LoadSearchPath(searchPath.get()); - searchPathsForProject.IncludeSearchPath(searchPath.get()); - m_loaded_project_search_paths.emplace_back(std::move(searchPath)); - } - - searchPathsForProject.IncludeSearchPath(&m_asset_search_paths); - - for (auto* iwd : IWD::Repository) - { - searchPathsForProject.IncludeSearchPath(iwd); - } - - return searchPathsForProject; - } - - SearchPaths GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) - { - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetGdtSearchPathsForProject(gameName, projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Adding gdt search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding gdt search path: " << absolutePath.string() << std::endl; - - searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); - } - - searchPathsForProject.IncludeSearchPath(&m_gdt_search_paths); - - return searchPathsForProject; - } - - SearchPaths GetSourceSearchPathsForProject(const std::string& projectName) - { - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetSourceSearchPathsForProject(projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Adding source search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding source search path: " << absolutePath.string() << std::endl; - - searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); - } - - searchPathsForProject.IncludeSearchPath(&m_source_search_paths); - - return searchPathsForProject; - } - - /** - * \brief Initializes the Linker object's search paths based on the user's input. - * \return \c true if building the search paths was successful, otherwise \c false. - */ - bool BuildProjectIndependentSearchPaths() - { - for (const auto& path : m_args.GetProjectIndependentAssetSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Adding asset search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding asset search path: " << absolutePath.string() << std::endl; - - auto searchPath = std::make_unique(absolutePath.string()); - LoadSearchPath(searchPath.get()); - m_asset_search_paths.CommitSearchPath(std::move(searchPath)); - } - - for (const auto& path : m_args.GetProjectIndependentGdtSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Loading gdt search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding gdt search path: " << absolutePath.string() << std::endl; - - m_gdt_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); - } - - for (const auto& path : m_args.GetProjectIndependentSourceSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << "Loading source search path (Not found): " << absolutePath.string() << std::endl; - continue; - } - - if (m_args.m_verbose) - std::cout << "Adding source search path: " << absolutePath.string() << std::endl; - - m_source_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); - } - - return true; - } - bool IncludeAdditionalZoneDefinitions(const std::string& initialFileName, ZoneDefinition& zoneDefinition, ISearchPath* sourceSearchPath) const { std::set sourceNames; @@ -500,7 +322,7 @@ class Linker::Impl bool BuildProject(const std::string& projectName) { - auto sourceSearchPaths = GetSourceSearchPathsForProject(projectName); + auto sourceSearchPaths = m_search_paths.GetSourceSearchPathsForProject(projectName); const auto zoneDefinition = ReadZoneDefinition(projectName, &sourceSearchPaths); if (!zoneDefinition) @@ -513,19 +335,15 @@ class Linker::Impl for (auto& c : gameName) c = static_cast(std::tolower(c)); - auto assetSearchPaths = GetAssetSearchPathsForProject(gameName, projectName); - auto gdtSearchPaths = GetGdtSearchPathsForProject(gameName, projectName); + auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName); + auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName); const auto zone = CreateZoneForDefinition(projectName, *zoneDefinition, &assetSearchPaths, &gdtSearchPaths, &sourceSearchPaths); auto result = zone != nullptr; if (zone) result = WriteZoneToFile(projectName, zone.get()); - for (const auto& loadedSearchPath : m_loaded_project_search_paths) - { - UnloadSearchPath(loadedSearchPath.get()); - } - m_loaded_project_search_paths.clear(); + m_search_paths.UnloadProjectSpecificSearchPaths(); return result; } @@ -576,18 +394,17 @@ class Linker::Impl } public: - Impl() - = default; + LinkerImpl() + : m_search_paths(m_args) + { + } - /** - * \copydoc Linker::Start - */ - bool Start(const int argc, const char** argv) + bool Start(const int argc, const char** argv) override { if (!m_args.ParseArgs(argc, argv)) return false; - if (!BuildProjectIndependentSearchPaths()) + if (!m_search_paths.BuildProjectIndependentSearchPaths()) return false; if (!LoadZones()) @@ -609,18 +426,7 @@ public: } }; -Linker::Linker() +std::unique_ptr Linker::Create() { - m_impl = new Impl(); -} - -Linker::~Linker() -{ - delete m_impl; - m_impl = nullptr; -} - -bool Linker::Start(const int argc, const char** argv) const -{ - return m_impl->Start(argc, argv); + return std::make_unique(); } diff --git a/src/Linker/Linker.h b/src/Linker/Linker.h index 3e452c90..06bb0cb0 100644 --- a/src/Linker/Linker.h +++ b/src/Linker/Linker.h @@ -1,13 +1,11 @@ #pragma once +#include class Linker { - class Impl; - Impl* m_impl; - public: - Linker(); - ~Linker(); + Linker() = default; + virtual ~Linker() = default; Linker(const Linker& other) = delete; Linker(Linker&& other) noexcept = delete; @@ -20,5 +18,7 @@ public: * \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; -}; \ No newline at end of file + virtual bool Start(int argc, const char** argv) = 0; + + static std::unique_ptr Create(); +}; diff --git a/src/Linker/LinkerSearchPaths.cpp b/src/Linker/LinkerSearchPaths.cpp new file mode 100644 index 00000000..48ce337d --- /dev/null +++ b/src/Linker/LinkerSearchPaths.cpp @@ -0,0 +1,190 @@ +#include "LinkerSearchPaths.h" + +#include +#include + +#include "ObjLoading.h" +#include "ObjContainer/IWD/IWD.h" +#include "SearchPath/SearchPathFilesystem.h" + +namespace fs = std::filesystem; + +LinkerSearchPaths::LinkerSearchPaths(const LinkerArgs& args) + : m_args(args) +{ +} + +void LinkerSearchPaths::LoadSearchPath(ISearchPath* searchPath) const +{ + if (m_args.m_verbose) + { + printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str()); + } + + ObjLoading::LoadIWDsInSearchPath(searchPath); +} + +void LinkerSearchPaths::UnloadSearchPath(ISearchPath* searchPath) const +{ + if (m_args.m_verbose) + { + printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str()); + } + + ObjLoading::UnloadIWDsInSearchPath(searchPath); +} + +SearchPaths LinkerSearchPaths::GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) +{ + SearchPaths searchPathsForProject; + + for (const auto& searchPathStr : m_args.GetAssetSearchPathsForProject(gameName, projectName)) + { + auto absolutePath = fs::absolute(searchPathStr); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Adding asset search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding asset search path: " << absolutePath.string() << std::endl; + + auto searchPath = std::make_unique(searchPathStr); + LoadSearchPath(searchPath.get()); + searchPathsForProject.IncludeSearchPath(searchPath.get()); + m_loaded_project_search_paths.emplace_back(std::move(searchPath)); + } + + searchPathsForProject.IncludeSearchPath(&m_asset_search_paths); + + for (auto* iwd : IWD::Repository) + { + searchPathsForProject.IncludeSearchPath(iwd); + } + + return searchPathsForProject; +} + +SearchPaths LinkerSearchPaths::GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) +{ + SearchPaths searchPathsForProject; + + for (const auto& searchPathStr : m_args.GetGdtSearchPathsForProject(gameName, projectName)) + { + auto absolutePath = fs::absolute(searchPathStr); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Adding gdt search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding gdt search path: " << absolutePath.string() << std::endl; + + searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); + } + + searchPathsForProject.IncludeSearchPath(&m_gdt_search_paths); + + return searchPathsForProject; +} + +SearchPaths LinkerSearchPaths::GetSourceSearchPathsForProject(const std::string& projectName) +{ + SearchPaths searchPathsForProject; + + for (const auto& searchPathStr : m_args.GetSourceSearchPathsForProject(projectName)) + { + auto absolutePath = fs::absolute(searchPathStr); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Adding source search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding source search path: " << absolutePath.string() << std::endl; + + searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); + } + + searchPathsForProject.IncludeSearchPath(&m_source_search_paths); + + return searchPathsForProject; +} + +bool LinkerSearchPaths::BuildProjectIndependentSearchPaths() +{ + for (const auto& path : m_args.GetProjectIndependentAssetSearchPaths()) + { + auto absolutePath = fs::absolute(path); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Adding asset search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding asset search path: " << absolutePath.string() << std::endl; + + auto searchPath = std::make_unique(absolutePath.string()); + LoadSearchPath(searchPath.get()); + m_asset_search_paths.CommitSearchPath(std::move(searchPath)); + } + + for (const auto& path : m_args.GetProjectIndependentGdtSearchPaths()) + { + auto absolutePath = fs::absolute(path); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Loading gdt search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding gdt search path: " << absolutePath.string() << std::endl; + + m_gdt_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); + } + + for (const auto& path : m_args.GetProjectIndependentSourceSearchPaths()) + { + auto absolutePath = fs::absolute(path); + + if (!fs::is_directory(absolutePath)) + { + if (m_args.m_verbose) + std::cout << "Loading source search path (Not found): " << absolutePath.string() << std::endl; + continue; + } + + if (m_args.m_verbose) + std::cout << "Adding source search path: " << absolutePath.string() << std::endl; + + m_source_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); + } + + return true; +} + + +void LinkerSearchPaths::UnloadProjectSpecificSearchPaths() +{ + for (const auto& loadedSearchPath : m_loaded_project_search_paths) + { + UnloadSearchPath(loadedSearchPath.get()); + } + + m_loaded_project_search_paths.clear(); +} diff --git a/src/Linker/LinkerSearchPaths.h b/src/Linker/LinkerSearchPaths.h new file mode 100644 index 00000000..ea5825d2 --- /dev/null +++ b/src/Linker/LinkerSearchPaths.h @@ -0,0 +1,46 @@ +#pragma once +#include "SearchPath/SearchPaths.h" + +#include +#include + +#include "LinkerArgs.h" + +class LinkerSearchPaths +{ +public: + explicit LinkerSearchPaths(const LinkerArgs& args); + + /** + * \brief Loads a search path. + * \param searchPath The search path to load. + */ + void LoadSearchPath(ISearchPath* searchPath) const; + + /** + * \brief Unloads a search path. + * \param searchPath The search path to unload. + */ + void UnloadSearchPath(ISearchPath* searchPath) const; + + SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName); + + SearchPaths GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName); + + SearchPaths GetSourceSearchPathsForProject(const std::string& projectName); + + /** + * \brief Initializes the Linker object's search paths based on the user's input. + * \return \c true if building the search paths was successful, otherwise \c false. + */ + bool BuildProjectIndependentSearchPaths(); + + void UnloadProjectSpecificSearchPaths(); + +private: + const LinkerArgs& m_args; + std::vector> m_loaded_project_search_paths; + SearchPaths m_asset_search_paths; + SearchPaths m_gdt_search_paths; + SearchPaths m_source_search_paths; +}; diff --git a/src/Linker/main.cpp b/src/Linker/main.cpp index 6e78bec1..36f84947 100644 --- a/src/Linker/main.cpp +++ b/src/Linker/main.cpp @@ -2,7 +2,7 @@ int main(const int argc, const char** argv) { - Linker linker; + const auto linker = Linker::Create(); - return linker.Start(argc, argv) ? 0 : 1; + return linker->Start(argc, argv) ? 0 : 1; }