pluginmanager.cpp

来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 1,645 行 · 第 1/4 页

CPP
1,645
字号
// PlugInManager.cpp: implementation of the CPlugInManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "io.h"
#include "Radiant.h"
#include "PlugInManager.h"
#include "PlugIn.h"
#include "DialogInfo.h"
#include "pakstuff.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPlugInManager::CPlugInManager()
{
  m_pTexturePlug = NULL;
  m_pSurfaceListPlug = NULL;
  PatchesMode = EActivePatches;
}

CPlugInManager::~CPlugInManager()
{
  Cleanup();
}

void CPlugInManager::Init(const char * pPath)
{
	Cleanup();

	// set some globals
	g_qeglobals.bSurfacePropertiesPlugin = false;
	g_qeglobals.bBSPFrontendPlugin = false;
	
	CString strPath(pPath);
	strPath += "*.dll";
	
	bool bGo = true;
	
	struct _finddata_t fileinfo;
	int handle = _findfirst (strPath, &fileinfo);
	if (handle != -1)
	{
		do
		{
			strPath.Format("%s\\%s", pPath, fileinfo.name);
			CPlugIn *pPlug = new CPlugIn();
			if (pPlug->load(strPath))
			{
				if(FillFuncTable(pPlug))		// PGM
				{
					m_PlugIns.Add(pPlug);

					pPlug->RegisterPluginEntities();

					// if this thing handles surface properties
					pPlug->InitSurfacePlugin();
					
					// will test and init if it's a BSP frontend
					pPlug->InitBSPFrontendPlugin();

					g_pParentWnd->AddPlugInMenuItem(pPlug);
					
					// if this thing handles textures
					if (pPlug->getTextureInfo() != NULL)
					{
						this->m_pTexturePlug = pPlug;
						
						// if this is a wad style texture extension, have it load everything now
						if (pPlug->getTextureInfo()->m_bWadStyle)
						{
							CString strPath = ValueForKey(g_qeglobals.d_project_entity, "texturepath");
							pPlug->loadTexture(strPath);
						}
					}
					
					if (pPlug->getSurfaceFlags() != NULL)
					{
						this->m_pSurfaceListPlug = pPlug;
					}
				}
				else
				{
					delete pPlug;				// PGM
				}
			}
			else
			{
				delete pPlug;
			}
		} while (_findnext( handle, &fileinfo ) != -1);
		_findclose (handle);
	}
	
}

void CPlugInManager::Cleanup()
{
	int i;
	for (i = 0; i < m_PlugIns.GetSize(); i++)
	{
		CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
		plug->free();
		delete plug;
	}
	m_PlugIns.RemoveAll();
	
	for (i = 0; i < m_BrushHandles.GetSize(); i++)
	{
		brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
		Brush_Free(pb);
	}
	m_BrushHandles.RemoveAll();
	
	for (i = 0; i < m_EntityHandles.GetSize(); i++)
	{
		entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
		Entity_Free(pe);
	}
	m_EntityHandles.RemoveAll();
	
	// patches
	// these are linked into the map
	m_PatchesHandles.RemoveAll();
	// these patches were allocated by Radiant on plugin request
	// if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
	// in which case we are supposed to delete them
	// or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
	// erased and we are trying a second time, therefore crashing ..
	//++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
#ifdef _DEBUG
	if (m_PluginPatches.GetSize() != 0)
		Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
#endif
/*	for (i = 0; i < m_PluginPatches.GetSize(); i++)
	{
		patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
		if (pMesh->pSymbiot)
			delete pMesh;
	}
	m_PluginPatches.RemoveAll(); */
}

void CPlugInManager::Dispatch(int n, const char * p)
{
  for (int i = 0; i < m_PlugIns.GetSize(); i++)
  {
    CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
    if (plug->ownsCommandID(n))
    {
      vec3_t vMin, vMax;
    	if (selected_brushes.next == &selected_brushes)
      {
        vMin[0] = vMin[1] = vMin[2] = 0;
        VectorCopy(vMin, vMax);
      }
      else
      {
        Select_GetBounds (vMin, vMax);
      }
      plug->dispatchCommand(p, vMin, vMax, QE_SingleBrush(true));	// PGM -- added quiet
      break;
    }
  }
}

// creates a dummy brush in the active brushes list
// FIXME : is this one really USED ?
void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	
	brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
	Entity_LinkBrush (world_entity, pBrush);
	Brush_Build(pBrush);
	Brush_AddToList (pBrush, &active_brushes);
	Select_Brush(pBrush);
	Sys_UpdateWindows(W_ALL);
}

LPVOID CPlugInManager::CreateBrushHandle()
{
	brush_t *pb = Brush_Alloc();
	pb->numberId = g_nBrushId++;
  m_BrushHandles.Add(pb);
  return (LPVOID)pb;
}

