Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

PlugInManager.cpp

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // PlugInManager.cpp: implementation of the CPlugInManager class.
00023 //
00025 
00026 #include "stdafx.h"
00027 #include "io.h"
00028 #include "Radiant.h"
00029 #include "PlugInManager.h"
00030 #include "PlugIn.h"
00031 #include "DialogInfo.h"
00032 #include "pakstuff.h"
00033 
00034 #ifdef _DEBUG
00035 #undef THIS_FILE
00036 static char THIS_FILE[]=__FILE__;
00037 #define new DEBUG_NEW
00038 #endif
00039 
00041 // Construction/Destruction
00043 
00044 CPlugInManager::CPlugInManager()
00045 {
00046   m_pTexturePlug = NULL;
00047   m_pSurfaceListPlug = NULL;
00048   PatchesMode = EActivePatches;
00049 }
00050 
00051 CPlugInManager::~CPlugInManager()
00052 {
00053   Cleanup();
00054 }
00055 
00056 void CPlugInManager::Init(const char * pPath)
00057 {
00058     Cleanup();
00059 
00060     // set some globals
00061     g_qeglobals.bSurfacePropertiesPlugin = false;
00062     g_qeglobals.bBSPFrontendPlugin = false;
00063     
00064     CString strPath(pPath);
00065     strPath += "*.dll";
00066     
00067     bool bGo = true;
00068     
00069     struct _finddata_t fileinfo;
00070     int handle = _findfirst (strPath, &fileinfo);
00071     if (handle != -1)
00072     {
00073         do
00074         {
00075             strPath.Format("%s\\%s", pPath, fileinfo.name);
00076             CPlugIn *pPlug = new CPlugIn();
00077             if (pPlug->load(strPath))
00078             {
00079                 if(FillFuncTable(pPlug))        // PGM
00080                 {
00081                     m_PlugIns.Add(pPlug);
00082 
00083                     pPlug->RegisterPluginEntities();
00084 
00085                     // if this thing handles surface properties
00086                     pPlug->InitSurfacePlugin();
00087                     
00088                     // will test and init if it's a BSP frontend
00089                     pPlug->InitBSPFrontendPlugin();
00090 
00091                     g_pParentWnd->AddPlugInMenuItem(pPlug);
00092                     
00093                     // if this thing handles textures
00094                     if (pPlug->getTextureInfo() != NULL)
00095                     {
00096                         this->m_pTexturePlug = pPlug;
00097                         
00098                         // if this is a wad style texture extension, have it load everything now
00099                         if (pPlug->getTextureInfo()->m_bWadStyle)
00100                         {
00101                             CString strPath = ValueForKey(g_qeglobals.d_project_entity, "texturepath");
00102                             pPlug->loadTexture(strPath);
00103                         }
00104                     }
00105                     
00106                     if (pPlug->getSurfaceFlags() != NULL)
00107                     {
00108                         this->m_pSurfaceListPlug = pPlug;
00109                     }
00110                 }
00111                 else
00112                 {
00113                     delete pPlug;               // PGM
00114                 }
00115             }
00116             else
00117             {
00118                 delete pPlug;
00119             }
00120         } while (_findnext( handle, &fileinfo ) != -1);
00121         _findclose (handle);
00122     }
00123     
00124 }
00125 
00126 void CPlugInManager::Cleanup()
00127 {
00128     int i;
00129     for (i = 0; i < m_PlugIns.GetSize(); i++)
00130     {
00131         CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
00132         plug->free();
00133         delete plug;
00134     }
00135     m_PlugIns.RemoveAll();
00136     
00137     for (i = 0; i < m_BrushHandles.GetSize(); i++)
00138     {
00139         brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
00140         Brush_Free(pb);
00141     }
00142     m_BrushHandles.RemoveAll();
00143     
00144     for (i = 0; i < m_EntityHandles.GetSize(); i++)
00145     {
00146         entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
00147         Entity_Free(pe);
00148     }
00149     m_EntityHandles.RemoveAll();
00150     
00151     // patches
00152     // these are linked into the map
00153     m_PatchesHandles.RemoveAll();
00154     // these patches were allocated by Radiant on plugin request
00155     // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
00156     // in which case we are supposed to delete them
00157     // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
00158     // erased and we are trying a second time, therefore crashing ..
00159     //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
00160 #ifdef _DEBUG
00161     if (m_PluginPatches.GetSize() != 0)
00162         Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
00163 #endif
00164 /*  for (i = 0; i < m_PluginPatches.GetSize(); i++)
00165     {
00166         patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
00167         if (pMesh->pSymbiot)
00168             delete pMesh;
00169     }
00170     m_PluginPatches.RemoveAll(); */
00171 }
00172 
00173 void CPlugInManager::Dispatch(int n, const char * p)
00174 {
00175   for (int i = 0; i < m_PlugIns.GetSize(); i++)
00176   {
00177     CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
00178     if (plug->ownsCommandID(n))
00179     {
00180       vec3_t vMin, vMax;
00181         if (selected_brushes.next == &selected_brushes)
00182       {
00183         vMin[0] = vMin[1] = vMin[2] = 0;
00184         VectorCopy(vMin, vMax);
00185       }
00186       else
00187       {
00188         Select_GetBounds (vMin, vMax);
00189       }
00190       plug->dispatchCommand(p, vMin, vMax, QE_SingleBrush(true));   // PGM -- added quiet
00191       break;
00192     }
00193   }
00194 }
00195 
00196 // creates a dummy brush in the active brushes list
00197 // FIXME : is this one really USED ?
00198 void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
00199 {
00200     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00201     
00202     brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
00203     Entity_LinkBrush (world_entity, pBrush);
00204     Brush_Build(pBrush);
00205     Brush_AddToList (pBrush, &active_brushes);
00206     Select_Brush(pBrush);
00207     Sys_UpdateWindows(W_ALL);
00208 }
00209 
00210 LPVOID CPlugInManager::CreateBrushHandle()
00211 {
00212     brush_t *pb = Brush_Alloc();
00213     pb->numberId = g_nBrushId++;
00214   m_BrushHandles.Add(pb);
00215   return (LPVOID)pb;
00216 }
00217 
00218 void CPlugInManager::DeleteBrushHandle(void * vp)
00219 {
00220   CPtrArray* pHandles[3];
00221   pHandles[0] = &m_SelectedBrushHandles;
00222   pHandles[1] = &m_ActiveBrushHandles;
00223   pHandles[2] = &m_BrushHandles;
00224 
00225   for (int j = 0; j < 3; j++)
00226   {
00227     for (int i = 0; i < pHandles[j]->GetSize(); i++)
00228     {
00229       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
00230       if (pb == reinterpret_cast<brush_t*>(vp))
00231       {
00232         if (j == 2)
00233         {
00234           // only remove it from the list if it is work area
00235           // this allows the selected and active list indexes to remain constant
00236           // throughout a session (i.e. between an allocate and release)
00237           pHandles[j]->RemoveAt(i);
00238         }
00239         Brush_Free(pb);
00240         Sys_MarkMapModified();      // PGM
00241         return;
00242       }
00243     }
00244   }
00245 }
00246 
00247 void CPlugInManager::CommitBrushHandleToMap(void * vp)
00248 {
00249   g_bScreenUpdates = false; 
00250   for (int i = 0; i < m_BrushHandles.GetSize(); i++)
00251   {
00252     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
00253     if (pb == reinterpret_cast<brush_t*>(vp))
00254     {
00255       m_BrushHandles.RemoveAt(i);
00256       Entity_LinkBrush (world_entity, pb);
00257       Brush_Build(pb);
00258       Brush_AddToList (pb, &active_brushes);
00259       Select_Brush(pb);
00260     }
00261   }
00262   g_bScreenUpdates = true; 
00263   Sys_UpdateWindows(W_ALL);
00264 }
00265 
00266 void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
00267 {
00268   brush_t *bp = FindBrushHandle(vp);
00269   if (bp != NULL)
00270   {
00271         face_t *f = Face_Alloc();
00272         f->texdef = g_qeglobals.d_texturewin.texdef;
00273         f->texdef.flags &= ~SURF_KEEP;
00274         f->texdef.contents &= ~CONTENTS_KEEP;
00275         f->next = bp->brush_faces;
00276         bp->brush_faces = f;
00277         VectorCopy (v1, f->planepts[0]);
00278         VectorCopy (v2, f->planepts[1]);
00279         VectorCopy (v3, f->planepts[2]);
00280   }
00281 }
00282 
00283 brush_t* CPlugInManager::FindBrushHandle(void * vp)
00284 {
00285   CPtrArray* pHandles[4];
00286   pHandles[0] = &m_SelectedBrushHandles;
00287   pHandles[1] = &m_ActiveBrushHandles;
00288   pHandles[2] = &m_BrushHandles;
00289   pHandles[3] = &m_EntityBrushHandles;
00290 
00291   for (int j = 0; j < 4; j++)
00292   {
00293     for (int i = 0; i < pHandles[j]->GetSize(); i++)
00294     {
00295       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
00296       if (pb == reinterpret_cast<brush_t*>(vp))
00297       {
00298         return pb;
00299       }
00300     }
00301   }
00302   return NULL;
00303 }
00304 
00305 patchMesh_t* CPlugInManager::FindPatchHandle(int index)
00306 {
00307     switch (PatchesMode)
00308     {
00309     case EActivePatches:
00310     case ESelectedPatches:
00311         if ( index < m_PatchesHandles.GetSize() )
00312         {
00313             brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
00314             return pb->pPatch;
00315         }
00316 #ifdef _DEBUG
00317         Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
00318 #endif
00319         break;
00320     case EAllocatedPatches:
00321         if ( index < m_PluginPatches.GetSize() )
00322         {
00323             patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
00324             return pPatch;
00325         }
00326 #ifdef _DEBUG
00327         Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
00328 #endif
00329         break;
00330     }
00331     return NULL;
00332 }
00333 
00334 LPVOID WINAPI QERApp_CreateBrushHandle()
00335 {
00336     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00337   return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
00338 }
00339 
00340 void WINAPI QERApp_DeleteBrushHandle(LPVOID vp)
00341 {
00342     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00343   g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
00344 }
00345 
00346 void WINAPI QERApp_CommitBrushHandleToMap(LPVOID vp)
00347 {
00348     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00349   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
00350 }
00351 
00352 void WINAPI QERApp_AddFace(LPVOID vp, vec3_t v1, vec3_t v2, vec3_t v3)
00353 {
00354     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00355   g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
00356 }
00357 
00358 void WINAPI QERApp_DeleteSelection()
00359 {
00360     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00361   Select_Delete();
00362 }
00363 
00364 void WINAPI QERApp_SysMsg(LPCSTR pMsg)
00365 {
00366     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00367   CString str = pMsg;
00368   Sys_Printf(str.GetBuffer(0));
00369 }
00370 
00371 // NOTE: called only in case of plugin error. We can try a plugin refresh instead of a straight crash ?
00372 void WINAPI QERApp_ErrorMsg(LPCSTR pMsg)
00373 {
00374     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00375     CString str = pMsg;
00376     Error(str.GetBuffer(0));
00377 }
00378 
00379 void WINAPI QERApp_InfoMsg(LPCSTR pMsg)
00380 {
00381     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00382   ShowInfoDialog(pMsg);
00383 }
00384 
00385 void WINAPI QERApp_HideInfoMsg()
00386 {
00387     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00388   HideInfoDialog();
00389 }
00390 
00391 //=====
00392 //PGM
00393 void WINAPI QERApp_PositionView(vec3_t  v1, vec3_t v2)
00394 {
00395     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00396     g_pParentWnd->ActiveXY()->SetOrigin(v1);
00397     // FIXME - implement this!
00398     Sys_UpdateWindows(W_ALL);
00399 }
00400 //PGM
00401 //=====
00402 
00403 //FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
00404 bool g_bPlugWait = false;
00405 bool g_bPlugOK = false;
00406 int  g_nPlugCount = 0;
00407 
00408 void _PlugDone(bool b, int n)
00409 {
00410   g_bPlugWait = false;
00411   g_bPlugOK = b;
00412   g_nPlugCount = n;
00413 }
00414 
00415 void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, LPCSTR pMsg)
00416 {
00417     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00418   ShowInfoDialog(pMsg);
00419   g_bPlugWait = true;
00420   g_bPlugOK = false;
00421   g_nPlugCount = 0;
00422 //  g_nPlugCount=nMax-1;
00423   AcquirePath(nMax, &_PlugDone);
00424   while (g_bPlugWait)
00425   {
00426     MSG msg;
00427     if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
00428     { 
00429       TranslateMessage(&msg);
00430       DispatchMessage(&msg);
00431     }
00432   }
00433   HideInfoDialog();
00434   
00435   pData->m_nCount = 0;
00436   pData->m_pVectors = NULL;
00437 
00438   if (g_bPlugOK && g_nPlugCount > 0)
00439   {
00440     pData->m_nCount = g_nPlugCount;
00441     pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
00442     vec3_t *pOut = pData->m_pVectors;
00443     for (int i = 0; i < g_nPlugCount; i++)
00444     {
00445     memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
00446     pOut++;
00447     }
00448   }
00449 }
00450 
00451 void WINAPI QERApp_AddFaceData(LPVOID pv, _QERFaceData *pData)
00452 {
00453     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00454 
00455     brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00456   if (pBrush != NULL)
00457   {
00458         face_t *f = Face_Alloc();
00459         f->texdef = g_qeglobals.d_texturewin.texdef;
00460         f->texdef.flags = pData->m_nFlags;
00461     f->texdef.contents = pData->m_nContents;
00462     f->texdef.value = pData->m_nValue;
00463     f->texdef.rotate = pData->m_fRotate;
00464     f->texdef.shift[0] = pData->m_fShift[0];
00465     f->texdef.shift[1] = pData->m_fShift[1];
00466     f->texdef.scale[0] = pData->m_fScale[0];
00467     f->texdef.scale[1] = pData->m_fScale[1];
00468     //strcpy(f->texdef.name, pData->m_TextureName);
00469     f->texdef.SetName(pData->m_TextureName);
00470         f->next = pBrush->brush_faces;
00471         pBrush->brush_faces = f;
00472         VectorCopy (pData->m_v1, f->planepts[0]);
00473         VectorCopy (pData->m_v2, f->planepts[1]);
00474         VectorCopy (pData->m_v3, f->planepts[2]);
00475         Sys_MarkMapModified();      // PGM
00476   }
00477 }
00478 
00479 int WINAPI QERApp_GetFaceCount(LPVOID pv)
00480 {
00481     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00482   int n = 0;
00483   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00484   if (pBrush != NULL)
00485   {
00486       for (face_t *f = pBrush->brush_faces ; f; f = f->next)
00487     {
00488       n++;
00489     }
00490   }
00491   return n;
00492 }
00493 
00494 _QERFaceData* WINAPI QERApp_GetFaceData(LPVOID pv, int nFaceIndex)
00495 {
00496     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00497   static _QERFaceData face;
00498   int n = 0;
00499   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00500 
00501   if (pBrush != NULL)
00502   {
00503     for (face_t *f = pBrush->brush_faces ; f; f = f->next)
00504     {
00505 
00506 #ifdef _DEBUG
00507         if (!pBrush->brush_faces)
00508         {
00509             Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
00510             return NULL;
00511         }
00512 #endif
00513 
00514       if (n == nFaceIndex)
00515       {
00516         face.m_nContents = f->texdef.contents;
00517         face.m_nFlags = f->texdef.flags;
00518         face.m_fRotate = f->texdef.rotate;
00519         face.m_fScale[0] = f->texdef.scale[0];
00520         face.m_fScale[1] = f->texdef.scale[1];
00521         face.m_fShift[0] = f->texdef.shift[0];
00522         face.m_fShift[1] = f->texdef.shift[1];
00523         face.m_nValue = f->texdef.value;
00524         strcpy(face.m_TextureName, f->texdef.name);
00525         VectorCopy(f->planepts[0], face.m_v1);
00526         VectorCopy(f->planepts[1], face.m_v2);
00527         VectorCopy(f->planepts[2], face.m_v3);
00528         return &face;
00529       }
00530       n++;
00531     }
00532   }
00533   return NULL;
00534 }
00535 
00536 void WINAPI QERApp_SetFaceData(LPVOID pv, int nFaceIndex, _QERFaceData *pData)
00537 {
00538     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00539     int n = 0;
00540     brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00541 
00542     if (pBrush != NULL)
00543     {
00544         for (face_t *f = pBrush->brush_faces ; f; f = f->next)
00545         {
00546             if (n == nFaceIndex)
00547             {
00548                 f->texdef.flags = pData->m_nFlags;
00549                 f->texdef.contents = pData->m_nContents;
00550                 f->texdef.value = pData->m_nValue;
00551                 f->texdef.rotate = pData->m_fRotate;
00552                 f->texdef.shift[0] = pData->m_fShift[0];
00553                 f->texdef.shift[1] = pData->m_fShift[1];
00554                 f->texdef.scale[0] = pData->m_fScale[0];
00555                 f->texdef.scale[1] = pData->m_fScale[1];
00556                 //strcpy(f->texdef.name, pData->m_TextureName);
00557                 f->texdef.SetName(pData->m_TextureName);
00558                 VectorCopy(pData->m_v1, f->planepts[0]);
00559                 VectorCopy(pData->m_v2, f->planepts[1]);
00560                 VectorCopy(pData->m_v3, f->planepts[2]);
00561                 Sys_MarkMapModified();      // PGM
00562                 return;                     // PGM
00563             }
00564             n++;
00565         }
00566     }
00567 }
00568 
00569 void WINAPI QERApp_DeleteFace(LPVOID pv, int nFaceIndex)
00570 {
00571     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00572   int n = 0;
00573   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00574   if (pBrush != NULL)
00575   {
00576     face_t *pPrev = pBrush->brush_faces;
00577       for (face_t *f = pBrush->brush_faces; f; f = f->next)
00578     {
00579       if (n == nFaceIndex)
00580       {
00581         pPrev->next = f->next;
00582               Face_Free (f);
00583         Sys_MarkMapModified();      // PGM
00584         return;
00585       }
00586       n++;
00587       pPrev = f;
00588     }
00589   }
00590 }
00591 
00592 //==========
00593 //PGM
00594 void WINAPI QERApp_BuildBrush (LPVOID pv)
00595 {
00596     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00597     brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00598     if (pBrush != NULL)
00599     {
00600         Brush_Build(pBrush);
00601         Sys_UpdateWindows(W_ALL);
00602     }
00603 }
00604 
00605 //Timo : another version with bConvert flag
00606 //++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
00607 void WINAPI QERApp_BuildBrush2 (LPVOID pv, int bConvert)
00608 {
00609     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00610     brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00611     if (pBrush != NULL)
00612     {
00613         Brush_Build( pBrush, true, true, bConvert );
00614         Sys_UpdateWindows(W_ALL);
00615     }
00616 }
00617 
00618 void WINAPI QERApp_SelectBrush (LPVOID pv)
00619 {
00620     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00621     brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00622     if (pBrush != NULL)
00623     {
00624         Select_Brush(pBrush, false);
00625         Sys_UpdateWindows(W_ALL);
00626     }
00627 
00628 }
00629 
00630 void WINAPI QERApp_DeselectBrush (LPVOID pv)
00631 {
00632     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00633     // FIXME - implement this!
00634 }
00635 
00636 void WINAPI QERApp_ResetPlugins()
00637 {
00638     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00639   g_pParentWnd->OnPluginsRefresh();
00640 }
00641 
00642 void WINAPI QERApp_DeselectAllBrushes ()
00643 {
00644     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00645     Select_Deselect();
00646     Sys_UpdateWindows(W_ALL);
00647 }
00648 //PGM
00649 //==========
00650 
00651 void WINAPI QERApp_TextureBrush(LPVOID pv, LPCSTR pName)
00652 {
00653     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00654   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
00655   if (pBrush != NULL)
00656   {
00657       for (face_t *f = pBrush->brush_faces ; f; f = f->next)
00658     {
00659       //strcpy(f->texdef.name, pName);
00660       f->texdef.SetName(pName);
00661     }
00662     Sys_MarkMapModified();      // PGM
00663   }
00664 }
00665 
00666 int WINAPI QERApp_SelectedBrushCount()
00667 {
00668     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00669   int n = 0;
00670     for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
00671     {
00672     n++;
00673   }
00674   return n;
00675 }
00676 
00677 int WINAPI QERApp_ActiveBrushCount()
00678 {
00679     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00680   int n = 0;
00681     for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
00682     {
00683     n++;
00684   }
00685   return n;
00686 }
00687 
00688 int WINAPI QERApp_AllocateSelectedBrushHandles()
00689 {
00690     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00691   int n = 0;
00692     for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
00693     {
00694     n++;
00695     g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
00696   }
00697   return n;
00698 }
00699 
00700 int WINAPI QERApp_AllocateActiveBrushHandles()
00701 {
00702     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00703   int n = 0;
00704     for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
00705     {
00706     n++;
00707     g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
00708   }
00709   return n;
00710 }
00711 
00712 void WINAPI QERApp_ReleaseSelectedBrushHandles()
00713 {
00714     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00715   g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
00716   Sys_UpdateWindows(W_ALL);
00717 }
00718 
00719 void WINAPI QERApp_ReleaseActiveBrushHandles()
00720 {
00721     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00722   g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
00723   Sys_UpdateWindows(W_ALL);
00724 }
00725 
00726 LPVOID WINAPI QERApp_GetActiveBrushHandle(int nIndex)
00727 {
00728     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00729   if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
00730   {
00731     return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
00732   }
00733   return NULL;
00734 }
00735 
00736 LPVOID WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
00737 {
00738     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00739   if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
00740   {
00741     return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
00742   }
00743   return NULL;
00744 }
00745 
00746 int WINAPI QERApp_TextureCount()
00747 {
00748     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00749     Texture_StartPos ();
00750   int x, y;
00751   int n = 0;
00752     while (1)
00753     {
00754         qtexture_t *q = Texture_NextPos (&x, &y);
00755         if (!q)
00756             break;
00757     n++;
00758   }
00759   return n;
00760 }
00761 
00762 LPCSTR WINAPI QERApp_GetTexture(int nIndex)
00763 {
00764     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00765   static char name[QER_MAX_NAMELEN];
00766     Texture_StartPos ();
00767   int x, y;
00768   int n = 0;
00769     while (1)
00770     {
00771         qtexture_t *q = Texture_NextPos (&x, &y);
00772         if (!q)
00773             break;
00774     if (n == nIndex)
00775     {
00776       strcpy(name, q->name);
00777       return name;
00778     }
00779     n++;
00780   }
00781   return NULL;
00782 }
00783 
00784 LPCSTR WINAPI QERApp_GetCurrentTexture()
00785 {
00786     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00787   return g_qeglobals.d_texturewin.texdef.name;
00788 }
00789 
00790 void WINAPI QERApp_SetCurrentTexture(LPCSTR strName)
00791 {
00792     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00793     //++timo hu ?? tex is not initialized ?? can be any value ..
00794   texdef_t tex;
00795   //++timo added a brushprimit_texdef ..
00796   // smthg to be done here
00797   brushprimit_texdef_t brushprimit_tex;
00798   //strcpy(tex.name, strName);
00799   tex.SetName(strName);
00800   Texture_SetTexture(&tex,&brushprimit_tex);
00801 }
00802 
00803 int WINAPI QERApp_GetEClassCount()
00804 {
00805     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00806   int n = 0;
00807   for (eclass_t *e = eclass ; e ; e = e->next)
00808     {
00809     n++;
00810   }
00811   return n;
00812 }
00813 
00814 LPCSTR WINAPI QERApp_GetEClass(int nIndex)
00815 {
00816     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00817   int n = 0;
00818   for (eclass_t *e = eclass ; e ; e = e->next)
00819     {
00820     if (n == nIndex)
00821     {
00822       return e->name;
00823     }
00824   }
00825   return NULL;
00826 }
00827 
00828 void WINAPI QERApp_LoadTextureRGBA(LPVOID vp)
00829 {
00830   Texture_LoadFromPlugIn(vp);
00831 }
00832 
00833 // v1.70 code
00834 // world_entity holds the worldspawn and is indexed as 0
00835 // other entities are in the entities doubly linked list
00836 // QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
00837 int WINAPI QERApp_GetEntityCount()
00838 {
00839     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00840     int n = 1;
00841     for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
00842     {
00843         n++;
00844     }
00845     return n;
00846 }
00847 
00848 // We don't store entities in CPtrArray, we need to walk the list
00849 LPVOID WINAPI QERApp_GetEntityHandle(int nIndex)
00850 {
00851     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00852     if (nIndex==0)
00853         // looks for the worldspawn
00854         return static_cast<LPVOID>(world_entity);
00855     entity_t *pe = &entities;
00856     int n = 0;
00857     while ( n < nIndex )
00858     {
00859         pe = pe->next;
00860         n++;
00861     }
00862     return static_cast<LPVOID>(pe);
00863 }
00864 
00865 epair_t** WINAPI QERApp_GetEntityKeyValList(LPVOID vp)
00866 {
00867     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00868     entity_t *pe = static_cast<entity_t *>(vp);
00869     return &pe->epairs;
00870 }
00871 
00872 epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )
00873 {
00874     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00875     epair_t *e = (epair_t*)qmalloc (sizeof(*e));
00876     e->key = (char*)qmalloc(strlen(key)+1);
00877     strcpy (e->key, key);
00878     e->value = (char*)qmalloc(strlen(val)+1);
00879     strcpy (e->value, val);
00880     return e;
00881 }
00882 
00883 void WINAPI QERApp_SetEntityKeyValList(LPVOID vp, epair_t* ep)
00884 {
00885     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00886     entity_t *pe = static_cast<entity_t *>(vp);
00887     if (pe->epairs)
00888         Sys_Printf( "Warning : pe->epairs != NULL in QERApp_SetEntityKeyValList, will not set\n" );
00889     else
00890         pe->epairs = ep;
00891 }
00892 
00893 int WINAPI QERApp_AllocateEntityBrushHandles(LPVOID vp)
00894 {
00895     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00896     entity_t *pe = static_cast<entity_t *>(vp);
00897     int n = 0;
00898     if (!pe->brushes.onext)
00899         return 0;
00900     g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
00901     for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
00902     {
00903         n++;
00904         g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
00905     }
00906     return n;
00907 }
00908     
00909 void WINAPI QERApp_ReleaseEntityBrushHandles()
00910 {
00911     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00912     g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
00913 }
00914 
00915 LPVOID WINAPI QERApp_GetEntityBrushHandle(int nIndex)
00916 {
00917     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00918     if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
00919         return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
00920     return NULL;
00921 }
00922 
00923 LPVOID WINAPI QERApp_CreateEntityHandle()
00924 {
00925     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00926     entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
00927     pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
00928     g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<LPVOID>(pe));
00929     return static_cast<LPVOID>(pe);
00930 }
00931 
00932 // the vpBrush needs to be in m_BrushHandles
00933 //++timo we don't have allocation nor storage for vpEntity, no checks for this one
00934 void WINAPI QERApp_CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
00935 {
00936     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00937     g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
00938     return;
00939 }
00940 
00941 char* WINAPI QERApp_ReadProjectKey(char* key)
00942 {
00943     return ValueForKey(g_qeglobals.d_project_entity, key);
00944 }
00945 
00946 int WINAPI QERApp_ScanFileForEClass(char *filename )
00947 {
00948     // set single class parsing
00949     parsing_single = true;
00950     Eclass_ScanFile(filename);
00951     if (eclass_found)
00952     {
00953         eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
00954         return 1;
00955     }
00956     return 0;
00957 }
00958 
00959 // the vpBrush needs to be in m_BrushHandles
00960 //++timo add a debug check to see if we found the brush handle
00961 // NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
00962 // links the brush to its entity, everything else is done when commiting the entity to the map
00963 void CPlugInManager::CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
00964 {
00965     brush_t* pb;
00966     entity_t* pe;
00967     for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
00968     {
00969         if (vpBrush == m_BrushHandles.GetAt(i))
00970         {
00971             m_BrushHandles.RemoveAt(i);
00972             pb = reinterpret_cast<brush_t*>(vpBrush);
00973             pe = reinterpret_cast<entity_t *>(vpEntity);
00974             Entity_LinkBrush (pe, pb);
00975         }
00976     }
00977     Sys_UpdateWindows(W_ALL);
00978 }
00979 
00980 // the vpEntity must be in m_EntityHandles
00981 void WINAPI QERApp_CommitEntityHandleToMap(LPVOID vpEntity)
00982 {
00983     AFX_MANAGE_STATE(AfxGetStaticModuleState());
00984     g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
00985     return;
00986 }
00987 
00988 int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
00989 {
00990     char cPath[1024];
00991     sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
00992   int nSize = LoadFile( cPath, buffer);
00993   if (nSize == -1)
00994   {
00995     nSize = PakLoadAnyFile(cPath, buffer);
00996   }
00997     return nSize;
00998 }
00999 
01000 char * WINAPI QERApp_ExpandReletivePath (char *p)
01001 {
01002     return ExpandReletivePath(p);
01003 }
01004 
01005 // NOTE: this is a simplified version
01006 int WINAPI QERApp_HasShader( const char *pName )
01007 {
01008     CShaderInfo *pInfo = hasShader( pName );
01009     if (pInfo)
01010         return 1;
01011     return 0;
01012 }
01013 
01014 qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
01015 {
01016     // if the texture is not loaded yet, this call will get it loaded
01017     // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_hdcBase , g_qeglobals.d_hglrcBase GL context
01018     // the plugin may set the GL context to whatever he likes, but then load would fail
01019     // NOTE: is context switching time-consuming? then maybe the plugin could handle the context switch and only add a 
01020     // sanity check in debug mode here
01021     // read current context
01022     HDC pluginHDC = qwglGetCurrentDC();
01023     HGLRC pluginHGLRC = qwglGetCurrentContext();
01024     qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
01025     qtexture_t* qtex = Texture_ForName( name );
01026     return qtex;
01027     qwglMakeCurrent( pluginHDC, pluginHGLRC );
01028 }
01029 
01030 void WINAPI QERApp_RadiantFree( void * buf )
01031 {
01032     free( buf );
01033 }
01034 
01035 char* WINAPI QERApp_Token()
01036 {
01037     return token;
01038 }
01039 
01040 char* WINAPI QERApp_GetMapName()
01041 {
01042     return currentmap;
01043 }
01044 
01045 void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
01046 {
01047     entity_t *pe;
01048     eclass_t *e;
01049     brush_t     *b;
01050     vec3_t mins,maxs;
01051     bool has_brushes;
01052     for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
01053     {
01054         if (vpEntity == m_EntityHandles.GetAt(i))
01055         {
01056             m_EntityHandles.RemoveAt(i);
01057             pe = reinterpret_cast<entity_t*>(vpEntity);
01058             // fill additional fields
01059             // straight copy from Entity_Parse
01060             // entity_t::origin
01061             GetVectorForKey (pe, "origin", pe->origin);
01062             // entity_t::eclass
01063             if (pe->brushes.onext == &pe->brushes)
01064                 has_brushes = false;
01065             else
01066                 has_brushes = true;
01067             e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
01068             pe->eclass = e;
01069             // fixedsize
01070             if (e->fixedsize)
01071             {
01072                 if (pe->brushes.onext != &pe->brushes)
01073                 {
01074                     Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
01075                 }
01076                 // create a custom brush
01077                 VectorAdd(e->mins, pe->origin, mins);
01078                 VectorAdd(e->maxs, pe->origin, maxs);
01079                 float a = 0;
01080                 if (e->nShowFlags & ECLASS_MISCMODEL)
01081                 {
01082                     char* p = ValueForKey(pe, "model");
01083                     if (p != NULL && strlen(p) > 0)
01084                     {
01085                         vec3_t vMin, vMax;
01086                         a = FloatForKey (pe, "angle");
01087                         if (GetCachedModel(pe, p, vMin, vMax))
01088                         {
01089                               // create a custom brush
01090                               VectorAdd (pe->md3Class->mins, pe->origin, mins);
01091                               VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
01092                         }
01093                     }
01094                 }
01095         
01096                 b = Brush_Create (mins, maxs, &e->texdef);
01097 
01098                 if (a)
01099                 {
01100                     vec3_t vAngle;
01101                     vAngle[0] = vAngle[1] = 0;
01102                     vAngle[2] = a;
01103                     Brush_Rotate(b, vAngle, pe->origin, false);
01104                 }
01105 
01106                 b->owner = pe;
01107 
01108                 b->onext = pe->brushes.onext;
01109                 b->oprev = &pe->brushes;
01110                 pe->brushes.onext->oprev = b;
01111                 pe->brushes.onext = b;
01112             }
01113             else
01114             {   // brush entity
01115                 if (pe->brushes.next == &pe->brushes)
01116                     Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
01117             }
01118 
01119             // add brushes to the active brushes list
01120             // and build them along the way
01121             for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
01122             {
01123                 // convert between old brushes and brush primitive
01124                 if (g_qeglobals.m_bBrushPrimitMode)
01125                 {
01126                     // we only filled the shift scale rot fields, needs conversion
01127                     Brush_Build( b, true, true, true );
01128                 }
01129                 else
01130                 {
01131                     // we are using old brushes
01132                     Brush_Build( b );
01133                 }
01134                 b->next = active_brushes.next;
01135                 active_brushes.next->prev = b;
01136                 b->prev = &active_brushes;
01137                 active_brushes.next = b;
01138             }
01139 
01140             // handle worldspawn entities
01141             // if worldspawn has no brushes, use the new one
01142             if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
01143             {
01144                 if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
01145                 {
01146                     // worldspawn already has brushes
01147                     Sys_Printf ("Commiting worldspawn as func_group\n");
01148                     SetKeyValue(pe, "classname", "func_group");
01149                     // add the entity to the end of the entity list
01150                     pe->next = &entities;
01151                     pe->prev = entities.prev;
01152                     entities.prev->next = pe;
01153                     entities.prev = pe;
01154                     g_qeglobals.d_num_entities++;
01155                 }
01156                 else
01157                 {
01158                     // there's a worldspawn with no brushes, we assume the map is empty
01159                     if ( world_entity )
01160                     {
01161                         Entity_Free( world_entity );
01162                         world_entity = pe;
01163                     }
01164                     else
01165                         Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
01166                 }
01167             }
01168             else
01169             {
01170                 // add the entity to the end of the entity list
01171                 pe->next = &entities;
01172                 pe->prev = entities.prev;
01173                 entities.prev->next = pe;
01174                 entities.prev = pe;
01175                 g_qeglobals.d_num_entities++;
01176             }
01177         }
01178     }
01179 }
01180 
01181 void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
01182 {
01183     g_bScreenUpdates = bScreenUpdates; 
01184 }
01185 
01186 texturewin_t* WINAPI QERApp_QeglobalsTexturewin()
01187 {
01188     return &g_qeglobals.d_texturewin;
01189 }
01190 
01191 _QERTextureInfo* CPlugInManager::GetTextureInfo()
01192 {
01193   if (m_pTexturePlug != NULL)
01194   {
01195     return m_pTexturePlug->getTextureInfo();
01196   }
01197   else
01198   {
01199     return NULL;
01200   }
01201 }
01202 
01203 LPVOID CPlugInManager::GetSurfaceFlags()
01204 {
01205   if (m_pSurfaceListPlug != NULL)
01206   {
01207     return m_pSurfaceListPlug->getSurfaceFlags();
01208   }
01209   else
01210   {
01211     return NULL;
01212   }
01213 }
01214 
01215 void CPlugInManager::LoadTexture(const char *pFilename)
01216 {
01217   if (m_pTexturePlug != NULL)
01218   {
01219     m_pTexturePlug->loadTexture(pFilename);
01220   }
01221 }
01222 
01223 patchMesh_t* WINAPI QERApp_GetSelectedPatch( )
01224 {
01225     for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
01226     {
01227         if (pb->patchBrush)
01228         {
01229             return pb->pPatch;
01230         }
01231     }
01232 #ifdef _DEBUG
01233     Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
01234 #endif
01235     return NULL;
01236 }
01237 
01238 char* WINAPI QERApp_GetGamePath()
01239 {
01240     return g_PrefsDlg.m_strQuake2.GetBuffer(0);
01241 }
01242 
01243 char* WINAPI QERApp_GetQERPath()
01244 {
01245     return g_strAppPath.GetBuffer(0);
01246 }
01247 
01248 // patches in/out -----------------------------------
01249 int WINAPI QERApp_AllocateActivePatchHandles()
01250 {
01251     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01252     return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
01253 }
01254 
01255 int CPlugInManager::AllocateActivePatchHandles()
01256 {
01257     int n = 0;
01258     for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
01259     {
01260         if (pb->patchBrush)
01261         {
01262             n++;
01263             m_PatchesHandles.Add(pb);
01264         }
01265     }
01266     return n;
01267 }
01268 
01269 int WINAPI QERApp_AllocateSelectedPatchHandles()
01270 {
01271     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01272     return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
01273 }
01274     
01275 int CPlugInManager::AllocateSelectedPatchHandles()
01276 {
01277     int n = 0;
01278     for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
01279     {
01280         if (pb->patchBrush)
01281         {
01282             n++;
01283             m_PatchesHandles.Add(pb);
01284         }
01285     }
01286     return n;
01287 }
01288 
01289 void WINAPI QERApp_ReleasePatchHandles()
01290 {
01291     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01292     g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
01293 }
01294 
01295 patchMesh_t* WINAPI QERApp_GetPatchData(int index)
01296 {
01297     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01298     static patchMesh_t patch;
01299     patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
01300     if (pPatch)
01301     {
01302         memcpy( &patch, pPatch, sizeof(patchMesh_t) );
01303         return &patch;
01304     }
01305     return NULL;
01306 }
01307 
01308 void WINAPI QERApp_DeletePatch(int index)
01309 {
01310     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01311     patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
01312     if (pPatch)
01313     {
01314         brush_t *pb = pPatch->pSymbiot;
01315         Patch_Delete( pPatch );
01316         if (pb)
01317             Brush_Free( pb );
01318     }
01319 #ifdef _DEBUG
01320     Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
01321 #endif
01322 }
01323 
01324 int WINAPI QERApp_CreatePatchHandle()
01325 {
01326     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01327     return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
01328 }
01329 
01330 int CPlugInManager::CreatePatchHandle()
01331 {
01332     // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
01333     patchMesh_t *pPatch = MakeNewPatch();
01334     m_PluginPatches.Add( pPatch );
01335     // change mode
01336     PatchesMode = EAllocatedPatches;
01337     return m_PluginPatches.GetSize()-1;
01338 }
01339 
01340 void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
01341 {
01342     AFX_MANAGE_STATE(AfxGetStaticModuleState());
01343     g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
01344 }
01345 
01346 void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
01347 {
01348     if (PatchesMode==EAllocatedPatches)
01349     {
01350         patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
01351         memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
01352         // patch texturing, if none given use current texture
01353         if (texName)
01354             pPatch->d_texture = Texture_ForName(texName);
01355         if ( !pPatch->d_texture )
01356         {
01357             pPatch->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
01358             // checking .. just in case
01359             if (!pPatch->d_texture)
01360             {
01361 #ifdef _DEBUG
01362                 Sys_Printf("WARNING: failed to set patch to current texture in CPlugInManager::CommitPatchHandleToMap\n");
01363 #endif
01364                 pPatch->d_texture = notexture;
01365             }
01366         }
01367         g_bScreenUpdates = false;
01368         // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
01369         brush_t *pb = AddBrushForPatch( pPatch, true );
01370         Select_Brush( pb );
01371         g_bScreenUpdates = true;
01372