diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 9a5c4badc..30140c35c 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -7,6 +7,12 @@ #ifndef NAZARA_ENUMS_CORE_HPP #define NAZARA_ENUMS_CORE_HPP +enum nzPlugin +{ + nzPlugin_Assimp, + nzPlugin_FreeType +}; + enum nzProcessorCap { nzProcessorCap_x64, diff --git a/include/Nazara/Core/PluginManager.hpp b/include/Nazara/Core/PluginManager.hpp new file mode 100644 index 000000000..f9d755a93 --- /dev/null +++ b/include/Nazara/Core/PluginManager.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PLUGINMANAGER_HPP +#define NAZARA_PLUGINMANAGER_HPP + +#include +#include +#include + +class NzPluginManager +{ + public: + NzPluginManager() = delete; + ~NzPluginManager() = delete; + + static bool AddDirectory(const NzString& directoryPath); + + static bool Initialize(); + + static bool Mount(nzPlugin plugin); + static bool Mount(const NzString& pluginPath); + + static void RemoveDirectory(const NzString& directoryPath); + + static void Unmount(nzPlugin plugin); + static void Unmount(const NzString& pluginPath); + + static void Uninitialize(); +}; + +#endif // NAZARA_PLUGINMANAGER_HPP diff --git a/src/Nazara/Core/PluginManager.cpp b/src/Nazara/Core/PluginManager.cpp new file mode 100644 index 000000000..5f2de2825 --- /dev/null +++ b/src/Nazara/Core/PluginManager.cpp @@ -0,0 +1,162 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + using PluginLoad = bool (*)(); + using PluginUnload = void (*)(); + + std::list s_directories; + std::map s_plugins; + + NzString s_pluginFiles[] = + { + "NazaraAssimp", // nzPlugin_Assimp + "NazaraFreetype" // nzPlugin_FreeType + }; +} + +bool NzPluginManager::AddDirectory(const NzString& directoryPath) +{ + NzString path = NzFile::AbsolutePath(directoryPath); + + if (!NzDirectory::Exists(path)) + { + NazaraWarning("Directory not existing: " + directoryPath); + return false; + } + + s_directories.push_back(directoryPath); + return true; +} + +bool NzPluginManager::Initialize() +{ + s_directories.push_back(NzFile::AbsolutePath('.')); + + NzString libDir = NzFile::AbsolutePath("lib"); + if (NzDirectory::Exists(libDir)) + s_directories.push_back(libDir); + + return true; +} + +bool NzPluginManager::Mount(nzPlugin plugin) +{ + return Mount(s_pluginFiles[plugin]); +} + +bool NzPluginManager::Mount(const NzString& pluginPath) +{ + NzString path = pluginPath; + if (!path.EndsWith(NAZARA_DYNLIB_EXTENSION)) + path += NAZARA_DYNLIB_EXTENSION; + + bool exists = false; + if (!NzFile::IsAbsolute(path)) + { + for (const NzString& dir : s_directories) + { + NzString testPath; + testPath.Reserve(dir.GetSize() + path.GetSize() + 10); + + testPath = dir; + testPath += NAZARA_DIRECTORY_SEPARATOR; + testPath += path; + + if (NzFile::Exists(testPath)) + { + path = testPath; + exists = true; + break; + } + } + } + else if (NzFile::Exists(path)) + exists = true; + + if (!exists) + { + NazaraError("Failed to find plugin file"); + return false; + } + + std::unique_ptr library(new NzDynLib(path)); + if (!library->Load()) + { + NazaraError("Failed to load plugin"); + return false; + } + + PluginLoad func = reinterpret_cast(library->GetSymbol("NzPluginLoad")); + if (!func) + { + NazaraError("Failed to get symbol NzPluginLoad"); + return false; + } + + if (!func()) + { + NazaraError("Plugin failed to load"); + return false; + } + + s_plugins[pluginPath] = library.release(); + + return true; +} + +void NzPluginManager::RemoveDirectory(const NzString& directoryPath) +{ + s_directories.remove(directoryPath); +} + +void NzPluginManager::Unmount(nzPlugin plugin) +{ + Unmount(s_pluginFiles[plugin]); +} + +void NzPluginManager::Unmount(const NzString& pluginPath) +{ + auto it = s_plugins.find(pluginPath); + if (it == s_plugins.end()) + { + NazaraError("Plugin not loaded"); + return; + } + + PluginUnload func = reinterpret_cast(it->second->GetSymbol("NzPluginUnload")); + if (func) + func(); + + it->second->Unload(); + + s_plugins.erase(it); +} + +void NzPluginManager::Uninitialize() +{ + s_directories.clear(); + + for (auto pair : s_plugins) + { + PluginUnload func = reinterpret_cast(pair.second->GetSymbol("NzPluginUnload")); + if (func) + func(); + + pair.second->Unload(); + } + + s_plugins.clear(); +}