Files
FC1/Editor/PluginManager.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

298 lines
7.8 KiB
C++

// PluginManager.cpp: implementation of the CPluginManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PluginManager.h"
#include <io.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPluginManager::CPluginManager()
{
m_pIAssociatedPlugin = NULL;
m_iAssociatedPluginUIID = 0;
}
CPluginManager::~CPluginManager()
{
CleanUp();
}
bool CPluginManager::LoadAllPlugins(CString strPath)
{
//////////////////////////////////////////////////////////////////////
// Load all plugin DLLs which are in the passed path
//////////////////////////////////////////////////////////////////////
CFileEnum cDLLFiles;
__finddata64_t sFile;
char szFilePath[_MAX_PATH];
HMODULE hPlugin = NULL;
pfnCreatePluginInstance pfnFactory = NULL;
PLUGIN_INIT_PARAM sInitParam = { GetIEditor(), NULL /*TODO: CEngineSingleton::GetGameInterface()*/ };
IPlugin *pIPlugin = NULL;
bool bReturn;
uint8 iUIID = 0;
// Terminate old plugins first
CleanUp();
CLogFile::WriteLine("Loading plugins...");
if (!PathFileExists(strPath.GetBuffer(0)))
{
CLogFile::FormatLine("Can't find plugin directory '%s'", strPath.GetBuffer(1));
return false;
}
if (cDLLFiles.StartEnumeration(strPath.GetBuffer(1), "*.DLL", &sFile))
{
do
{
// Construct the full filepath of the current file
strcpy(szFilePath, strPath.GetBuffer(0));
PathAddBackslash(szFilePath);
strcat(szFilePath, sFile.name);
// Load the plugin's DLL
hPlugin = LoadLibrary(szFilePath);
if (!hPlugin)
{
CLogFile::FormatLine("Can't load plugin DLL '%s' !", szFilePath);
ASSERT(hPlugin);
continue;
}
// Query the factory pointer
pfnFactory = (pfnCreatePluginInstance) GetProcAddress(hPlugin, "CreatePluginInstance");
if (!pfnFactory)
{
CLogFile::WriteLine("Can't query plugin DLL factory pointer !");
ASSERT(pfnFactory);
continue;
}
// Create an instance of the plugin
pIPlugin = pfnFactory(&sInitParam);
if (!pIPlugin)
{
CLogFile::FormatLine("Can't create instance of plugin DLL '%s' !", szFilePath);
ASSERT(pfnFactory);
continue;
}
// Push the plugin on the list
m_lPlugins.push_back(pIPlugin);
// Temporary associate the editor interface with the current plugin. This ensures
// that all calls from to it are associated with it
// We need a special user inteface ID for the plugin which is stored with all created
// UI elements. This allows us later to easly identify the plugin which handles events
// of the UI element
SetAssociatedPlugin(pIPlugin,iUIID);
// Ask the plugin to create its user interface now
bReturn = pIPlugin->CreateUIElements();
if (!bReturn)
{
CLogFile::WriteLine("Plugin failed to create UI elements !");
ASSERT(bReturn);
continue;
}
// No plugin is associated with the interface now, this helps to catch errors where
// plugins access the UI creation function of the editor interface outside of
// CreateUIElements()
SetAssociatedPlugin(NULL,0);
// Store the UI ID - Plugin association in the map
m_mUIIDPluginMap[iUIID] = pIPlugin;
// Next UIID
iUIID++;
if (iUIID == 0)
{
CLogFile::WriteLine("Too many plugins loaded, 256 maximum !");
AfxMessageBox("Too many plugins loaded, 256 maximum !");
ASSERT(false);
return true;
}
// Write log string about plugin
CLogFile::FormatLine("Successfully loaded plugin '%s' version '%i' (GUID: %s)",
pIPlugin->GetPluginName(), pIPlugin->GetPluginVersion(), pIPlugin->GetPluginGUID());
} while (cDLLFiles.GetNextFile(&sFile));
}
return true;
}
void CPluginManager::CleanUp()
{
//////////////////////////////////////////////////////////////////////
// Unloads all plugins without asking for unsaved data etc.
//////////////////////////////////////////////////////////////////////
PluginIt it;
CLogFile::WriteLine("Unloading all previous plugins");
// Release the plugins
for (it=m_lPlugins.begin(); it!=m_lPlugins.end(); it++)
(* it)->Release();
// Clear the list of plugins
m_lPlugins.clear();
// Clear the map of plugin event maps
m_mPluginEventMap.clear();
// Clear the map of UI IDs and plugins
m_mUIIDPluginMap.clear();
}
void CPluginManager::NewDocument()
{
//////////////////////////////////////////////////////////////////////
// Resets the status of all plugins to be prepared for a document
// change
//////////////////////////////////////////////////////////////////////
PluginIt it;
CLogFile::WriteLine("Resetting the state of all plugins");
for (it=m_lPlugins.begin(); it!=m_lPlugins.end(); it++)
(* it)->ResetContent();
}
IPlugin * CPluginManager::GetPluginByGUID(const char * pszGUID)
{
//////////////////////////////////////////////////////////////////////
// Try to find a plugin which the passed GUID
//////////////////////////////////////////////////////////////////////
PluginIt it;
for (it=m_lPlugins.begin(); it!=m_lPlugins.end(); it++)
{
if (strcmp((* it)->GetPluginGUID(), pszGUID) == 0)
return (* it);
}
return NULL;
}
IPlugin * CPluginManager::GetPluginByUIID(uint8 iUserInterfaceID)
{
//////////////////////////////////////////////////////////////////////
// Try to find the plugin which has the passed user interface ID
//////////////////////////////////////////////////////////////////////
UIIDPluginIt it;
// Look up the plugin pointer from the list
it = m_mUIIDPluginMap.find(iUserInterfaceID);
// Found ?
if (it == m_mUIIDPluginMap.end())
return NULL;
return (* it).second;
}
IUIEvent * CPluginManager::GetEventByIDAndPluginID(uint8 iPluginID, uint8 iEvtID)
{
//////////////////////////////////////////////////////////////////////
// Return the event interface of a user interface element which is
// specified by its ID and the user interface ID of the plugin which
// created the UI element
//////////////////////////////////////////////////////////////////////
IPlugin * pIPlugin = NULL;
EventHandlerIt EventIt;
PluginEventIt PluginIt;
// Try to get the plugin pointer
pIPlugin = GetPluginByUIID(iPluginID);
// Failed ?
if (!pIPlugin)
return NULL;
// Try to get the event map for the plugin
PluginIt = m_mPluginEventMap.find(pIPlugin);
// Failed ?
if (PluginIt == m_mPluginEventMap.end())
return NULL;
// Try to get the event handler for the passed event ID
EventIt = (* PluginIt).second.find(iEvtID);
// Failed ?
if (EventIt == (* PluginIt).second.end())
return NULL;
return (* EventIt).second;
}
bool CPluginManager::CanAllPluginsExitNow()
{
//////////////////////////////////////////////////////////////////////
// Calls the CanExitNow() function of all plugins
//////////////////////////////////////////////////////////////////////
PluginIt it;
for (it=m_lPlugins.begin(); it!=m_lPlugins.end(); it++)
{
if (!(* it)->CanExitNow())
return false;
}
return true;
}
bool CPluginManager::CallExport(const char * pszGamePath)
{
//////////////////////////////////////////////////////////////////////
// Call the export function for all plugins
//////////////////////////////////////////////////////////////////////
PluginIt it;
for (it=m_lPlugins.begin(); it!=m_lPlugins.end(); it++)
{
if (!(* it)->ExportDataToGame(pszGamePath))
return false;
}
return true;
}
void CPluginManager::AddHandlerForCmdID(IPlugin *pIPluginOfHandler, uint8 iCmdID, IUIEvent *pIEvt)
{
//////////////////////////////////////////////////////////////////////
// Associates the UI element ID dwCmdID of the plugin
// pIPluginOfHandler with the event handler pIEvt
//////////////////////////////////////////////////////////////////////
(m_mPluginEventMap[pIPluginOfHandler])[iCmdID] = pIEvt;
}
void CPluginManager::SetAssociatedPlugin(IPlugin * pIPlugin,uint8 iUIID)
{
m_pIAssociatedPlugin = pIPlugin;
m_iAssociatedPluginUIID = iUIID;
};