Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

PlugInManager.cpp (47542B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // PlugInManager.cpp: implementation of the CPlugInManager class.
     23 //
     24 //////////////////////////////////////////////////////////////////////
     25 
     26 #include "stdafx.h"
     27 #include "io.h"
     28 #include "Radiant.h"
     29 #include "PlugInManager.h"
     30 #include "PlugIn.h"
     31 #include "DialogInfo.h"
     32 #include "pakstuff.h"
     33 
     34 #ifdef _DEBUG
     35 #undef THIS_FILE
     36 static char THIS_FILE[]=__FILE__;
     37 #define new DEBUG_NEW
     38 #endif
     39 
     40 //////////////////////////////////////////////////////////////////////
     41 // Construction/Destruction
     42 //////////////////////////////////////////////////////////////////////
     43 
     44 CPlugInManager::CPlugInManager()
     45 {
     46   m_pTexturePlug = NULL;
     47   m_pSurfaceListPlug = NULL;
     48   PatchesMode = EActivePatches;
     49 }
     50 
     51 CPlugInManager::~CPlugInManager()
     52 {
     53   Cleanup();
     54 }
     55 
     56 void CPlugInManager::Init(const char * pPath)
     57 {
     58 	Cleanup();
     59 
     60 	// set some globals
     61 	g_qeglobals.bSurfacePropertiesPlugin = false;
     62 	g_qeglobals.bBSPFrontendPlugin = false;
     63 	
     64 	CString strPath(pPath);
     65 	strPath += "*.dll";
     66 	
     67 	bool bGo = true;
     68 	
     69 	struct _finddata_t fileinfo;
     70 	int handle = _findfirst (strPath, &fileinfo);
     71 	if (handle != -1)
     72 	{
     73 		do
     74 		{
     75 			strPath.Format("%s\\%s", pPath, fileinfo.name);
     76 			CPlugIn *pPlug = new CPlugIn();
     77 			if (pPlug->load(strPath))
     78 			{
     79 				if(FillFuncTable(pPlug))		// PGM
     80 				{
     81 					m_PlugIns.Add(pPlug);
     82 
     83 					pPlug->RegisterPluginEntities();
     84 
     85 					// if this thing handles surface properties
     86 					pPlug->InitSurfacePlugin();
     87 					
     88 					// will test and init if it's a BSP frontend
     89 					pPlug->InitBSPFrontendPlugin();
     90 
     91 					g_pParentWnd->AddPlugInMenuItem(pPlug);
     92 					
     93 					// if this thing handles textures
     94 					if (pPlug->getTextureInfo() != NULL)
     95 					{
     96 						this->m_pTexturePlug = pPlug;
     97 						
     98 						// if this is a wad style texture extension, have it load everything now
     99 						if (pPlug->getTextureInfo()->m_bWadStyle)
    100 						{
    101 							CString strPath = ValueForKey(g_qeglobals.d_project_entity, "texturepath");
    102 							pPlug->loadTexture(strPath);
    103 						}
    104 					}
    105 					
    106 					if (pPlug->getSurfaceFlags() != NULL)
    107 					{
    108 						this->m_pSurfaceListPlug = pPlug;
    109 					}
    110 				}
    111 				else
    112 				{
    113 					delete pPlug;				// PGM
    114 				}
    115 			}
    116 			else
    117 			{
    118 				delete pPlug;
    119 			}
    120 		} while (_findnext( handle, &fileinfo ) != -1);
    121 		_findclose (handle);
    122 	}
    123 	
    124 }
    125 
    126 void CPlugInManager::Cleanup()
    127 {
    128 	int i;
    129 	for (i = 0; i < m_PlugIns.GetSize(); i++)
    130 	{
    131 		CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
    132 		plug->free();
    133 		delete plug;
    134 	}
    135 	m_PlugIns.RemoveAll();
    136 	
    137 	for (i = 0; i < m_BrushHandles.GetSize(); i++)
    138 	{
    139 		brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
    140 		Brush_Free(pb);
    141 	}
    142 	m_BrushHandles.RemoveAll();
    143 	
    144 	for (i = 0; i < m_EntityHandles.GetSize(); i++)
    145 	{
    146 		entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
    147 		Entity_Free(pe);
    148 	}
    149 	m_EntityHandles.RemoveAll();
    150 	
    151 	// patches
    152 	// these are linked into the map
    153 	m_PatchesHandles.RemoveAll();
    154 	// these patches were allocated by Radiant on plugin request
    155 	// if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
    156 	// in which case we are supposed to delete them
    157 	// or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
    158 	// erased and we are trying a second time, therefore crashing ..
    159 	//++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
    160 #ifdef _DEBUG
    161 	if (m_PluginPatches.GetSize() != 0)
    162 		Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
    163 #endif
    164 /*	for (i = 0; i < m_PluginPatches.GetSize(); i++)
    165 	{
    166 		patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
    167 		if (pMesh->pSymbiot)
    168 			delete pMesh;
    169 	}
    170 	m_PluginPatches.RemoveAll(); */
    171 }
    172 
    173 void CPlugInManager::Dispatch(int n, const char * p)
    174 {
    175   for (int i = 0; i < m_PlugIns.GetSize(); i++)
    176   {
    177     CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
    178     if (plug->ownsCommandID(n))
    179     {
    180       vec3_t vMin, vMax;
    181     	if (selected_brushes.next == &selected_brushes)
    182       {
    183         vMin[0] = vMin[1] = vMin[2] = 0;
    184         VectorCopy(vMin, vMax);
    185       }
    186       else
    187       {
    188         Select_GetBounds (vMin, vMax);
    189       }
    190       plug->dispatchCommand(p, vMin, vMax, QE_SingleBrush(true));	// PGM -- added quiet
    191       break;
    192     }
    193   }
    194 }
    195 
    196 // creates a dummy brush in the active brushes list
    197 // FIXME : is this one really USED ?
    198 void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
    199 {
    200 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    201 	
    202 	brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
    203 	Entity_LinkBrush (world_entity, pBrush);
    204 	Brush_Build(pBrush);
    205 	Brush_AddToList (pBrush, &active_brushes);
    206 	Select_Brush(pBrush);
    207 	Sys_UpdateWindows(W_ALL);
    208 }
    209 
    210 LPVOID CPlugInManager::CreateBrushHandle()
    211 {
    212 	brush_t *pb = Brush_Alloc();
    213 	pb->numberId = g_nBrushId++;
    214   m_BrushHandles.Add(pb);
    215   return (LPVOID)pb;
    216 }
    217 
    218 void CPlugInManager::DeleteBrushHandle(void * vp)
    219 {
    220   CPtrArray* pHandles[3];
    221   pHandles[0] = &m_SelectedBrushHandles;
    222   pHandles[1] = &m_ActiveBrushHandles;
    223   pHandles[2] = &m_BrushHandles;
    224 
    225   for (int j = 0; j < 3; j++)
    226   {
    227     for (int i = 0; i < pHandles[j]->GetSize(); i++)
    228     {
    229       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
    230       if (pb == reinterpret_cast<brush_t*>(vp))
    231       {
    232         if (j == 2)
    233         {
    234           // only remove it from the list if it is work area
    235           // this allows the selected and active list indexes to remain constant
    236           // throughout a session (i.e. between an allocate and release)
    237           pHandles[j]->RemoveAt(i);
    238         }
    239         Brush_Free(pb);
    240 		Sys_MarkMapModified();		// PGM
    241         return;
    242       }
    243     }
    244   }
    245 }
    246 
    247 void CPlugInManager::CommitBrushHandleToMap(void * vp)
    248 {
    249   g_bScreenUpdates = false; 
    250   for (int i = 0; i < m_BrushHandles.GetSize(); i++)
    251   {
    252     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
    253     if (pb == reinterpret_cast<brush_t*>(vp))
    254     {
    255       m_BrushHandles.RemoveAt(i);
    256 	  Entity_LinkBrush (world_entity, pb);
    257       Brush_Build(pb);
    258 	  Brush_AddToList (pb, &active_brushes);
    259       Select_Brush(pb);
    260     }
    261   }
    262   g_bScreenUpdates = true; 
    263   Sys_UpdateWindows(W_ALL);
    264 }
    265 
    266 void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
    267 {
    268   brush_t *bp = FindBrushHandle(vp);
    269   if (bp != NULL)
    270   {
    271 		face_t *f = Face_Alloc();
    272 		f->texdef = g_qeglobals.d_texturewin.texdef;
    273 		f->texdef.flags &= ~SURF_KEEP;
    274 		f->texdef.contents &= ~CONTENTS_KEEP;
    275 		f->next = bp->brush_faces;
    276 		bp->brush_faces = f;
    277 		VectorCopy (v1, f->planepts[0]);
    278 		VectorCopy (v2, f->planepts[1]);
    279 		VectorCopy (v3, f->planepts[2]);
    280   }
    281 }
    282 
    283 brush_t* CPlugInManager::FindBrushHandle(void * vp)
    284 {
    285   CPtrArray* pHandles[4];
    286   pHandles[0] = &m_SelectedBrushHandles;
    287   pHandles[1] = &m_ActiveBrushHandles;
    288   pHandles[2] = &m_BrushHandles;
    289   pHandles[3] = &m_EntityBrushHandles;
    290 
    291   for (int j = 0; j < 4; j++)
    292   {
    293     for (int i = 0; i < pHandles[j]->GetSize(); i++)
    294     {
    295       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
    296       if (pb == reinterpret_cast<brush_t*>(vp))
    297       {
    298         return pb;
    299       }
    300     }
    301   }
    302   return NULL;
    303 }
    304 
    305 patchMesh_t* CPlugInManager::FindPatchHandle(int index)
    306 {
    307 	switch (PatchesMode)
    308 	{
    309 	case EActivePatches:
    310 	case ESelectedPatches:
    311 		if ( index < m_PatchesHandles.GetSize() )
    312 		{
    313 			brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
    314 			return pb->pPatch;
    315 		}
    316 #ifdef _DEBUG
    317 		Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
    318 #endif
    319 		break;
    320 	case EAllocatedPatches:
    321 		if ( index < m_PluginPatches.GetSize() )
    322 		{
    323 			patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
    324 			return pPatch;
    325 		}
    326 #ifdef _DEBUG
    327 		Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
    328 #endif
    329 		break;
    330 	}
    331 	return NULL;
    332 }
    333 
    334 LPVOID WINAPI QERApp_CreateBrushHandle()
    335 {
    336 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    337   return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
    338 }
    339 
    340 void WINAPI QERApp_DeleteBrushHandle(LPVOID vp)
    341 {
    342 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    343   g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
    344 }
    345 
    346 void WINAPI QERApp_CommitBrushHandleToMap(LPVOID vp)
    347 {
    348 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    349   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
    350 }
    351 
    352 void WINAPI QERApp_AddFace(LPVOID vp, vec3_t v1, vec3_t v2, vec3_t v3)
    353 {
    354 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    355   g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
    356 }
    357 
    358 void WINAPI QERApp_DeleteSelection()
    359 {
    360 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    361   Select_Delete();
    362 }
    363 
    364 void WINAPI QERApp_SysMsg(LPCSTR pMsg)
    365 {
    366 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    367   CString str = pMsg;
    368   Sys_Printf(str.GetBuffer(0));
    369 }
    370 
    371 // NOTE: called only in case of plugin error. We can try a plugin refresh instead of a straight crash ?
    372 void WINAPI QERApp_ErrorMsg(LPCSTR pMsg)
    373 {
    374 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    375 	CString str = pMsg;
    376 	Error(str.GetBuffer(0));
    377 }
    378 
    379 void WINAPI QERApp_InfoMsg(LPCSTR pMsg)
    380 {
    381 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    382   ShowInfoDialog(pMsg);
    383 }
    384 
    385 void WINAPI QERApp_HideInfoMsg()
    386 {
    387 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    388   HideInfoDialog();
    389 }
    390 
    391 //=====
    392 //PGM
    393 void WINAPI QERApp_PositionView(vec3_t	v1, vec3_t v2)
    394 {
    395 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    396 	g_pParentWnd->ActiveXY()->SetOrigin(v1);
    397 	// FIXME - implement this!
    398 	Sys_UpdateWindows(W_ALL);
    399 }
    400 //PGM
    401 //=====
    402 
    403 //FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
    404 bool g_bPlugWait = false;
    405 bool g_bPlugOK = false;
    406 int  g_nPlugCount = 0;
    407 
    408 void _PlugDone(bool b, int n)
    409 {
    410   g_bPlugWait = false;
    411   g_bPlugOK = b;
    412   g_nPlugCount = n;
    413 }
    414 
    415 void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, LPCSTR pMsg)
    416 {
    417 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    418   ShowInfoDialog(pMsg);
    419   g_bPlugWait = true;
    420   g_bPlugOK = false;
    421   g_nPlugCount = 0;
    422 //  g_nPlugCount=nMax-1;
    423   AcquirePath(nMax, &_PlugDone);
    424   while (g_bPlugWait)
    425   {
    426     MSG msg;
    427     if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
    428     { 
    429       TranslateMessage(&msg);
    430       DispatchMessage(&msg);
    431     }
    432   }
    433   HideInfoDialog();
    434   
    435   pData->m_nCount = 0;
    436   pData->m_pVectors = NULL;
    437 
    438   if (g_bPlugOK && g_nPlugCount > 0)
    439   {
    440     pData->m_nCount = g_nPlugCount;
    441     pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
    442     vec3_t *pOut = pData->m_pVectors;
    443     for (int i = 0; i < g_nPlugCount; i++)
    444     {
    445 	memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
    446 	pOut++;
    447     }
    448   }
    449 }
    450 
    451 void WINAPI QERApp_AddFaceData(LPVOID pv, _QERFaceData *pData)
    452 {
    453 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    454 
    455 	brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    456   if (pBrush != NULL)
    457   {
    458 		face_t *f = Face_Alloc();
    459 		f->texdef = g_qeglobals.d_texturewin.texdef;
    460 		f->texdef.flags = pData->m_nFlags;
    461     f->texdef.contents = pData->m_nContents;
    462     f->texdef.value = pData->m_nValue;
    463     f->texdef.rotate = pData->m_fRotate;
    464     f->texdef.shift[0] = pData->m_fShift[0];
    465     f->texdef.shift[1] = pData->m_fShift[1];
    466     f->texdef.scale[0] = pData->m_fScale[0];
    467     f->texdef.scale[1] = pData->m_fScale[1];
    468     //strcpy(f->texdef.name, pData->m_TextureName);
    469     f->texdef.SetName(pData->m_TextureName);
    470 		f->next = pBrush->brush_faces;
    471 		pBrush->brush_faces = f;
    472 		VectorCopy (pData->m_v1, f->planepts[0]);
    473 		VectorCopy (pData->m_v2, f->planepts[1]);
    474 		VectorCopy (pData->m_v3, f->planepts[2]);
    475 		Sys_MarkMapModified();		// PGM
    476   }
    477 }
    478 
    479 int WINAPI QERApp_GetFaceCount(LPVOID pv)
    480 {
    481 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    482   int n = 0;
    483   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    484   if (pBrush != NULL)
    485   {
    486 	  for (face_t *f = pBrush->brush_faces ; f; f = f->next)
    487     {
    488       n++;
    489     }
    490   }
    491   return n;
    492 }
    493 
    494 _QERFaceData* WINAPI QERApp_GetFaceData(LPVOID pv, int nFaceIndex)
    495 {
    496 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    497   static _QERFaceData face;
    498   int n = 0;
    499   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    500 
    501   if (pBrush != NULL)
    502   {
    503     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
    504     {
    505 
    506 #ifdef _DEBUG
    507 		if (!pBrush->brush_faces)
    508 		{
    509 			Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
    510 			return NULL;
    511 		}
    512 #endif
    513 
    514       if (n == nFaceIndex)
    515       {
    516         face.m_nContents = f->texdef.contents;
    517         face.m_nFlags = f->texdef.flags;
    518         face.m_fRotate = f->texdef.rotate;
    519         face.m_fScale[0] = f->texdef.scale[0];
    520         face.m_fScale[1] = f->texdef.scale[1];
    521         face.m_fShift[0] = f->texdef.shift[0];
    522         face.m_fShift[1] = f->texdef.shift[1];
    523         face.m_nValue = f->texdef.value;
    524         strcpy(face.m_TextureName, f->texdef.name);
    525         VectorCopy(f->planepts[0], face.m_v1);
    526         VectorCopy(f->planepts[1], face.m_v2);
    527         VectorCopy(f->planepts[2], face.m_v3);
    528         return &face;
    529       }
    530       n++;
    531     }
    532   }
    533   return NULL;
    534 }
    535 
    536 void WINAPI QERApp_SetFaceData(LPVOID pv, int nFaceIndex, _QERFaceData *pData)
    537 {
    538 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    539 	int n = 0;
    540 	brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    541 
    542 	if (pBrush != NULL)
    543 	{
    544 		for (face_t *f = pBrush->brush_faces ; f; f = f->next)
    545 		{
    546 			if (n == nFaceIndex)
    547 			{
    548 				f->texdef.flags = pData->m_nFlags;
    549 				f->texdef.contents = pData->m_nContents;
    550 				f->texdef.value = pData->m_nValue;
    551 				f->texdef.rotate = pData->m_fRotate;
    552 				f->texdef.shift[0] = pData->m_fShift[0];
    553 				f->texdef.shift[1] = pData->m_fShift[1];
    554 				f->texdef.scale[0] = pData->m_fScale[0];
    555 				f->texdef.scale[1] = pData->m_fScale[1];
    556 				//strcpy(f->texdef.name, pData->m_TextureName);
    557 				f->texdef.SetName(pData->m_TextureName);
    558 				VectorCopy(pData->m_v1, f->planepts[0]);
    559 				VectorCopy(pData->m_v2, f->planepts[1]);
    560 				VectorCopy(pData->m_v3, f->planepts[2]);
    561 				Sys_MarkMapModified();		// PGM
    562 				return;						// PGM
    563 			}
    564 			n++;
    565 		}
    566 	}
    567 }
    568 
    569 void WINAPI QERApp_DeleteFace(LPVOID pv, int nFaceIndex)
    570 {
    571 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    572   int n = 0;
    573   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    574   if (pBrush != NULL)
    575   {
    576     face_t *pPrev = pBrush->brush_faces;
    577 	  for (face_t *f = pBrush->brush_faces; f; f = f->next)
    578     {
    579       if (n == nFaceIndex)
    580       {
    581         pPrev->next = f->next;
    582 			  Face_Free (f);
    583 		Sys_MarkMapModified();		// PGM
    584         return;
    585       }
    586       n++;
    587       pPrev = f;
    588     }
    589   }
    590 }
    591 
    592 //==========
    593 //PGM
    594 void WINAPI QERApp_BuildBrush (LPVOID pv)
    595 {
    596 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    597 	brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    598 	if (pBrush != NULL)
    599 	{
    600 		Brush_Build(pBrush);
    601 		Sys_UpdateWindows(W_ALL);
    602 	}
    603 }
    604 
    605 //Timo : another version with bConvert flag
    606 //++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
    607 void WINAPI QERApp_BuildBrush2 (LPVOID pv, int bConvert)
    608 {
    609 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    610 	brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    611 	if (pBrush != NULL)
    612 	{
    613 		Brush_Build( pBrush, true, true, bConvert );
    614 		Sys_UpdateWindows(W_ALL);
    615 	}
    616 }
    617 
    618 void WINAPI QERApp_SelectBrush (LPVOID pv)
    619 {
    620 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    621 	brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    622 	if (pBrush != NULL)
    623 	{
    624 		Select_Brush(pBrush, false);
    625 		Sys_UpdateWindows(W_ALL);
    626 	}
    627 
    628 }
    629 
    630 void WINAPI QERApp_DeselectBrush (LPVOID pv)
    631 {
    632 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    633 	// FIXME - implement this!
    634 }
    635 
    636 void WINAPI QERApp_ResetPlugins()
    637 {
    638 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    639   g_pParentWnd->OnPluginsRefresh();
    640 }
    641 
    642 void WINAPI QERApp_DeselectAllBrushes ()
    643 {
    644 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    645 	Select_Deselect();
    646 	Sys_UpdateWindows(W_ALL);
    647 }
    648 //PGM
    649 //==========
    650 
    651 void WINAPI QERApp_TextureBrush(LPVOID pv, LPCSTR pName)
    652 {
    653 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    654   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
    655   if (pBrush != NULL)
    656   {
    657 	  for (face_t *f = pBrush->brush_faces ; f; f = f->next)
    658     {
    659       //strcpy(f->texdef.name, pName);
    660       f->texdef.SetName(pName);
    661     }
    662     Sys_MarkMapModified();		// PGM
    663   }
    664 }
    665 
    666 int WINAPI QERApp_SelectedBrushCount()
    667 {
    668 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    669   int n = 0;
    670 	for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
    671 	{
    672     n++;
    673   }
    674   return n;
    675 }
    676 
    677 int WINAPI QERApp_ActiveBrushCount()
    678 {
    679 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    680   int n = 0;
    681 	for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
    682 	{
    683     n++;
    684   }
    685   return n;
    686 }
    687 
    688 int WINAPI QERApp_AllocateSelectedBrushHandles()
    689 {
    690 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    691   int n = 0;
    692 	for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
    693 	{
    694     n++;
    695     g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
    696   }
    697   return n;
    698 }
    699 
    700 int WINAPI QERApp_AllocateActiveBrushHandles()
    701 {
    702 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    703   int n = 0;
    704 	for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
    705 	{
    706     n++;
    707     g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
    708   }
    709   return n;
    710 }
    711 
    712 void WINAPI QERApp_ReleaseSelectedBrushHandles()
    713 {
    714 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    715   g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
    716   Sys_UpdateWindows(W_ALL);
    717 }
    718 
    719 void WINAPI QERApp_ReleaseActiveBrushHandles()
    720 {
    721 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    722   g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
    723   Sys_UpdateWindows(W_ALL);
    724 }
    725 
    726 LPVOID WINAPI QERApp_GetActiveBrushHandle(int nIndex)
    727 {
    728 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    729   if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
    730   {
    731     return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
    732   }
    733   return NULL;
    734 }
    735 
    736 LPVOID WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
    737 {
    738 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    739   if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
    740   {
    741     return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
    742   }
    743   return NULL;
    744 }
    745 
    746 int WINAPI QERApp_TextureCount()
    747 {
    748 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    749 	Texture_StartPos ();
    750   int x, y;
    751   int n = 0;
    752 	while (1)
    753 	{
    754 		qtexture_t *q = Texture_NextPos (&x, &y);
    755 		if (!q)
    756 			break;
    757     n++;
    758   }
    759   return n;
    760 }
    761 
    762 LPCSTR WINAPI QERApp_GetTexture(int nIndex)
    763 {
    764 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    765   static char name[QER_MAX_NAMELEN];
    766 	Texture_StartPos ();
    767   int x, y;
    768   int n = 0;
    769 	while (1)
    770 	{
    771 		qtexture_t *q = Texture_NextPos (&x, &y);
    772 		if (!q)
    773 			break;
    774     if (n == nIndex)
    775     {
    776       strcpy(name, q->name);
    777       return name;
    778     }
    779     n++;
    780   }
    781   return NULL;
    782 }
    783 
    784 LPCSTR WINAPI QERApp_GetCurrentTexture()
    785 {
    786 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    787   return g_qeglobals.d_texturewin.texdef.name;
    788 }
    789 
    790 void WINAPI QERApp_SetCurrentTexture(LPCSTR strName)
    791 {
    792 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    793 	//++timo hu ?? tex is not initialized ?? can be any value ..
    794   texdef_t tex;
    795   //++timo added a brushprimit_texdef ..
    796   // smthg to be done here
    797   brushprimit_texdef_t brushprimit_tex;
    798   //strcpy(tex.name, strName);
    799   tex.SetName(strName);
    800   Texture_SetTexture(&tex,&brushprimit_tex);
    801 }
    802 
    803 int WINAPI QERApp_GetEClassCount()
    804 {
    805 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    806   int n = 0;
    807   for (eclass_t *e = eclass ; e ; e = e->next)
    808 	{
    809     n++;
    810   }
    811   return n;
    812 }
    813 
    814 LPCSTR WINAPI QERApp_GetEClass(int nIndex)
    815 {
    816 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    817   int n = 0;
    818   for (eclass_t *e = eclass ; e ; e = e->next)
    819 	{
    820     if (n == nIndex)
    821     {
    822       return e->name;
    823     }
    824   }
    825   return NULL;
    826 }
    827 
    828 void WINAPI QERApp_LoadTextureRGBA(LPVOID vp)
    829 {
    830   Texture_LoadFromPlugIn(vp);
    831 }
    832 
    833 // v1.70 code
    834 // world_entity holds the worldspawn and is indexed as 0
    835 // other entities are in the entities doubly linked list
    836 // QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
    837 int WINAPI QERApp_GetEntityCount()
    838 {
    839 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    840 	int n = 1;
    841 	for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
    842 	{
    843 		n++;
    844 	}
    845 	return n;
    846 }
    847 
    848 // We don't store entities in CPtrArray, we need to walk the list
    849 LPVOID WINAPI QERApp_GetEntityHandle(int nIndex)
    850 {
    851 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    852 	if (nIndex==0)
    853 		// looks for the worldspawn
    854 		return static_cast<LPVOID>(world_entity);
    855 	entity_t *pe = &entities;
    856 	int n = 0;
    857 	while ( n < nIndex )
    858 	{
    859 		pe = pe->next;
    860 		n++;
    861 	}
    862 	return static_cast<LPVOID>(pe);
    863 }
    864 
    865 epair_t** WINAPI QERApp_GetEntityKeyValList(LPVOID vp)
    866 {
    867 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    868 	entity_t *pe = static_cast<entity_t *>(vp);
    869 	return &pe->epairs;
    870 }
    871 
    872 epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )
    873 {
    874 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    875 	epair_t *e = (epair_t*)qmalloc (sizeof(*e));
    876 	e->key = (char*)qmalloc(strlen(key)+1);
    877 	strcpy (e->key, key);
    878 	e->value = (char*)qmalloc(strlen(val)+1);
    879 	strcpy (e->value, val);
    880 	return e;
    881 }
    882 
    883 void WINAPI QERApp_SetEntityKeyValList(LPVOID vp, epair_t* ep)
    884 {
    885 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    886 	entity_t *pe = static_cast<entity_t *>(vp);
    887 	if (pe->epairs)
    888 		Sys_Printf( "Warning : pe->epairs != NULL in QERApp_SetEntityKeyValList, will not set\n" );
    889 	else
    890 		pe->epairs = ep;
    891 }
    892 
    893 int WINAPI QERApp_AllocateEntityBrushHandles(LPVOID vp)
    894 {
    895 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    896 	entity_t *pe = static_cast<entity_t *>(vp);
    897 	int n = 0;
    898 	if (!pe->brushes.onext)
    899 		return 0;
    900 	g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
    901 	for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
    902 	{
    903 		n++;
    904 		g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
    905 	}
    906 	return n;
    907 }
    908 	
    909 void WINAPI QERApp_ReleaseEntityBrushHandles()
    910 {
    911 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    912 	g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
    913 }
    914 
    915 LPVOID WINAPI QERApp_GetEntityBrushHandle(int nIndex)
    916 {
    917 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    918 	if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
    919 		return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
    920 	return NULL;
    921 }
    922 
    923 LPVOID WINAPI QERApp_CreateEntityHandle()
    924 {
    925 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    926 	entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
    927 	pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
    928 	g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<LPVOID>(pe));
    929 	return static_cast<LPVOID>(pe);
    930 }
    931 
    932 // the vpBrush needs to be in m_BrushHandles
    933 //++timo we don't have allocation nor storage for vpEntity, no checks for this one
    934 void WINAPI QERApp_CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
    935 {
    936 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    937 	g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
    938 	return;
    939 }
    940 
    941 char* WINAPI QERApp_ReadProjectKey(char* key)
    942 {
    943 	return ValueForKey(g_qeglobals.d_project_entity, key);
    944 }
    945 
    946 int WINAPI QERApp_ScanFileForEClass(char *filename )
    947 {
    948 	// set single class parsing
    949 	parsing_single = true;
    950 	Eclass_ScanFile(filename);
    951 	if (eclass_found)
    952 	{
    953 		eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
    954 		return 1;
    955 	}
    956 	return 0;
    957 }
    958 
    959 // the vpBrush needs to be in m_BrushHandles
    960 //++timo add a debug check to see if we found the brush handle
    961 // NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
    962 // links the brush to its entity, everything else is done when commiting the entity to the map
    963 void CPlugInManager::CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
    964 {
    965 	brush_t* pb;
    966 	entity_t* pe;
    967 	for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
    968 	{
    969 		if (vpBrush == m_BrushHandles.GetAt(i))
    970 		{
    971 			m_BrushHandles.RemoveAt(i);
    972 			pb = reinterpret_cast<brush_t*>(vpBrush);
    973 			pe = reinterpret_cast<entity_t *>(vpEntity);
    974 			Entity_LinkBrush (pe, pb);
    975 		}
    976 	}
    977 	Sys_UpdateWindows(W_ALL);
    978 }
    979 
    980 // the vpEntity must be in m_EntityHandles
    981 void WINAPI QERApp_CommitEntityHandleToMap(LPVOID vpEntity)
    982 {
    983 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    984 	g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
    985 	return;
    986 }
    987 
    988 int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
    989 {
    990 	char cPath[1024];
    991 	sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
    992   int nSize = LoadFile( cPath, buffer);
    993   if (nSize == -1)
    994   {
    995     nSize = PakLoadAnyFile(cPath, buffer);
    996   }
    997 	return nSize;
    998 }
    999 
   1000 char * WINAPI QERApp_ExpandReletivePath (char *p)
   1001 {
   1002 	return ExpandReletivePath(p);
   1003 }
   1004 
   1005 // NOTE: this is a simplified version
   1006 int WINAPI QERApp_HasShader( const char *pName )
   1007 {
   1008 	CShaderInfo *pInfo = hasShader( pName );
   1009 	if (pInfo)
   1010 		return 1;
   1011 	return 0;
   1012 }
   1013 
   1014 qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
   1015 {
   1016 	// if the texture is not loaded yet, this call will get it loaded
   1017 	// but: when we assign a GL bind number, we need to be in the g_qeglobals.d_hdcBase , g_qeglobals.d_hglrcBase GL context
   1018 	// the plugin may set the GL context to whatever he likes, but then load would fail
   1019 	// NOTE: is context switching time-consuming? then maybe the plugin could handle the context switch and only add a 
   1020 	// sanity check in debug mode here
   1021 	// read current context
   1022 	HDC pluginHDC = qwglGetCurrentDC();
   1023 	HGLRC pluginHGLRC = qwglGetCurrentContext();
   1024 	qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
   1025 	qtexture_t* qtex = Texture_ForName( name );
   1026 	return qtex;
   1027 	qwglMakeCurrent( pluginHDC, pluginHGLRC );
   1028 }
   1029 
   1030 void WINAPI QERApp_RadiantFree( void * buf )
   1031 {
   1032 	free( buf );
   1033 }
   1034 
   1035 char* WINAPI QERApp_Token()
   1036 {
   1037 	return token;
   1038 }
   1039 
   1040 char* WINAPI QERApp_GetMapName()
   1041 {
   1042 	return currentmap;
   1043 }
   1044 
   1045 void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
   1046 {
   1047 	entity_t *pe;
   1048 	eclass_t *e;
   1049 	brush_t		*b;
   1050 	vec3_t mins,maxs;
   1051 	bool has_brushes;
   1052 	for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
   1053 	{
   1054 		if (vpEntity == m_EntityHandles.GetAt(i))
   1055 		{
   1056 			m_EntityHandles.RemoveAt(i);
   1057 			pe = reinterpret_cast<entity_t*>(vpEntity);
   1058 			// fill additional fields
   1059 			// straight copy from Entity_Parse
   1060 			// entity_t::origin
   1061 			GetVectorForKey (pe, "origin", pe->origin);
   1062 			// entity_t::eclass
   1063 			if (pe->brushes.onext == &pe->brushes)
   1064 				has_brushes = false;
   1065 			else
   1066 				has_brushes = true;
   1067 			e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
   1068 			pe->eclass = e;
   1069 			// fixedsize
   1070 			if (e->fixedsize)
   1071 			{
   1072 				if (pe->brushes.onext != &pe->brushes)
   1073 				{
   1074 					Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
   1075 				}
   1076 				// create a custom brush
   1077 				VectorAdd(e->mins, pe->origin, mins);
   1078 				VectorAdd(e->maxs, pe->origin, maxs);
   1079 				float a = 0;
   1080 				if (e->nShowFlags & ECLASS_MISCMODEL)
   1081 				{
   1082 					char* p = ValueForKey(pe, "model");
   1083 					if (p != NULL && strlen(p) > 0)
   1084 					{
   1085 						vec3_t vMin, vMax;
   1086 						a = FloatForKey (pe, "angle");
   1087 				        if (GetCachedModel(pe, p, vMin, vMax))
   1088 				        {
   1089 						      // create a custom brush
   1090 						      VectorAdd (pe->md3Class->mins, pe->origin, mins);
   1091 						      VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
   1092 				        }
   1093 					}
   1094 			    }
   1095 		
   1096 			    b = Brush_Create (mins, maxs, &e->texdef);
   1097 
   1098 			    if (a)
   1099 			    {
   1100 					vec3_t vAngle;
   1101 					vAngle[0] = vAngle[1] = 0;
   1102 					vAngle[2] = a;
   1103 					Brush_Rotate(b, vAngle, pe->origin, false);
   1104 				}
   1105 
   1106 				b->owner = pe;
   1107 
   1108 				b->onext = pe->brushes.onext;
   1109 				b->oprev = &pe->brushes;
   1110 				pe->brushes.onext->oprev = b;
   1111 				pe->brushes.onext = b;
   1112 			}
   1113 			else
   1114 			{	// brush entity
   1115 				if (pe->brushes.next == &pe->brushes)
   1116 					Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
   1117 			}
   1118 
   1119 			// add brushes to the active brushes list
   1120 			// and build them along the way
   1121 			for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
   1122 			{
   1123 				// convert between old brushes and brush primitive
   1124 				if (g_qeglobals.m_bBrushPrimitMode)
   1125 				{
   1126 					// we only filled the shift scale rot fields, needs conversion
   1127 					Brush_Build( b, true, true, true );
   1128 				}
   1129 				else
   1130 				{
   1131 					// we are using old brushes
   1132 					Brush_Build( b );
   1133 				}
   1134 				b->next = active_brushes.next;
   1135 				active_brushes.next->prev = b;
   1136 				b->prev = &active_brushes;
   1137 				active_brushes.next = b;
   1138 			}
   1139 
   1140 			// handle worldspawn entities
   1141 			// if worldspawn has no brushes, use the new one
   1142 			if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
   1143 			{
   1144 				if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
   1145 				{
   1146 					// worldspawn already has brushes
   1147 					Sys_Printf ("Commiting worldspawn as func_group\n");
   1148 					SetKeyValue(pe, "classname", "func_group");
   1149 					// add the entity to the end of the entity list
   1150 					pe->next = &entities;
   1151 					pe->prev = entities.prev;
   1152 					entities.prev->next = pe;
   1153 					entities.prev = pe;
   1154 					g_qeglobals.d_num_entities++;
   1155 				}
   1156 				else
   1157 				{
   1158 					// there's a worldspawn with no brushes, we assume the map is empty
   1159 					if ( world_entity )
   1160 					{
   1161 						Entity_Free( world_entity );
   1162 						world_entity = pe;
   1163 					}
   1164 					else
   1165 						Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
   1166 				}
   1167 			}
   1168 			else
   1169 			{
   1170 				// add the entity to the end of the entity list
   1171 				pe->next = &entities;
   1172 				pe->prev = entities.prev;
   1173 				entities.prev->next = pe;
   1174 				entities.prev = pe;
   1175 				g_qeglobals.d_num_entities++;
   1176 			}
   1177 		}
   1178 	}
   1179 }
   1180 
   1181 void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
   1182 {
   1183 	g_bScreenUpdates = bScreenUpdates; 
   1184 }
   1185 
   1186 texturewin_t* WINAPI QERApp_QeglobalsTexturewin()
   1187 {
   1188 	return &g_qeglobals.d_texturewin;
   1189 }
   1190 
   1191 _QERTextureInfo* CPlugInManager::GetTextureInfo()
   1192 {
   1193   if (m_pTexturePlug != NULL)
   1194   {
   1195     return m_pTexturePlug->getTextureInfo();
   1196   }
   1197   else
   1198   {
   1199     return NULL;
   1200   }
   1201 }
   1202 
   1203 LPVOID CPlugInManager::GetSurfaceFlags()
   1204 {
   1205   if (m_pSurfaceListPlug != NULL)
   1206   {
   1207     return m_pSurfaceListPlug->getSurfaceFlags();
   1208   }
   1209   else
   1210   {
   1211     return NULL;
   1212   }
   1213 }
   1214 
   1215 void CPlugInManager::LoadTexture(const char *pFilename)
   1216 {
   1217   if (m_pTexturePlug != NULL)
   1218   {
   1219     m_pTexturePlug->loadTexture(pFilename);
   1220   }
   1221 }
   1222 
   1223 patchMesh_t* WINAPI QERApp_GetSelectedPatch( )
   1224 {
   1225 	for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
   1226 	{
   1227 		if (pb->patchBrush)
   1228 		{
   1229 			return pb->pPatch;
   1230 		}
   1231 	}
   1232 #ifdef _DEBUG
   1233 	Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
   1234 #endif
   1235 	return NULL;
   1236 }
   1237 
   1238 char* WINAPI QERApp_GetGamePath()
   1239 {
   1240 	return g_PrefsDlg.m_strQuake2.GetBuffer(0);
   1241 }
   1242 
   1243 char* WINAPI QERApp_GetQERPath()
   1244 {
   1245 	return g_strAppPath.GetBuffer(0);
   1246 }
   1247 
   1248 // patches in/out -----------------------------------
   1249 int WINAPI QERApp_AllocateActivePatchHandles()
   1250 {
   1251 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1252 	return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
   1253 }
   1254 
   1255 int CPlugInManager::AllocateActivePatchHandles()
   1256 {
   1257 	int n = 0;
   1258 	for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
   1259 	{
   1260 		if (pb->patchBrush)
   1261 		{
   1262 			n++;
   1263 			m_PatchesHandles.Add(pb);
   1264 		}
   1265 	}
   1266 	return n;
   1267 }
   1268 
   1269 int WINAPI QERApp_AllocateSelectedPatchHandles()
   1270 {
   1271 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1272 	return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
   1273 }
   1274 	
   1275 int CPlugInManager::AllocateSelectedPatchHandles()
   1276 {
   1277 	int n = 0;
   1278 	for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
   1279 	{
   1280 		if (pb->patchBrush)
   1281 		{
   1282 			n++;
   1283 			m_PatchesHandles.Add(pb);
   1284 		}
   1285 	}
   1286 	return n;
   1287 }
   1288 
   1289 void WINAPI QERApp_ReleasePatchHandles()
   1290 {
   1291 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1292 	g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
   1293 }
   1294 
   1295 patchMesh_t* WINAPI QERApp_GetPatchData(int index)
   1296 {
   1297 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1298 	static patchMesh_t patch;
   1299 	patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
   1300 	if (pPatch)
   1301 	{
   1302 		memcpy( &patch, pPatch, sizeof(patchMesh_t) );
   1303 		return &patch;
   1304 	}
   1305 	return NULL;
   1306 }
   1307 
   1308 void WINAPI QERApp_DeletePatch(int index)
   1309 {
   1310 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1311 	patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
   1312 	if (pPatch)
   1313 	{
   1314 		brush_t *pb = pPatch->pSymbiot;
   1315 		Patch_Delete( pPatch );
   1316 		if (pb)
   1317 			Brush_Free( pb );
   1318 	}
   1319 #ifdef _DEBUG
   1320 	Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
   1321 #endif
   1322 }
   1323 
   1324 int WINAPI QERApp_CreatePatchHandle()
   1325 {
   1326 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1327 	return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
   1328 }
   1329 
   1330 int CPlugInManager::CreatePatchHandle()
   1331 {
   1332 	// NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
   1333 	patchMesh_t *pPatch = MakeNewPatch();
   1334 	m_PluginPatches.Add( pPatch );
   1335 	// change mode
   1336 	PatchesMode = EAllocatedPatches;
   1337 	return m_PluginPatches.GetSize()-1;
   1338 }
   1339 
   1340 void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
   1341 {
   1342 	AFX_MANAGE_STATE(AfxGetStaticModuleState());
   1343 	g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
   1344 }
   1345 
   1346 void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
   1347 {
   1348 	if (PatchesMode==EAllocatedPatches)
   1349 	{
   1350 		patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
   1351 		memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
   1352 		// patch texturing, if none given use current texture
   1353 		if (texName)
   1354 			pPatch->d_texture = Texture_ForName(texName);
   1355 		if ( !pPatch->d_texture )
   1356 		{
   1357 			pPatch->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
   1358 			// checking .. just in case
   1359 			if (!pPatch->d_texture)
   1360 			{
   1361 #ifdef _DEBUG
   1362 				Sys_Printf("WARNING: failed to set patch to current texture in CPlugInManager::CommitPatchHandleToMap\n");
   1363 #endif
   1364 				pPatch->d_texture = notexture;
   1365 			}
   1366 		}
   1367 		g_bScreenUpdates = false;
   1368 		// the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
   1369 		brush_t *pb = AddBrushForPatch( pPatch, true );
   1370 		Select_Brush( pb );
   1371 		g_bScreenUpdates = true;
   1372 		Sys_UpdateWindows(W_ALL);
   1373 	}
   1374 	else
   1375 	{
   1376 		brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
   1377 		patchMesh_t *pPatch = pBrush->pPatch;
   1378 		pPatch->width = pMesh->width;
   1379 		pPatch->height = pMesh->height;
   1380 		pPatch->contents = pMesh->contents;
   1381 		pPatch->flags = pMesh->flags;
   1382 		pPatch->value = pMesh->value;
   1383 		pPatch->type = pMesh->type;
   1384 		memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
   1385 		pPatch->bDirty = true;
   1386 	}
   1387 }
   1388 
   1389 // this gets called when the plugin needs specific services, for example the OpenGL drawing interface
   1390 //++timo plugins should be able to dynamically register their own interfaces in there
   1391 int WINAPI QERApp_RequestInterface( REFGUID refGUID, LPVOID pInterface )
   1392 {
   1393 	if (IsEqualGUID( refGUID, QERQglTable_GUID ))
   1394 	{
   1395 		_QERQglTable *pQglTable = static_cast<_QERQglTable *>(pInterface);
   1396 		if ( pQglTable->m_nSize != sizeof(_QERQglTable) )
   1397 		{
   1398 			Sys_Printf("wrong m_nSize in plugin-requested _QERQglTable interface\n");
   1399 			return 0;
   1400 		}
   1401 		pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;
   1402 		pQglTable->m_pfn_qglBegin = qglBegin;
   1403 		pQglTable->m_pfn_qglBindTexture = qglBindTexture;
   1404 		pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;
   1405 		pQglTable->m_pfn_qglCallList = qglCallList;
   1406 		pQglTable->m_pfn_qglCallLists = qglCallLists;
   1407 		pQglTable->m_pfn_qglClear = qglClear;
   1408 		pQglTable->m_pfn_qglClearColor = qglClearColor;
   1409 		pQglTable->m_pfn_qglClearDepth = qglClearDepth;
   1410 		pQglTable->m_pfn_qglColor3f = qglColor3f;
   1411 		pQglTable->m_pfn_qglColor4f = qglColor4f;
   1412 		pQglTable->m_pfn_qglCullFace = qglCullFace;
   1413 		pQglTable->m_pfn_qglDisable = qglDisable;
   1414 		pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;
   1415 		pQglTable->m_pfn_qglEnable = qglEnable;
   1416 		pQglTable->m_pfn_qglEnd = qglEnd;
   1417 		pQglTable->m_pfn_qglEndList = qglEndList;
   1418 		pQglTable->m_pfn_qglGenLists = qglGenLists;
   1419 		pQglTable->m_pfn_qglListBase = qglListBase;
   1420 		pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;
   1421 		pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;
   1422 		pQglTable->m_pfn_qglNewList = qglNewList;
   1423 		pQglTable->m_pfn_qglNormal3f = qglNormal3f;
   1424 		pQglTable->m_pfn_qglOrtho = qglOrtho;
   1425 		pQglTable->m_pfn_qglPointSize = qglPointSize;
   1426 		pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;
   1427 		pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;
   1428 		pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;
   1429 		pQglTable->m_pfn_qglRotated = qglRotated;
   1430 		pQglTable->m_pfn_qglRotatef = qglRotatef;
   1431 		pQglTable->m_pfn_qglScalef = qglScalef;
   1432 		pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;
   1433 		pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;
   1434 		pQglTable->m_pfn_qglTexGenf = qglTexGenf;
   1435 		pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;
   1436 		pQglTable->m_pfn_qglTranslated = qglTranslated;
   1437 		pQglTable->m_pfn_qglTranslatef = qglTranslatef;
   1438 		pQglTable->m_pfn_qglVertex2f = qglVertex2f;
   1439 		pQglTable->m_pfn_qglVertex3f = qglVertex3f;
   1440 		pQglTable->m_pfn_qglViewport = qglViewport;
   1441 		pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;
   1442 		pQglTable->m_pfn_QEW_SetupPixelFormat = &QEW_SetupPixelFormat;
   1443 		pQglTable->m_pfn_qwglCreateContext = qwglCreateContext;
   1444 		pQglTable->m_pfn_qwglDeleteContext = qwglDeleteContext;
   1445 		pQglTable->m_pfn_qwglMakeCurrent = qwglMakeCurrent;
   1446 		pQglTable->m_pfn_qwglShareLists = qwglShareLists;
   1447 		pQglTable->m_pfn_qwglSwapBuffers = qwglSwapBuffers;
   1448 		pQglTable->m_pfn_qwglUseFontBitmaps = qwglUseFontBitmaps;
   1449 		pQglTable->m_pfnGetQeglobalsHGLRC = &QERApp_GetQeglobalsHGLRC;
   1450 		pQglTable->m_pfn_qgluPerspective = qgluPerspective;
   1451 		pQglTable->m_pfn_qgluLookAt = qgluLookAt;
   1452 		pQglTable->m_pfnHookXYGLWindow = QERApp_HookXYGLWindow;
   1453 		pQglTable->m_pfnUnHookGLWindow = QERApp_UnHookGLWindow;
   1454 
   1455 		return 1;
   1456 	}
   1457 	else if (IsEqualGUID( refGUID, QERSelectedFaceTable_GUID ))
   1458 	{
   1459 		_QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pInterface);
   1460 		if ( pSelectedFaceTable->m_nSize != sizeof(_QERSelectedFaceTable) )
   1461 		{
   1462 			Sys_Printf("wrong m_nSize in plugin-requested _QERSelectedFaceTable interface\n");
   1463 			return 0;
   1464 		}
   1465 		pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;
   1466 		pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;
   1467 		pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;
   1468 		pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;
   1469 		pSelectedFaceTable->m_pfnTextureForName = &QERApp_Texture_ForName;
   1470 		pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;
   1471 		return 1;
   1472 	}
   1473 	else if (IsEqualGUID( refGUID, QERPluginEntitiesTable_GUID ))
   1474 	{
   1475 		_QERPluginEntitiesTable *pPluginEntitiesTable = static_cast<_QERPluginEntitiesTable *>(pInterface);
   1476 		if ( pPluginEntitiesTable->m_nSize != sizeof(_QERPluginEntitiesTable) )
   1477 		{
   1478 			Sys_Printf("wrong m_nSize in plugin-requested _QERPluginEntitiesTable interface\n");
   1479 			return 0;
   1480 		}
   1481 		pPluginEntitiesTable->m_pfnEClassScanDir = &QERApp_EClassScanDir;
   1482 		return 1;
   1483 	}
   1484 	else if (IsEqualGUID( refGUID, QERScripLibTable_GUID ))
   1485 	{
   1486 		_QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pInterface);
   1487 		if ( pScripLibTable->m_nSize != sizeof( _QERScripLibTable ) )
   1488 		{
   1489 			Sys_Printf("wrong m_nSize in plugin-requested _QERScripLibTable\n");
   1490 			return 0;
   1491 		}
   1492 		pScripLibTable->m_pfnGetToken = &GetToken;
   1493 		pScripLibTable->m_pfnToken = &QERApp_Token;
   1494 		pScripLibTable->m_pfnUnGetToken = &UngetToken;
   1495 		return 1;
   1496 	}
   1497 	else if (IsEqualGUID( refGUID, QERAppSurfaceTable_GUID ))
   1498 	{
   1499 		_QERAppSurfaceTable *pSurfaceTable = static_cast<_QERAppSurfaceTable *>(pInterface);
   1500 		if ( pSurfaceTable->m_nSize != sizeof( _QERAppSurfaceTable ) )
   1501 		{
   1502 			Sys_Printf("wrong m_nSize in plugin-requested _QERAppSurfaceTable\n");
   1503 			return 0;
   1504 		}
   1505 		pSurfaceTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;
   1506 		pSurfaceTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;
   1507 		pSurfaceTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;
   1508 		pSurfaceTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;
   1509 		pSurfaceTable->m_pfnPatchRebuild = &Patch_Rebuild;
   1510 		pSurfaceTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;
   1511 		return 1;
   1512 	}
   1513 	else if (IsEqualGUID( refGUID, QERAppBSPFrontendTable_GUID ))
   1514 	{
   1515 		_QERAppBSPFrontendTable *pBSPFrontendTable = static_cast<_QERAppBSPFrontendTable *>(pInterface);
   1516 		if ( pBSPFrontendTable->m_nSize != sizeof( _QERAppBSPFrontendTable ) )
   1517 		{
   1518 			Sys_Printf("wrong m_nSize in plugin-requested _QERAppBSPFrontendTable\n");
   1519 			return 0;
   1520 		}
   1521 		pBSPFrontendTable->m_pfnGetMapName = &QERApp_GetMapName;
   1522 		pBSPFrontendTable->m_pfnLoadPointFile = &Pointfile_Check;
   1523 		return 1;
   1524 	}
   1525 	else if (IsEqualGUID( refGUID, QERMessaging_GUID ))
   1526 	{
   1527 		_QERMessagingTable *pMessagingTable = static_cast<_QERMessagingTable *>(pInterface);
   1528 		if ( pMessagingTable->m_nSize != sizeof( _QERMessagingTable ) )
   1529 		{
   1530 			Sys_Printf("wrong m_nSize in plugin-requested _QERMessagingTable\n");
   1531 			return 0;
   1532 		}
   1533 		pMessagingTable->m_pfnHookWindow = QERApp_HookWindow;
   1534 		pMessagingTable->m_pfnUnHookWindow = QERApp_UnHookWindow;
   1535 		pMessagingTable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;
   1536 		pMessagingTable->m_pfnHookListener = QERApp_HookListener;
   1537 		pMessagingTable->m_pfnUnHookListener = QERApp_UnHookListener;
   1538 		return 1;
   1539 	}
   1540 	else if (IsEqualGUID( refGUID, QERShadersTable_GUID ))
   1541 	{
   1542 		_QERShadersTable *pShadersTable = static_cast<_QERShadersTable *>(pInterface);
   1543 		if ( pShadersTable->m_nSize != sizeof( _QERShadersTable ) )
   1544 		{
   1545 			Sys_Printf("wring m_nSize in plugin-requested _QERShadersTable\n");
   1546 			return 0;
   1547 		}
   1548 		pShadersTable->m_pfnTryTextureForName = QERApp_TryTextureForName;
   1549 		return 1;
   1550 	}
   1551 	return 0;
   1552 }
   1553 
   1554 int CPlugInManager::FillFuncTable(CPlugIn *pPlug)
   1555 {
   1556   _QERFuncTable_1 *pTable = reinterpret_cast<_QERFuncTable_1*>(pPlug->getFuncTable());
   1557   if (pTable != NULL)
   1558   {
   1559     if (pTable->m_fVersion != QER_PLUG_VERSION)
   1560     {
   1561       Sys_Printf("Radiant plugin manager was built with version %.2f, Plugin %s is version %.2f\n", QER_PLUG_VERSION, pPlug->getVersionStr() , pTable->m_fVersion);
   1562     }
   1563     if (pTable->m_fVersion >= QER_PLUG_VERSION_1)
   1564     {
   1565       pTable->m_pfnCreateBrush = &QERApp_CreateBrush;
   1566       pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;
   1567       pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;
   1568       pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;
   1569       pTable->m_pfnAddFace = &QERApp_AddFace;
   1570       pTable->m_pfnAddFaceData = &QERApp_AddFaceData;
   1571       pTable->m_pfnGetFaceData = &QERApp_GetFaceData;
   1572       pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;
   1573       pTable->m_pfnSetFaceData = &QERApp_SetFaceData;
   1574       pTable->m_pfnDeleteFace = &QERApp_DeleteFace;
   1575       pTable->m_pfnTextureBrush = &QERApp_TextureBrush;
   1576 	  pTable->m_pfnBuildBrush = &QERApp_BuildBrush;						// PGM
   1577   	  pTable->m_pfnSelectBrush = &QERApp_SelectBrush;					// PGM
   1578 	  pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush;				// PGM
   1579 	  pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes;		// PGM
   1580       pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;
   1581       pTable->m_pfnGetPoints = &QERApp_GetPoints;
   1582       pTable->m_pfnSysMsg = &QERApp_SysMsg;
   1583       pTable->m_pfnInfoMsg = &QERApp_InfoMsg;
   1584       pTable->m_pfnHideInfoMsg = &QERApp_HideInfoMsg;
   1585       pTable->m_pfnPositionView = &QERApp_PositionView;					// PGM
   1586       pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;
   1587       pTable->m_pfnAllocateSelectedBrushHandles  = &QERApp_AllocateSelectedBrushHandles;
   1588       pTable->m_pfnReleaseSelectedBrushHandles  = &QERApp_ReleaseSelectedBrushHandles;
   1589       pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;
   1590       pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;
   1591       pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;
   1592       pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;
   1593       pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;
   1594       pTable->m_pfnTextureCount = &QERApp_TextureCount;
   1595       pTable->m_pfnGetTexture = &QERApp_GetTexture;
   1596       pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;
   1597       pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;
   1598       pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;
   1599       pTable->m_pfnGetEClass = &QERApp_GetEClass;
   1600       pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;
   1601     }
   1602     // end of v1.00
   1603     if (pTable->m_fVersion >= 1.5f)
   1604     {
   1605       // v1.50 starts
   1606       pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;
   1607       // end of v1.50
   1608     }
   1609 	if (pTable->m_fVersion >= 1.7f)
   1610 	{
   1611 		pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;
   1612 		pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;
   1613 		pTable->m_pfnGetEntityKeyValList = &QERApp_GetEntityKeyValList;
   1614 		pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;
   1615 		pTable->m_pfnSetEntityKeyValList = &QERApp_SetEntityKeyValList;
   1616 		pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;
   1617 		pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;
   1618 		pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;
   1619 		pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;
   1620 		pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;
   1621 		pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;
   1622 		pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;
   1623 		pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;
   1624 		pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;
   1625 		pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;
   1626 		pTable->m_pfnScanFileForEClass = &QERApp_ScanFileForEClass;
   1627 		pTable->m_pfnRequestInterface = &QERApp_RequestInterface;
   1628 		pTable->m_pfnErrorMsg = &QERApp_ErrorMsg;
   1629 		pTable->m_pfnLoadFile = &QERApp_LoadFile;
   1630 		pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;
   1631 		pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;
   1632 		pTable->m_pfnHasShader = &QERApp_HasShader;
   1633 		pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;
   1634 		pTable->m_pfnRadiantFree = &QERApp_RadiantFree;
   1635 		pTable->m_pfnGetGamePath = &QERApp_GetGamePath;
   1636 		pTable->m_pfnGetQERPath = &QERApp_GetQERPath;
   1637 		// patches
   1638 		pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;
   1639 		pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;
   1640 		pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;
   1641 		pTable->m_pfnGetPatchData = &QERApp_GetPatchData;
   1642 		pTable->m_pfnDeletePatch = &QERApp_DeletePatch;
   1643 		pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;
   1644 		pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;
   1645 	}
   1646 	return true;
   1647   }
   1648   else
   1649   {
   1650     Sys_Printf("Unable to load %s because the function tables are not the same size\n", pPlug->getVersionStr());
   1651   }
   1652   return false;
   1653 }
   1654 
   1655 CPlugIn * CPlugInManager::PluginForModule(HMODULE hPlug)
   1656 {
   1657 	int i;
   1658 	for( i=0; i!=m_PlugIns.GetSize(); i++ )
   1659 	{
   1660 		if ( reinterpret_cast<CPlugIn *>(m_PlugIns[i])->GetDLLModule() == hPlug )
   1661 			return reinterpret_cast<CPlugIn *>(m_PlugIns[i]);
   1662 	}
   1663 	return NULL;
   1664 }
   1665