void CPlugInManager::DeleteBrushHandle(void * vp)
{
  CPtrArray* pHandles[3];
  pHandles[0] = &m_SelectedBrushHandles;
  pHandles[1] = &m_ActiveBrushHandles;
  pHandles[2] = &m_BrushHandles;

  for (int j = 0; j < 3; j++)
  {
    for (int i = 0; i < pHandles[j]->GetSize(); i++)
    {
      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
      if (pb == reinterpret_cast<brush_t*>(vp))
      {
        if (j == 2)
        {
          // only remove it from the list if it is work area
          // this allows the selected and active list indexes to remain constant
          // throughout a session (i.e. between an allocate and release)
          pHandles[j]->RemoveAt(i);
        }
        Brush_Free(pb);
		Sys_MarkMapModified();		// PGM
        return;
      }
    }
  }
}

void CPlugInManager::CommitBrushHandleToMap(void * vp)
{
  g_bScreenUpdates = false; 
  for (int i = 0; i < m_BrushHandles.GetSize(); i++)
  {
    brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
    if (pb == reinterpret_cast<brush_t*>(vp))
    {
      m_BrushHandles.RemoveAt(i);
	  Entity_LinkBrush (world_entity, pb);
      Brush_Build(pb);
	  Brush_AddToList (pb, &active_brushes);
      Select_Brush(pb);
    }
  }
  g_bScreenUpdates = true; 
  Sys_UpdateWindows(W_ALL);
}

void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
{
  brush_t *bp = FindBrushHandle(vp);
  if (bp != NULL)
  {
		face_t *f = Face_Alloc();
		f->texdef = g_qeglobals.d_texturewin.texdef;
		f->texdef.flags &= ~SURF_KEEP;
		f->texdef.contents &= ~CONTENTS_KEEP;
		f->next = bp->brush_faces;
		bp->brush_faces = f;
		VectorCopy (v1, f->planepts[0]);
		VectorCopy (v2, f->planepts[1]);
		VectorCopy (v3, f->planepts[2]);
  }
}

brush_t* CPlugInManager::FindBrushHandle(void * vp)
{
  CPtrArray* pHandles[4];
  pHandles[0] = &m_SelectedBrushHandles;
  pHandles[1] = &m_ActiveBrushHandles;
  pHandles[2] = &m_BrushHandles;
  pHandles[3] = &m_EntityBrushHandles;

  for (int j = 0; j < 4; j++)
  {
    for (int i = 0; i < pHandles[j]->GetSize(); i++)
    {
      brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
      if (pb == reinterpret_cast<brush_t*>(vp))
      {
        return pb;
      }
    }
  }
  return NULL;
}

patchMesh_t* CPlugInManager::FindPatchHandle(int index)
{
	switch (PatchesMode)
	{
	case EActivePatches:
	case ESelectedPatches:
		if ( index < m_PatchesHandles.GetSize() )
		{
			brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
			return pb->pPatch;
		}
#ifdef _DEBUG
		Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
#endif
		break;
	case EAllocatedPatches:
		if ( index < m_PluginPatches.GetSize() )
		{
			patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
			return pPatch;
		}
#ifdef _DEBUG
		Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
#endif
		break;
	}
	return NULL;
}

LPVOID WINAPI QERApp_CreateBrushHandle()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
}

void WINAPI QERApp_DeleteBrushHandle(LPVOID vp)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
}

void WINAPI QERApp_CommitBrushHandleToMap(LPVOID vp)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
}

void WINAPI QERApp_AddFace(LPVOID vp, vec3_t v1, vec3_t v2, vec3_t v3)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
}

void WINAPI QERApp_DeleteSelection()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  Select_Delete();
}

void WINAPI QERApp_SysMsg(LPCSTR pMsg)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  CString str = pMsg;
  Sys_Printf(str.GetBuffer(0));
}

// NOTE: called only in case of plugin error. We can try a plugin refresh instead of a straight crash ?
void WINAPI QERApp_ErrorMsg(LPCSTR pMsg)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	CString str = pMsg;
	Error(str.GetBuffer(0));
}

void WINAPI QERApp_InfoMsg(LPCSTR pMsg)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  ShowInfoDialog(pMsg);
}

void WINAPI QERApp_HideInfoMsg()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  HideInfoDialog();
}

//=====
//PGM
void WINAPI QERApp_PositionView(vec3_t	v1, vec3_t v2)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	g_pParentWnd->ActiveXY()->SetOrigin(v1);
	// FIXME - implement this!
	Sys_UpdateWindows(W_ALL);
}
//PGM
//=====

//FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
bool g_bPlugWait = false;
bool g_bPlugOK = false;
int  g_nPlugCount = 0;

void _PlugDone(bool b, int n)
{
  g_bPlugWait = false;
  g_bPlugOK = b;
  g_nPlugCount = n;
}

void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, LPCSTR pMsg)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
  ShowInfoDialog(pMsg);
  g_bPlugWait = true;
  g_bPlugOK = false;
  g_nPlugCount = 0;
//  g_nPlugCount=nMax-1;
  AcquirePath(nMax, &_PlugDone);
  while (g_bPlugWait)
  {
    MSG msg;
    if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
    { 
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  HideInfoDialog();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?