]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/pluginmanager.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / pluginmanager.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 // PlugInManager.cpp: implementation of the CPlugInManager class.\r
23 //\r
24 //////////////////////////////////////////////////////////////////////\r
25 \r
26 #include "stdafx.h"\r
27 #if defined (__linux__) || defined (__APPLE__)\r
28   #include <dirent.h>\r
29   #include <sys/time.h>\r
30 #endif\r
31 #ifdef __APPLE__\r
32   #ifdef __cplusplus\r
33     extern "C" {\r
34     #endif\r
35     #include <dlfcn.h>\r
36     #ifdef __cplusplus\r
37     }\r
38   #endif\r
39 #endif\r
40 #ifdef _WIN32\r
41   #include "objbase.h"\r
42 #endif\r
43 #include "pluginmanager.h"\r
44 #include "plugin.h"\r
45 #include "missing.h"\r
46 \r
47 #include "version.h"\r
48 \r
49 CRadiantImageManager g_ImageManager;\r
50 CRadiantPluginManager g_PluginsManager;    \r
51 \r
52 _QERPlugSurfaceTable g_SurfaceTable;\r
53 _QERFileSystemTable g_FileSystemTable;\r
54 _QERShadersTable g_ShadersTable;\r
55 _QERPlugMapTable g_MapTable;\r
56 _QERPlugMapTable g_MapTable2;\r
57 _QEREntityTable g_EntityTable;\r
58 _EClassTable g_EClassDefTable;\r
59 \r
60 /*!\r
61   extending entity class formats\r
62   this approach only allows a single additional format, but it is enough for now\r
63 */\r
64 bool g_bHaveEClassExt = false;\r
65 _EClassTable g_EClassExtTable;\r
66 \r
67 \r
68 filetype_t g_pattern_all("all files", "*.*");\r
69 filetype_t g_pattern_projqe4v2("qe4 v2 project files", "*.qe4");\r
70 filetype_t g_pattern_projxml("xml project files", "*.proj");\r
71 filetype_t g_pattern_mapq3("quake3 maps", "*.map");\r
72 filetype_t g_pattern_mapxml("xml quake3 maps", "*.xmap");\r
73 filetype_t g_pattern_modelmd3("md3 models", "*.md3");\r
74 filetype_t g_pattern_modelmdc("mdc models", "*.mdc");\r
75 filetype_t g_pattern_modelmd2("md2 models", "*.md2");\r
76 filetype_t g_pattern_modelmdl("mdl models", "*.mdl");\r
77 //filetype_t g_pattern_modelea3("EA3 models", "*.ea3");\r
78 filetype_t g_pattern_soundwav("PCM sound files", "*.wav");\r
79 filetype_t g_pattern_regq3("quake3 region", "*.reg");\r
80 \r
81 #include <map>\r
82 \r
83 class RadiantFileTypeRegistry : public IFileTypeRegistry\r
84 {\r
85 public:\r
86   virtual ~RadiantFileTypeRegistry() {}\r
87   virtual void addType(const char* key, filetype_t type)\r
88   {\r
89     m_typelists[key].push_back(type);\r
90   }\r
91   virtual void getTypeList(const char* key, IFileTypeList* typelist)\r
92   {\r
93     filetype_list_t& list_ref = m_typelists[key];\r
94     for(unsigned int i=0; i<list_ref.size(); ++i)\r
95       typelist->addType(list_ref[i].getType());\r
96   }\r
97 private:\r
98   struct filetype_copy_t\r
99   {\r
100     inline filetype_copy_t(const filetype_t other)\r
101       : m_name(other.name), m_pattern(other.pattern)\r
102     {}\r
103     inline filetype_t getType() const\r
104     {\r
105       return filetype_t(m_name.c_str(), m_pattern.c_str());\r
106     }\r
107   private:\r
108     string_t m_name;\r
109     string_t m_pattern;\r
110   };\r
111   typedef vector<filetype_copy_t> filetype_list_t;\r
112   map<string_t, filetype_list_t> m_typelists;\r
113 };\r
114 \r
115 static RadiantFileTypeRegistry g_patterns;\r
116 \r
117 IFileTypeRegistry* GetFileTypeRegistry()\r
118 {\r
119   return &g_patterns;\r
120 }\r
121 \r
122 void InitFileTypes()\r
123 {\r
124   //GetFileTypeRegistry()->addType("project", g_pattern_projqe4v2);\r
125   GetFileTypeRegistry()->addType("project", g_pattern_projxml);\r
126 \r
127   GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapq3);\r
128   GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapxml);\r
129   \r
130   GetFileTypeRegistry()->addType("region", g_pattern_regq3);\r
131 /*\r
132   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd3);\r
133   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd2);\r
134   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdl);\r
135   GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdc);\r
136   //GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelea3);\r
137   */\r
138 \r
139   GetFileTypeRegistry()->addType("sound", g_pattern_soundwav);\r
140 }\r
141 \r
142 \r
143 class CRadiantModelModuleManager : public CSynapseAPIManager\r
144 {\r
145   typedef list<APIDescriptor_t*> APIDescriptorList;\r
146 \r
147   APIDescriptorList mAPIs;\r
148 public:\r
149   CRadiantModelModuleManager()\r
150   {\r
151     SetMatchAPI(MODEL_MAJOR, "*");\r
152   }\r
153   virtual ~CRadiantModelModuleManager()\r
154   {\r
155     APIDescriptorList::iterator i;\r
156     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
157     {\r
158       delete (_QERPlugModelTable*)(*i)->mpTable;\r
159       delete *i;\r
160       *i = NULL;\r
161     }\r
162     mAPIs.clear();\r
163   }\r
164 \r
165   // CSynapseAPIManager interface -------------------\r
166   APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)\r
167   {\r
168     APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
169     pRequireAPI->mpTable = new _QERPlugModelTable;\r
170     ((_QERPlugModelTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugModelTable);\r
171     pRequireAPI->mSize = sizeof(_QERPlugModelTable);\r
172     mAPIs.push_front(pRequireAPI);\r
173     return pRequireAPI;\r
174   }\r
175 \r
176   // Model Manager specific\r
177   const _QERPlugModelTable* GetModelTable(const char* version)\r
178   {\r
179     APIDescriptorList::iterator i;\r
180     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
181       if(strcmp(version, (*i)->minor_name) == 0)\r
182         return ((_QERPlugModelTable*)(*i)->mpTable);\r
183     return NULL;\r
184   }\r
185 };\r
186 \r
187 CRadiantModelModuleManager g_ModelManager;\r
188 \r
189 /*! One of these exists for each unique model ID in use */\r
190 class CModelWrapper\r
191 {\r
192   friend class CModelManager;\r
193 public:\r
194   CModelWrapper (const char *id, const char* version) : refcount(1)\r
195   {\r
196     copy(id, version);\r
197     construct();\r
198   }\r
199   void Refresh()\r
200   {\r
201     destroy();\r
202     construct();\r
203   }\r
204   ~CModelWrapper ()\r
205   {\r
206     destroy();\r
207   }\r
208 private:\r
209   void copy(const char* id, const char* version)\r
210   {\r
211     m_id = id;\r
212     m_version = version;\r
213   }\r
214   void construct()\r
215   {\r
216     m_model.pRender = NULL;\r
217     m_model.pSelect = NULL;\r
218     m_model.pEdit = NULL;\r
219 \r
220     const _QERPlugModelTable* pTable = g_ModelManager.GetModelTable(m_version.c_str());\r
221 \r
222     if(pTable != NULL)\r
223       pTable->m_pfnLoadModel(&m_model, m_id.c_str());\r
224   }\r
225   void destroy()\r
226   {\r
227     if (m_model.pRender) m_model.pRender->DecRef();\r
228     if (m_model.pSelect) m_model.pSelect->DecRef();\r
229     if (m_model.pEdit) m_model.pEdit->DecRef();\r
230   }\r
231   string_t m_id;\r
232   string_t m_version;\r
233   entity_interfaces_t m_model;\r
234   int refcount;\r
235 };\r
236 \r
237 /*! Creates and tracks CModelWrapper instances.\r
238 Creates a new instance for each unique ID requested, keeps count of the number of\r
239 times an ID is being referenced, and destroys any instance that is no longer in use */\r
240 class CModelManager : public IModelCache\r
241 {\r
242 public:\r
243   CModelManager()\r
244   {\r
245     m_ptrs = g_ptr_array_new ();\r
246   }\r
247   virtual ~CModelManager()\r
248   {\r
249     g_ptr_array_free(m_ptrs, FALSE);\r
250   }\r
251 \r
252   virtual void DeleteByID(const char *id, const char* version)\r
253   {\r
254     unsigned int i;\r
255     CModelWrapper *elem;\r
256     for(i=0; i<m_ptrs->len; i++)\r
257     {\r
258       elem = (CModelWrapper*)m_ptrs->pdata[i];\r
259       if(strcmp(elem->m_version.c_str(), version) == 0\r
260         && strcmp(elem->m_id.c_str(), id) == 0\r
261         && --elem->refcount == 0)\r
262       {\r
263         g_ptr_array_remove_index_fast(m_ptrs, i);\r
264         delete elem;\r
265         return;\r
266       }\r
267     }\r
268   }\r
269 \r
270   virtual entity_interfaces_t *GetByID(const char *id, const char* version)\r
271   {\r
272     unsigned int i;\r
273     CModelWrapper *elem;\r
274     for(i=0; i<m_ptrs->len; i++)\r
275     {\r
276       elem = (CModelWrapper*)m_ptrs->pdata[i];\r
277       if(strcmp(elem->m_version.c_str(), version) == 0\r
278         && strcmp(elem->m_id.c_str(), id) == 0)\r
279       {\r
280         elem->refcount++;\r
281         return &elem->m_model;\r
282       }\r
283     }\r
284     \r
285     elem = new CModelWrapper(id, version);\r
286     g_ptr_array_add(m_ptrs, elem);\r
287 \r
288     return &elem->m_model;\r
289   }\r
290 \r
291   virtual void RefreshAll()\r
292   {\r
293     for(unsigned int i=0; i<m_ptrs->len; ++i)\r
294       ((CModelWrapper*)m_ptrs->pdata[i])->Refresh();\r
295   }\r
296 private:\r
297   GPtrArray *m_ptrs; // array of CModelWrapper*\r
298 };\r
299 \r
300 CModelManager g_model_cache;\r
301 \r
302 IModelCache* GetModelCache()\r
303 {\r
304   return &g_model_cache;\r
305 }\r
306 \r
307 // toolbar manager\r
308 class CRadiantToolbarModuleManager : public CSynapseAPIManager\r
309 {\r
310   typedef list<APIDescriptor_t*> APIDescriptorList;\r
311 \r
312   APIDescriptorList mAPIs;\r
313 public:\r
314   CRadiantToolbarModuleManager()\r
315   {\r
316     SetMatchAPI(TOOLBAR_MAJOR, "*");\r
317   }\r
318   virtual ~CRadiantToolbarModuleManager()\r
319   {\r
320     APIDescriptorList::iterator i;\r
321     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
322     {\r
323       delete (_QERPlugToolbarTable*)(*i)->mpTable;\r
324       delete *i;\r
325       *i = NULL;\r
326     }\r
327     mAPIs.clear();\r
328   }\r
329   \r
330   // CSynapseAPIManager interface -------------------\r
331   APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)\r
332   {\r
333     APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
334     pRequireAPI->mpTable = new _QERPlugToolbarTable;\r
335     ((_QERPlugToolbarTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugToolbarTable);\r
336     pRequireAPI->mSize = sizeof(_QERPlugToolbarTable);\r
337     mAPIs.push_front(pRequireAPI);\r
338     return pRequireAPI;\r
339   }\r
340 \r
341   // Toolbar Manager specific\r
342   void ConstructToolbar()\r
343   {\r
344     APIDescriptorList::iterator i;\r
345     for(i=mAPIs.begin(); i!=mAPIs.end(); i++)\r
346       AddItem((_QERPlugToolbarTable*)(*i)->mpTable);\r
347   }\r
348   \r
349 private:\r
350 \r
351   void AddItem(_QERPlugToolbarTable* pTable)\r
352   {\r
353     const unsigned int count = pTable->m_pfnToolbarButtonCount();\r
354     for(unsigned int i=0; i<count; ++i)\r
355     {\r
356       const IToolbarButton* button = pTable->m_pfnGetToolbarButton(i);\r
357       g_pParentWnd->AddPlugInToolbarButton(button);\r
358     }\r
359   }\r
360 };\r
361 \r
362 CRadiantToolbarModuleManager g_ToolbarModuleManager;\r
363 \r
364 \r
365 /* image manager ---------------------------------------- */\r
366 \r
367 CRadiantImageManager::~CRadiantImageManager()\r
368 {\r
369   list<CImageTableSlot *>::iterator iSlot;\r
370   for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
371   {\r
372     delete *iSlot;\r
373     *iSlot = NULL;\r
374   }\r
375 }\r
376 \r
377 void CImageTableSlot::InitForFillAPITable(APIDescriptor_t *pAPI)\r
378 {\r
379   mpAPI = pAPI;\r
380   mpTable = new _QERPlugImageTable;\r
381   mpTable->m_nSize = sizeof(_QERPlugImageTable);\r
382   mpAPI->mSize = sizeof(_QERPlugImageTable);\r
383   mpAPI->mpTable = mpTable;\r
384 }\r
385 \r
386 void CRadiantImageManager::FillAPITable(APIDescriptor_t *pAPI)\r
387 {\r
388   CImageTableSlot *pSlot = new CImageTableSlot();\r
389   pSlot->InitForFillAPITable(pAPI);\r
390   mSlots.push_front(pSlot);\r
391 }\r
392 \r
393 /*!\r
394   Loads an image by calling the module that handles the extension extracted from the filename\r
395   \param name The filename to load. If no extension is provided, we walk the list of supported extensions.\r
396   \param pic The returned image data\r
397   \param width The returned width of the image\r
398   \param height The returned height of the image\r
399 */\r
400 void CRadiantImageManager::LoadImage(const char *name, byte **pic, int *width, int *height)\r
401 {\r
402   const char *ext = NULL;\r
403   int len;\r
404 \r
405   // extract extension\r
406   len = strlen (name);\r
407   if ((len > 5) && (name[len-4] == '.'))\r
408     ext = &name[len-3];\r
409 \r
410   if (ext == NULL)\r
411   {\r
412     // if no extension is provided, start walking through the list\r
413     Str fullname;\r
414     list<CImageTableSlot *>::iterator iSlot;\r
415     for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
416     {\r
417       APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();\r
418       fullname.Format("%s.%s", name, pAPI->minor_name);\r
419       (*iSlot)->GetTable()->m_pfnLoadImage(fullname.GetBuffer(), pic, width, height);\r
420       if (*pic)\r
421         return; // this was the right extension, we loaded\r
422     }\r
423     return;\r
424   }\r
425   \r
426   // start walking the interfaces\r
427   list<CImageTableSlot *>::iterator iSlot;\r
428   for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)\r
429   {\r
430     APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();\r
431     if (!strcmp(pAPI->minor_name, ext))\r
432     {\r
433       (*iSlot)->GetTable()->m_pfnLoadImage(name, pic, width, height);\r
434       return;\r
435     }\r
436   }\r
437   Sys_FPrintf(SYS_WRN, "WARNING: no image table for extension '%s'\n", ext);\r
438 }\r
439 \r
440 void CRadiantImageManager::BeginExtensionsScan()\r
441 {\r
442   mExtScanSlot = mSlots.begin();\r
443 }\r
444 \r
445 const char* CRadiantImageManager::GetNextExtension()\r
446 {\r
447   if (mExtScanSlot != mSlots.end())\r
448   {\r
449     char *ext = (*mExtScanSlot)->GetDescriptor()->minor_name;\r
450     mExtScanSlot++;\r
451     return ext;\r
452   }\r
453   return NULL;\r
454 }\r
455 \r
456 /* plugin manager --------------------------------------- */\r
457 APIDescriptor_t* CRadiantPluginManager::BuildRequireAPI(APIDescriptor_t *pAPI)\r
458 {  \r
459   CPluginSlot *pSlot = new CPluginSlot(pAPI);\r
460   mSlots.push_front(pSlot);\r
461   return pSlot->GetDescriptor();\r
462 }\r
463 \r
464 void CRadiantPluginManager::PopulateMenu()\r
465 {\r
466   list<CPluginSlot *>::iterator iPlug;\r
467   for(iPlug=mSlots.begin(); iPlug != mSlots.end(); iPlug++)\r
468   {\r
469     g_pParentWnd->AddPlugInMenuItem(*iPlug);\r
470   }\r
471 }\r
472 \r
473 void CSynapseClientRadiant::ImportMap(IDataStream *in, CPtrArray *ents, const char *type)\r
474 {\r
475   if (strcmp(type,"map")==0)\r
476   {\r
477     g_MapTable.m_pfnMap_Read(in, ents);\r
478   }\r
479   else if (strcmp(type,"xmap")==0)\r
480   {\r
481     g_MapTable2.m_pfnMap_Read(in, ents);    \r
482   }\r
483   else\r
484     Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);\r
485 }\r
486 \r
487 void CSynapseClientRadiant::ExportMap(CPtrArray *ents, IDataStream *out, const char *type)\r
488 {\r
489   if (strcmp(type,"map")==0)\r
490   {\r
491     g_MapTable.m_pfnMap_Write(ents, out);\r
492   }\r
493   else if (strcmp(type,"xmap")==0)\r
494   {\r
495     g_MapTable2.m_pfnMap_Write(ents, out);\r
496   }\r
497   else\r
498     Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);\r
499 }\r
500 \r
501 CPluginSlot::CPluginSlot(APIDescriptor_t *pAPI)\r
502 {\r
503   mpAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);\r
504   mpTable = new _QERPluginTable;\r
505   mpTable->m_nSize = sizeof(_QERPluginTable);\r
506   mpAPI->mSize = sizeof(_QERPluginTable);\r
507   mpAPI->mpTable = mpTable;\r
508   m_CommandStrings = NULL;\r
509   m_CommandIDs = NULL;\r
510   m_bReady = false;\r
511 }\r
512 \r
513 CPluginSlot::~CPluginSlot()\r
514 {  \r
515   delete mpAPI;\r
516   delete mpTable;\r
517   while (m_CommandStrings)\r
518   {\r
519     ::free (m_CommandStrings->data);\r
520     m_CommandStrings = g_slist_remove (m_CommandStrings, m_CommandStrings->data);\r
521   }\r
522 }\r
523 \r
524 void CPluginSlot::Init()\r
525 {\r
526   CString str =   mpTable->m_pfnQERPlug_GetCommandList();\r
527   char cTemp[1024];\r
528   strcpy(cTemp, str);\r
529   char* token = strtok(cTemp, ",;");\r
530   if (token && *token == ' ')\r
531   {\r
532     while (*token == ' ')\r
533     token++;\r
534   }\r
535   while (token != NULL)\r
536   {\r
537     m_CommandStrings = g_slist_append (m_CommandStrings, strdup (token));\r
538     token = strtok(NULL, ",;");\r
539   }\r
540   mpTable->m_pfnQERPlug_Init(NULL, (void*)g_pParentWnd->m_pWidget);\r
541   m_bReady = true;\r
542 }\r
543 \r
544 const char* CPluginSlot::getMenuName()\r
545 {\r
546   return mpAPI->minor_name;\r
547 }\r
548 \r
549 int CPluginSlot::getCommandCount()\r
550 {\r
551   if (!m_bReady)\r
552     Init();\r
553   return g_slist_length (m_CommandStrings);  \r
554 }\r
555   \r
556 const char* CPluginSlot::getCommand(int n)\r
557 {\r
558   if (!m_bReady)\r
559     Init();\r
560   return (char*)g_slist_nth_data (m_CommandStrings, n);  \r
561 }\r
562 \r
563 void CPluginSlot::addMenuID(int n)\r
564 {\r
565   m_CommandIDs = g_slist_append (m_CommandIDs, GINT_TO_POINTER (n));\r
566 }\r
567 \r
568 bool CPluginSlot::ownsCommandID(int n)\r
569 {\r
570   GSList* lst;\r
571 \r
572   for (lst = m_CommandIDs; lst != NULL; lst = g_slist_next (lst))\r
573   {\r
574     if (GPOINTER_TO_INT (lst->data) == n)\r
575       return true;\r
576   }\r
577   return false;\r
578 }\r
579 \r
580 void CPluginSlot::Dispatch(const char *p)\r
581 {\r
582   vec3_t vMin, vMax;\r
583   if (selected_brushes.next == &selected_brushes)\r
584   {\r
585     vMin[0] = vMin[1] = vMin[2] = 0;\r
586     VectorCopy(vMin, vMax);\r
587   } else\r
588   {\r
589     Select_GetBounds (vMin, vMax);\r
590   }\r
591   mpTable->m_pfnQERPlug_Dispatch(p, vMin, vMax, QE_SingleBrush(true));\r
592 }\r
593 \r
594 CRadiantPluginManager::~CRadiantPluginManager()\r
595 {\r
596   list<CPluginSlot *>::iterator iSlot;\r
597   for(iSlot=mSlots.begin(); iSlot!=mSlots.end(); iSlot++)\r
598   {\r
599     delete *iSlot;\r
600     *iSlot = NULL;\r
601   }\r
602 }\r
603 \r
604 bool CRadiantPluginManager::Dispatch(int n, const char* p)\r
605 {\r
606   list<CPluginSlot *>::iterator iPlug;\r
607   for(iPlug=mSlots.begin(); iPlug!=mSlots.end(); iPlug++)\r
608   {\r
609     CPluginSlot *pPlug = *iPlug;\r
610     if (pPlug->ownsCommandID(n))\r
611     {\r
612       pPlug->Dispatch(p);\r
613       return true;\r
614     }\r
615   }\r
616   return false;\r
617 }\r
618 \r
619 //////////////////////////////////////////////////////////////////////\r
620 // Construction/Destruction\r
621 //////////////////////////////////////////////////////////////////////\r
622 \r
623 CPlugInManager::CPlugInManager()\r
624 {\r
625   PatchesMode = EActivePatches;\r
626   m_PlugIns = NULL;\r
627 }\r
628 \r
629 CPlugInManager::~CPlugInManager()\r
630 {\r
631   Cleanup();\r
632 }\r
633 \r
634 void CPlugInManager::InitForDir(const Str &dir)\r
635 {\r
636   Str path;\r
637 \r
638   path = dir;\r
639   path += g_strPluginsDir;\r
640   // SYNAPSE\r
641   g_pParentWnd->GetSynapseServer().AddSearchPath(path);\r
642 \r
643   if (strcmp(g_strPluginsDir.GetBuffer(), g_strModulesDir.GetBuffer()) != 0)\r
644   {\r
645     path = dir;\r
646     path += g_strModulesDir;\r
647     // SYNAPSE\r
648     g_pParentWnd->GetSynapseServer().AddSearchPath(path);\r
649   } \r
650 }\r
651 \r
652 static const XMLConfigEntry_t manager_entries[] = \r
653   { \r
654     { VFS_MAJOR,            SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },\r
655     { SHADERS_MAJOR,        SYN_REQUIRE, sizeof(g_ShadersTable),    &g_ShadersTable },\r
656     { MAP_MAJOR,            SYN_REQUIRE, sizeof(g_MapTable),        &g_MapTable },\r
657     { ECLASS_MAJOR,         SYN_REQUIRE, sizeof(g_EClassDefTable),  &g_EClassDefTable },\r
658     { SURFACEDIALOG_MAJOR,  SYN_REQUIRE, sizeof(g_SurfaceTable),    &g_SurfaceTable },\r
659     { NULL, SYN_UNKNOWN, 0, NULL } };\r
660 \r
661 void CPlugInManager::Init()\r
662 {\r
663   Str synapse_config;\r
664   \r
665   Cleanup();\r
666   \r
667   // set some globals\r
668   g_qeglobals.bBSPFrontendPlugin = false;\r
669 \r
670   InitForDir(g_strGameToolsPath);\r
671   InitForDir(g_strAppPath);\r
672 \r
673   synapse_config = g_strGameToolsPath;\r
674   synapse_config += "synapse.config";\r
675   if (!g_pParentWnd->GetSynapseServer().Initialize(synapse_config.GetBuffer(), &Sys_Printf_VA))\r
676     Error("Synpase server initialization failed (see console)\n");\r
677   \r
678   // builtin modules\r
679   g_pParentWnd->GetSynapseServer().EnumerateBuiltinModule(&eclass_def);\r
680   \r
681   // APIs we provide\r
682   g_pParentWnd->GetSynapseClient().AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1));\r
683   g_pParentWnd->GetSynapseClient().AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(_QERScripLibTable));\r
684   g_pParentWnd->GetSynapseClient().AddAPI(BRUSH_MAJOR, NULL, sizeof(_QERBrushTable));\r
685   g_pParentWnd->GetSynapseClient().AddAPI(APPSHADERS_MAJOR, NULL, sizeof(_QERAppShadersTable));\r
686   g_pParentWnd->GetSynapseClient().AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable));\r
687   g_pParentWnd->GetSynapseClient().AddAPI(DATA_MAJOR, NULL, sizeof(_QERAppDataTable));\r
688   g_pParentWnd->GetSynapseClient().AddAPI(PATCH_MAJOR, NULL, sizeof(_QERPatchTable));\r
689   g_pParentWnd->GetSynapseClient().AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(_EClassManagerTable));\r
690   g_pParentWnd->GetSynapseClient().AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(_QERSelectedFaceTable));\r
691   g_pParentWnd->GetSynapseClient().AddAPI(APPSURFACEDIALOG_MAJOR, NULL, sizeof(_QERAppSurfaceTable));\r
692   g_pParentWnd->GetSynapseClient().AddAPI(UNDO_MAJOR, NULL, sizeof(_QERUndoTable));\r
693   g_pParentWnd->GetSynapseClient().AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable));  \r
694   g_pParentWnd->GetSynapseClient().AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable));  \r
695   g_pParentWnd->GetSynapseClient().AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable));  \r
696   \r
697   // modules configured by XML\r
698   if ( !g_pParentWnd->GetSynapseClient().ConfigXML( &g_pParentWnd->GetSynapseServer(), "core", manager_entries ) ) {\r
699     Error("Synapse server initialization failed (see console)\n");\r
700   }\r
701   \r
702   // adding a manager is a special case that ConfigXML doesn't take care of\r
703   g_pParentWnd->GetSynapseServer().SelectClientConfig( "core" );\r
704   char *minor;\r
705   if ( !g_pParentWnd->GetSynapseServer().GetConfigForAPI( IMAGE_MAJOR, &minor ) ) {\r
706     Syn_Printf( "GetConfigForAPI '%s' failed - invalid XML config file?\n", IMAGE_MAJOR );\r
707     Error("Synapse server initialization failed (see console)\n");\r
708   }\r
709   g_ImageManager.SetMatchAPI( IMAGE_MAJOR, minor );\r
710   g_pParentWnd->GetSynapseClient().AddManager( &g_ImageManager );\r
711   \r
712   // SYN_REQUIRE entries which are still hardcoded\r
713   g_pParentWnd->GetSynapseClient().AddAPI(MAP_MAJOR, "mapxml", sizeof(g_MapTable2), SYN_REQUIRE, &g_MapTable2);\r
714   g_pParentWnd->GetSynapseClient().AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);\r
715   \r
716   // plugins: load anything that claims to be a plugin\r
717   // minor becomes some kind of matching pattern\r
718   // g_PluginsManager is an API any class, it receives several function tables as needed\r
719   // you can't do a SYN_PROVIDE with that, has to be a SYN_REQUIRE ?\r
720   g_PluginsManager.SetMatchAPI(PLUGIN_MAJOR, "*");\r
721   g_pParentWnd->GetSynapseClient().AddManager(&g_PluginsManager);\r
722   g_pParentWnd->GetSynapseClient().AddManager(&g_ToolbarModuleManager);\r
723   g_pParentWnd->GetSynapseClient().AddManager(&g_ModelManager);\r
724   if (!g_pParentWnd->GetSynapseServer().Resolve(&g_pParentWnd->GetSynapseClient()))\r
725   {\r
726     Error("synapse initialization fail (see console)");\r
727   }\r
728   g_PluginsManager.PopulateMenu();\r
729   g_ToolbarModuleManager.ConstructToolbar();\r
730   InitFileTypes();\r
731 }\r
732 \r
733 void CPlugInManager::Shutdown()\r
734 {\r
735   g_pParentWnd->GetSynapseServer().Shutdown();\r
736 }\r
737 \r
738 void CPlugInManager::Cleanup()\r
739 {\r
740   int i;\r
741 \r
742   for (i = 0; i < m_BrushHandles.GetSize(); i++)\r
743   {\r
744     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));\r
745     Brush_Free(pb);\r
746   }\r
747   m_BrushHandles.RemoveAll();\r
748 \r
749   for (i = 0; i < m_EntityHandles.GetSize(); i++)\r
750   {\r
751     entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));\r
752     Entity_Free(pe);\r
753   }\r
754   m_EntityHandles.RemoveAll();\r
755 \r
756   // patches\r
757   // these are linked into the map\r
758   m_PatchesHandles.RemoveAll();\r
759   // these patches were allocated by Radiant on plugin request\r
760   // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map\r
761   // in which case we are supposed to delete them\r
762   // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been\r
763   // erased and we are trying a second time, therefore crashing ..\r
764   //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches\r
765 #ifdef _DEBUG\r
766   if (m_PluginPatches.GetSize() != 0)\r
767     Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");\r
768 #endif\r
769 \r
770 /*      for (i = 0; i < m_PluginPatches.GetSize(); i++)\r
771   {\r
772     patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));\r
773     if (pMesh->pSymbiot)\r
774       delete pMesh;\r
775   }\r
776   m_PluginPatches.RemoveAll(); */\r
777 }\r
778 \r
779 void CPlugInManager::Dispatch(int n, const char * p)\r
780 {\r
781   g_PluginsManager.Dispatch(n, p);\r
782 }\r
783 \r
784 void WINAPI QERApp_GetDispatchParams(vec3_t vMin, vec3_t vMax, bool *bSingleBrush)\r
785 {\r
786   if (selected_brushes.next == &selected_brushes)\r
787   {\r
788     vMin[0] = vMin[1] = vMin[2] = 0;\r
789     VectorCopy(vMin, vMax);\r
790   } else\r
791   {\r
792     Select_GetBounds (vMin, vMax);\r
793   }\r
794 \r
795   if( bSingleBrush )\r
796     *bSingleBrush = QE_SingleBrush(true);\r
797 }\r
798 \r
799 \r
800 // creates a dummy brush in the active brushes list\r
801 // FIXME : is this one really USED ?\r
802 void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)\r
803 {\r
804 \r
805   brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);\r
806   Entity_LinkBrush (world_entity, pBrush);\r
807   Brush_Build(pBrush);\r
808   Brush_AddToList (pBrush, &active_brushes);\r
809   Select_Brush(pBrush);\r
810   Sys_UpdateWindows(W_ALL);\r
811 }\r
812 \r
813 void* CPlugInManager::CreateBrushHandle()\r
814 {\r
815   brush_t *pb = Brush_Alloc();\r
816   pb->numberId = g_nBrushId++;\r
817   m_BrushHandles.Add(pb);\r
818   return(void*)pb;\r
819 }\r
820 \r
821 void CPlugInManager::DeleteBrushHandle(void * vp)\r
822 {\r
823   CPtrArray* pHandles[3];\r
824   pHandles[0] = &m_SelectedBrushHandles;\r
825   pHandles[1] = &m_ActiveBrushHandles;\r
826   pHandles[2] = &m_BrushHandles;\r
827 \r
828   for (int j = 0; j < 3; j++)\r
829   {\r
830     for (int i = 0; i < pHandles[j]->GetSize(); i++)\r
831     {\r
832       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));\r
833       if (pb == reinterpret_cast<brush_t*>(vp))\r
834       {\r
835         if (j == 2)\r
836         {\r
837           // only remove it from the list if it is work area\r
838           // this allows the selected and active list indexes to remain constant\r
839           // throughout a session (i.e. between an allocate and release)\r
840           pHandles[j]->RemoveAt(i);\r
841         }\r
842         Brush_Free(pb);\r
843         Sys_MarkMapModified();    // PGM\r
844         return;\r
845       }\r
846     }\r
847   }\r
848 }\r
849 \r
850 void CPlugInManager::CommitBrushHandleToMap(void * vp)\r
851 {\r
852   g_bScreenUpdates = false; \r
853   for (int i = 0; i < m_BrushHandles.GetSize(); i++)\r
854   {\r
855     brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));\r
856     if (pb == reinterpret_cast<brush_t*>(vp))\r
857     {\r
858       m_BrushHandles.RemoveAt(i);\r
859       Entity_LinkBrush (world_entity, pb);\r
860       Brush_Build(pb);\r
861       Brush_AddToList (pb, &active_brushes);\r
862       Select_Brush(pb);\r
863     }\r
864   }\r
865   g_bScreenUpdates = true; \r
866   Sys_UpdateWindows(W_ALL);\r
867 }\r
868 \r
869 void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)\r
870 {\r
871   brush_t *bp = FindBrushHandle(vp);\r
872   if (bp != NULL)\r
873   {\r
874     face_t *f = Face_Alloc();\r
875     f->texdef = g_qeglobals.d_texturewin.texdef;\r
876     f->texdef.flags &= ~SURF_KEEP;\r
877     f->texdef.contents &= ~CONTENTS_KEEP;\r
878     f->next = bp->brush_faces;\r
879     bp->brush_faces = f;\r
880     VectorCopy (v1, f->planepts[0]);\r
881     VectorCopy (v2, f->planepts[1]);\r
882     VectorCopy (v3, f->planepts[2]);\r
883   }\r
884 }\r
885 \r
886 brush_t* CPlugInManager::FindBrushHandle(void * vp)\r
887 {\r
888   CPtrArray* pHandles[4];\r
889   pHandles[0] = &m_SelectedBrushHandles;\r
890   pHandles[1] = &m_ActiveBrushHandles;\r
891   pHandles[2] = &m_BrushHandles;\r
892   pHandles[3] = &m_EntityBrushHandles;\r
893 \r
894   for (int j = 0; j < 4; j++)\r
895   {\r
896     for (int i = 0; i < pHandles[j]->GetSize(); i++)\r
897     {\r
898       brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));\r
899       if (pb == reinterpret_cast<brush_t*>(vp))\r
900       {\r
901         return pb;\r
902       }\r
903     }\r
904   }\r
905   return NULL;\r
906 }\r
907 \r
908 patchMesh_t* CPlugInManager::FindPatchHandle(int index)\r
909 {\r
910   switch (PatchesMode)\r
911   {\r
912   case EActivePatches:\r
913   case ESelectedPatches:\r
914     if ( index < m_PatchesHandles.GetSize() )\r
915     {\r
916       brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));\r
917       return pb->pPatch;\r
918     }\r
919 #ifdef _DEBUG\r
920     Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");\r
921 #endif\r
922     break;\r
923   case EAllocatedPatches:\r
924     if ( index < m_PluginPatches.GetSize() )\r
925     {\r
926       patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));\r
927       return pPatch;\r
928     }\r
929 #ifdef _DEBUG\r
930     Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");\r
931 #endif\r
932     break;\r
933   }\r
934   return NULL;\r
935 }\r
936 \r
937 void* WINAPI QERApp_CreateBrushHandle()\r
938 {\r
939   return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();\r
940 }\r
941 \r
942 void WINAPI QERApp_DeleteBrushHandle(void* vp)\r
943 {\r
944   g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);\r
945 }\r
946 \r
947 void WINAPI QERApp_CommitBrushHandleToMap(void* vp)\r
948 {\r
949   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);\r
950 }\r
951 \r
952 void WINAPI QERApp_AddFace(void* vp, vec3_t v1, vec3_t v2, vec3_t v3)\r
953 {\r
954   g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);\r
955 }\r
956 \r
957 void WINAPI QERApp_DeleteSelection()\r
958 {\r
959   Select_Delete();\r
960 }\r
961 \r
962 void QERApp_GetCamera( vec3_t origin, vec3_t angles )\r
963 {\r
964   VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->origin, origin );\r
965   VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->angles, angles );\r
966 }\r
967 \r
968 void QERApp_SetCamera( vec3_t origin, vec3_t angles )\r
969 {\r
970   VectorCopy( origin, g_pParentWnd->GetCamWnd()->Camera()->origin );\r
971   VectorCopy( angles, g_pParentWnd->GetCamWnd()->Camera()->angles );\r
972 \r
973   Sys_UpdateWindows( W_ALL ); // specify \r
974   g_pParentWnd->OnTimer();\r
975 }\r
976 \r
977 void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )\r
978 {\r
979   GtkWidget *widget;\r
980 \r
981   if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)\r
982     widget = g_pParentWnd->GetCamWnd()->m_pParent;\r
983   else\r
984     widget = g_pParentWnd->GetCamWnd()->GetWidget();\r
985 \r
986   get_window_pos (widget, x, y);\r
987 \r
988   *width = g_pParentWnd->GetCamWnd()->Camera()->width;\r
989   *height = g_pParentWnd->GetCamWnd()->Camera()->height;\r
990 }\r
991 \r
992 //FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up\r
993 bool g_bPlugWait = false;\r
994 bool g_bPlugOK = false;\r
995 int  g_nPlugCount = 0;\r
996 \r
997 void _PlugDone(bool b, int n)\r
998 {\r
999   g_bPlugWait = false;\r
1000   g_bPlugOK = b;\r
1001   g_nPlugCount = n;\r
1002 }\r
1003 \r
1004 void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, char* pMsg)\r
1005 {\r
1006   ShowInfoDialog(pMsg);\r
1007   g_bPlugWait = true;\r
1008   g_bPlugOK = false;\r
1009   g_nPlugCount = 0;\r
1010 //  g_nPlugCount=nMax-1;\r
1011   AcquirePath(nMax, &_PlugDone);\r
1012 \r
1013   while (g_bPlugWait)\r
1014     gtk_main_iteration ();\r
1015 \r
1016   HideInfoDialog();\r
1017 \r
1018   pData->m_nCount = 0;\r
1019   pData->m_pVectors = NULL;\r
1020 \r
1021   if (g_bPlugOK && g_nPlugCount > 0)\r
1022   {\r
1023     pData->m_nCount = g_nPlugCount;\r
1024     pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));\r
1025     vec3_t *pOut = pData->m_pVectors;\r
1026     for (int i = 0; i < g_nPlugCount; i++)\r
1027     {\r
1028       memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));\r
1029       pOut++;\r
1030     }\r
1031   }\r
1032 }\r
1033 \r
1034 //#define DBG_PAPI\r
1035 \r
1036 void CheckTexture(face_t *f)\r
1037 {\r
1038   if (!f->d_texture)\r
1039   {\r
1040 #ifdef DBG_PAPI\r
1041     Sys_Printf("CheckTexture: requesting %s\n", f->texdef.name);\r
1042 #endif\r
1043     f->pShader = QERApp_Shader_ForName (f->texdef.GetName());\r
1044     f->pShader->IncRef();\r
1045     f->d_texture = f->pShader->getTexture();\r
1046   }\r
1047 }\r
1048 \r
1049 // expects pData->m_TextureName to be relative to "textures/"\r
1050 void WINAPI QERApp_AddFaceData(void* pv, _QERFaceData *pData)\r
1051 {\r
1052 #ifdef DBG_PAPI\r
1053   Sys_Printf("FindBrushHandle...");\r
1054 #endif\r
1055   brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1056 #ifdef DBG_PAPI\r
1057   Sys_Printf("Done\n");\r
1058 #endif\r
1059   if (pBrush != NULL)\r
1060   {\r
1061     face_t *f = Face_Alloc();\r
1062     f->texdef = g_qeglobals.d_texturewin.texdef;\r
1063     f->texdef.flags = pData->m_nFlags;\r
1064     f->texdef.contents = pData->m_nContents;\r
1065     f->texdef.value = pData->m_nValue;\r
1066     f->texdef.SetName(pData->m_TextureName);\r
1067     f->next = pBrush->brush_faces;\r
1068     pBrush->brush_faces = f;\r
1069     VectorCopy (pData->m_v1, f->planepts[0]);\r
1070     VectorCopy (pData->m_v2, f->planepts[1]);\r
1071     VectorCopy (pData->m_v3, f->planepts[2]);\r
1072     // we might need to convert one way or the other if the input and the brush coordinates setting don't match\r
1073     if (pData->m_bBPrimit == true)\r
1074     {\r
1075       f->brushprimit_texdef = pData->brushprimit_texdef;\r
1076       if (!g_qeglobals.m_bBrushPrimitMode)\r
1077       {\r
1078         // before calling into the conversion, make sure we have a texture!\r
1079         CheckTexture (f);\r
1080 #ifdef DBG_PAPI\r
1081         Sys_Printf("BrushPrimitFaceToFace...");\r
1082 #endif\r
1083 \r
1084         // convert BP to regular\r
1085         BrushPrimitFaceToFace (f);\r
1086 #ifdef DBG_PAPI\r
1087         Sys_Printf("Done\n");\r
1088 #endif\r
1089       }\r
1090     } else\r
1091     {\r
1092 #ifdef _DEBUG\r
1093       if (pData->m_bBPrimit != false)\r
1094         Sys_FPrintf (SYS_WRN, "non-initialized pData->m_bBPrimit in QERApp_AddFaceData\n");\r
1095 #endif\r
1096       f->texdef.rotate = pData->m_fRotate;\r
1097       f->texdef.shift[0] = pData->m_fShift[0];\r
1098       f->texdef.shift[1] = pData->m_fShift[1];\r
1099       f->texdef.scale[0] = pData->m_fScale[0];\r
1100       f->texdef.scale[1] = pData->m_fScale[1];\r
1101       if (g_qeglobals.m_bBrushPrimitMode)\r
1102       {\r
1103         CheckTexture (f);\r
1104 #ifdef DBG_PAPI\r
1105         Sys_Printf("FaceToBrushPrimitFace...");\r
1106 #endif\r
1107 \r
1108         // convert regular to BP\r
1109         FaceToBrushPrimitFace (f);\r
1110 #ifdef DBG_PAPI\r
1111         Sys_Printf("Done\n");\r
1112 #endif\r
1113       }\r
1114     }\r
1115     Sys_MarkMapModified();    // PGM\r
1116   }\r
1117 }\r
1118 \r
1119 int WINAPI QERApp_GetFaceCount(void* pv)\r
1120 {\r
1121   int n = 0;\r
1122   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1123   if (pBrush != NULL)\r
1124   {\r
1125     for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
1126     {\r
1127       n++;\r
1128     }\r
1129   }\r
1130   return n;\r
1131 }\r
1132 \r
1133 _QERFaceData* WINAPI QERApp_GetFaceData(void* pv, int nFaceIndex)\r
1134 {\r
1135   static _QERFaceData face;\r
1136   int n = 0;\r
1137   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1138 \r
1139   if (pBrush != NULL)\r
1140   {\r
1141     for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
1142     {\r
1143 \r
1144 #ifdef _DEBUG\r
1145       if (!pBrush->brush_faces)\r
1146       {\r
1147         Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );\r
1148         return NULL;\r
1149       }\r
1150 #endif\r
1151 \r
1152       if (n == nFaceIndex)\r
1153       {\r
1154         face.m_nContents = f->texdef.contents;\r
1155         face.m_nFlags = f->texdef.flags;\r
1156         face.m_nValue = f->texdef.value;\r
1157         if (g_qeglobals.m_bBrushPrimitMode)\r
1158         {\r
1159           //++timo NOTE: we may want to convert back to old format for backward compatibility with some old plugins?\r
1160           face.m_bBPrimit = true;\r
1161           face.brushprimit_texdef = f->brushprimit_texdef;\r
1162         } else\r
1163         {\r
1164           face.m_fRotate = f->texdef.rotate;\r
1165           face.m_fScale[0] = f->texdef.scale[0];\r
1166           face.m_fScale[1] = f->texdef.scale[1];\r
1167           face.m_fShift[0] = f->texdef.shift[0];\r
1168           face.m_fShift[1] = f->texdef.shift[1];\r
1169         }\r
1170         strcpy(face.m_TextureName, f->texdef.GetName());\r
1171         VectorCopy(f->planepts[0], face.m_v1);\r
1172         VectorCopy(f->planepts[1], face.m_v2);\r
1173         VectorCopy(f->planepts[2], face.m_v3);\r
1174         return &face;\r
1175       }\r
1176       n++;\r
1177     }\r
1178   }\r
1179   return NULL;\r
1180 }\r
1181 \r
1182 void WINAPI QERApp_SetFaceData(void* pv, int nFaceIndex, _QERFaceData *pData)\r
1183 {\r
1184   int n = 0;\r
1185   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1186 \r
1187   if (pBrush != NULL)\r
1188   {\r
1189     for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
1190     {\r
1191       if (n == nFaceIndex)\r
1192       {\r
1193         f->texdef.flags = pData->m_nFlags;\r
1194         f->texdef.contents = pData->m_nContents;\r
1195         f->texdef.value = pData->m_nValue;\r
1196         f->texdef.rotate = pData->m_fRotate;\r
1197         f->texdef.shift[0] = pData->m_fShift[0];\r
1198         f->texdef.shift[1] = pData->m_fShift[1];\r
1199         f->texdef.scale[0] = pData->m_fScale[0];\r
1200         f->texdef.scale[1] = pData->m_fScale[1];\r
1201         //strcpy(f->texdef.name, pData->m_TextureName);\r
1202         f->texdef.SetName(pData->m_TextureName);\r
1203         VectorCopy(pData->m_v1, f->planepts[0]);\r
1204         VectorCopy(pData->m_v2, f->planepts[1]);\r
1205         VectorCopy(pData->m_v3, f->planepts[2]);\r
1206         Sys_MarkMapModified();    // PGM\r
1207         return;           // PGM\r
1208       }\r
1209       n++;\r
1210     }\r
1211   }\r
1212 }\r
1213 \r
1214 void WINAPI QERApp_DeleteFace(void* pv, int nFaceIndex)\r
1215 {\r
1216   int n = 0;\r
1217   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1218   if (pBrush != NULL)\r
1219   {\r
1220     face_t *pPrev = pBrush->brush_faces;\r
1221     for (face_t *f = pBrush->brush_faces; f; f = f->next)\r
1222     {\r
1223       if (n == nFaceIndex)\r
1224       {\r
1225         pPrev->next = f->next;\r
1226         Face_Free (f);\r
1227         Sys_MarkMapModified();    // PGM\r
1228         return;\r
1229       }\r
1230       n++;\r
1231       pPrev = f;\r
1232     }\r
1233   }\r
1234 }\r
1235 \r
1236 //==========\r
1237 //PGM\r
1238 void WINAPI QERApp_BuildBrush (void* pv)\r
1239 {\r
1240   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1241   if (pBrush != NULL)\r
1242   {\r
1243     Brush_Build(pBrush);\r
1244     Sys_UpdateWindows(W_ALL);\r
1245   }\r
1246 }\r
1247 \r
1248 //Timo : another version with bConvert flag\r
1249 //++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush\r
1250 void WINAPI QERApp_BuildBrush2 (void* pv, int bConvert)\r
1251 {\r
1252   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1253   if (pBrush != NULL)\r
1254   {\r
1255     Brush_Build( pBrush, true, true, bConvert );\r
1256     Sys_UpdateWindows(W_ALL);\r
1257   }\r
1258 }\r
1259 \r
1260 void WINAPI QERApp_SelectBrush (void* pv)\r
1261 {\r
1262   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1263   if (pBrush != NULL)\r
1264   {\r
1265     Select_Brush(pBrush, false);\r
1266     Sys_UpdateWindows(W_ALL);\r
1267   }\r
1268 \r
1269 }\r
1270 \r
1271 void WINAPI QERApp_DeselectBrush (void* pv)\r
1272 {\r
1273   // FIXME - implement this!\r
1274 }\r
1275 \r
1276 void WINAPI QERApp_ResetPlugins()\r
1277 {\r
1278   g_pParentWnd->OnPluginsRefresh();\r
1279 }\r
1280 \r
1281 void WINAPI QERApp_DeselectAllBrushes ()\r
1282 {\r
1283   Select_Deselect();\r
1284   Sys_UpdateWindows(W_ALL);\r
1285 }\r
1286 //PGM\r
1287 //==========\r
1288 \r
1289 void WINAPI QERApp_TextureBrush(void* pv, char* pName)\r
1290 {\r
1291   brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);\r
1292   if (pBrush != NULL)\r
1293   {\r
1294     for (face_t *f = pBrush->brush_faces ; f; f = f->next)\r
1295     {\r
1296       //strcpy(f->texdef.name, pName);\r
1297       f->texdef.SetName(pName);\r
1298     }\r
1299     Sys_MarkMapModified();    // PGM\r
1300   }\r
1301 }\r
1302 \r
1303 int WINAPI QERApp_SelectedBrushCount()\r
1304 {\r
1305   int n = 0;\r
1306   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
1307   {\r
1308     n++;\r
1309   }\r
1310   return n;\r
1311 }\r
1312 \r
1313 int WINAPI QERApp_ActiveBrushCount()\r
1314 {\r
1315   int n = 0;\r
1316   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
1317   {\r
1318     n++;\r
1319   }\r
1320   return n;\r
1321 }\r
1322 \r
1323 int WINAPI QERApp_AllocateSelectedBrushHandles()\r
1324 {\r
1325   int n = 0;\r
1326   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
1327   {\r
1328     n++;\r
1329     g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);\r
1330   }\r
1331   return n;\r
1332 }\r
1333 \r
1334 int WINAPI QERApp_AllocateActiveBrushHandles()\r
1335 {\r
1336   int n = 0;\r
1337   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
1338   {\r
1339     n++;\r
1340     g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);\r
1341   }\r
1342   return n;\r
1343 }\r
1344 \r
1345 void WINAPI QERApp_ReleaseSelectedBrushHandles()\r
1346 {\r
1347   g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();\r
1348   Sys_UpdateWindows(W_ALL);\r
1349 }\r
1350 \r
1351 void WINAPI QERApp_ReleaseActiveBrushHandles()\r
1352 {\r
1353   g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();\r
1354   Sys_UpdateWindows(W_ALL);\r
1355 }\r
1356 \r
1357 void* WINAPI QERApp_GetActiveBrushHandle(int nIndex)\r
1358 {\r
1359   if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())\r
1360   {\r
1361     return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));\r
1362   }\r
1363   return NULL;\r
1364 }\r
1365 \r
1366 void* WINAPI QERApp_GetSelectedBrushHandle(int nIndex)\r
1367 {\r
1368   if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())\r
1369   {\r
1370     return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));\r
1371   }\r
1372   return NULL;\r
1373 }\r
1374 \r
1375 int WINAPI QERApp_TextureCount()\r
1376 {\r
1377   //++timo TODO: replace by QERApp_GetActiveShaderCount and verify\r
1378   Texture_StartPos ();\r
1379   int x, y;\r
1380   int n = 0;\r
1381   while (1)\r
1382   {\r
1383     IShader *pShader = Texture_NextPos (&x, &y);\r
1384     if (!pShader)\r
1385       break;\r
1386     n++;\r
1387   }\r
1388   return n;\r
1389 }\r
1390 \r
1391 char* WINAPI QERApp_GetTexture(int nIndex)\r
1392 {\r
1393   //++timo TODO: replace by QERApp_ActiveShader_ForIndex\r
1394   // these funcs would end up being provided for backward compatibility\r
1395   static char name[QER_MAX_NAMELEN];\r
1396   Texture_StartPos ();\r
1397   int x, y;\r
1398   int n = 0;\r
1399   while (1)\r
1400   {\r
1401     IShader *pShader = Texture_NextPos (&x, &y);\r
1402     if (!pShader)\r
1403       break;\r
1404     if (n == nIndex)\r
1405     {\r
1406       strcpy(name, pShader->getName());\r
1407       return name;\r
1408     }\r
1409     n++;\r
1410   }\r
1411   return NULL;\r
1412 }\r
1413 \r
1414 char* WINAPI QERApp_GetCurrentTexture()\r
1415 {\r
1416   static char current_tex[1024];\r
1417   strcpy(current_tex,g_qeglobals.d_texturewin.texdef.GetName());\r
1418   return current_tex;\r
1419 }\r
1420 \r
1421 void WINAPI QERApp_SetCurrentTexture(char* strName)\r
1422 {\r
1423   //++timo hu ?? tex is not initialized ?? can be any value ..\r
1424   texdef_t tex;\r
1425   //++timo added a brushprimit_texdef ..\r
1426   // smthg to be done here\r
1427   brushprimit_texdef_t brushprimit_tex;\r
1428   //strcpy(tex.name, strName);\r
1429   tex.SetName(strName);\r
1430   Texture_SetTexture(&tex,&brushprimit_tex);\r
1431 }\r
1432 \r
1433 int WINAPI QERApp_GetEClassCount()\r
1434 {\r
1435   int n = 0;\r
1436   for (eclass_t *e = eclass ; e ; e = e->next)\r
1437   {\r
1438     n++;\r
1439   }\r
1440   return n;\r
1441 }\r
1442 \r
1443 char* WINAPI QERApp_GetEClass(int nIndex)\r
1444 {\r
1445   int n = 0;\r
1446   for (eclass_t *e = eclass ; e ; e = e->next)\r
1447   {\r
1448     if (n == nIndex)\r
1449     {\r
1450       return e->name;\r
1451     }\r
1452   }\r
1453   return NULL;\r
1454 }\r
1455 \r
1456 // v1.70 code\r
1457 // world_entity holds the worldspawn and is indexed as 0\r
1458 // other entities are in the entities doubly linked list\r
1459 // QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]\r
1460 int WINAPI QERApp_GetEntityCount()\r
1461 {\r
1462   int n = 1;\r
1463   for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)\r
1464   {\r
1465     n++;\r
1466   }\r
1467   return n;\r
1468 }\r
1469 \r
1470 // We don't store entities in CPtrArray, we need to walk the list\r
1471 void* WINAPI QERApp_GetEntityHandle(int nIndex)\r
1472 {\r
1473   if (nIndex==0)\r
1474     // looks for the worldspawn\r
1475     return static_cast<void*>(world_entity);\r
1476   entity_t *pe = &entities;\r
1477   int n = 0;\r
1478   while ( n < nIndex )\r
1479   {\r
1480     pe = pe->next;\r
1481     n++;\r
1482   }\r
1483   return static_cast<void*>(pe);\r
1484 }\r
1485 \r
1486 epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )\r
1487 {\r
1488   epair_t *e = (epair_t*)qmalloc (sizeof(*e));\r
1489   e->key = (char*)qmalloc(strlen(key)+1);\r
1490   strcpy (e->key, key);\r
1491   e->value = (char*)qmalloc(strlen(val)+1);\r
1492   strcpy (e->value, val);\r
1493   return e;\r
1494 }\r
1495 \r
1496 /*\r
1497 IEpair* WINAPI QERApp_IEpairForEntityHandle(void *vp)\r
1498 {\r
1499   entity_t *pe = static_cast<entity_t *>(vp);\r
1500   CEpairsWrapper *pEp = new CEpairsWrapper(pe);\r
1501   pEp->IncRef();\r
1502   return pEp;\r
1503 }\r
1504 \r
1505 IEpair* WINAPI QERApp_IEpairForProjectKeys()    \r
1506 {\r
1507   CEpairsWrapper *pEp = new CEpairsWrapper(g_qeglobals.d_project_entity);\r
1508   pEp->IncRef();\r
1509   return pEp;\r
1510 }\r
1511 */\r
1512 \r
1513 int WINAPI QERApp_AllocateEntityBrushHandles(void* vp)\r
1514 {\r
1515   entity_t *pe = static_cast<entity_t *>(vp);\r
1516   int n = 0;\r
1517   if (!pe->brushes.onext)\r
1518     return 0;\r
1519   g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();\r
1520   for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)\r
1521   {\r
1522     n++;\r
1523     g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);\r
1524   }\r
1525   return n;\r
1526 }\r
1527 \r
1528 void WINAPI QERApp_ReleaseEntityBrushHandles()\r
1529 {\r
1530   g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();\r
1531 }\r
1532 \r
1533 void* WINAPI QERApp_GetEntityBrushHandle(int nIndex)\r
1534 {\r
1535   if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())\r
1536     return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);\r
1537   return NULL;\r
1538 }\r
1539 \r
1540 // FIXME TTimo that entity handles thing sucks .. we should get rid of it ..\r
1541 \r
1542 void* WINAPI QERApp_CreateEntityHandle()\r
1543 {\r
1544   entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));\r
1545   pe->brushes.onext = pe->brushes.oprev = &pe->brushes;\r
1546   g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<void*>(pe));\r
1547   return static_cast<void*>(pe);\r
1548 }\r
1549 \r
1550 // the vpBrush needs to be in m_BrushHandles\r
1551 //++timo we don't have allocation nor storage for vpEntity, no checks for this one\r
1552 void WINAPI QERApp_CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)\r
1553 {\r
1554   g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);\r
1555   return;\r
1556 }\r
1557 \r
1558 const char* QERApp_ReadProjectKey(const char* key)\r
1559 {\r
1560   return ValueForKey(g_qeglobals.d_project_entity, key);\r
1561 }\r
1562 \r
1563 #ifdef USEPLUGINENTITIES\r
1564 \r
1565 int WINAPI QERApp_ScanFileForEClass(char *filename )\r
1566 {\r
1567   // set single class parsing\r
1568   parsing_single = true;\r
1569   Eclass_ScanFile(filename);\r
1570   if (eclass_found)\r
1571   {\r
1572     eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;\r
1573     return 1;\r
1574   }\r
1575   return 0;\r
1576 }\r
1577 #endif // USEPLUGINENTITIES\r
1578 \r
1579 // the vpBrush needs to be in m_BrushHandles\r
1580 //++timo add a debug check to see if we found the brush handle\r
1581 // NOTE : seems there's no way to check vpEntity is valid .. this is dangerous\r
1582 // links the brush to its entity, everything else is done when commiting the entity to the map\r
1583 void CPlugInManager::CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)\r
1584 {\r
1585   brush_t* pb;\r
1586   entity_t* pe;\r
1587   for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)\r
1588   {\r
1589     if (vpBrush == m_BrushHandles.GetAt(i))\r
1590     {\r
1591       m_BrushHandles.RemoveAt(i);\r
1592       pb = reinterpret_cast<brush_t*>(vpBrush);\r
1593       pe = reinterpret_cast<entity_t *>(vpEntity);\r
1594       Entity_LinkBrush (pe, pb);\r
1595     }\r
1596   }\r
1597   Sys_UpdateWindows(W_ALL);\r
1598 }\r
1599 \r
1600 // the vpEntity must be in m_EntityHandles\r
1601 void WINAPI QERApp_CommitEntityHandleToMap(void* vpEntity)\r
1602 {\r
1603   g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);\r
1604   return;\r
1605 }\r
1606 \r
1607 int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )\r
1608 {\r
1609   int nSize = vfsLoadFile(pLocation, buffer, 0);\r
1610   return nSize;\r
1611 }\r
1612 \r
1613 char * WINAPI QERApp_ExpandReletivePath (char *p)\r
1614 {\r
1615   return ExpandReletivePath(p);\r
1616 }\r
1617 \r
1618 qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)\r
1619 {\r
1620   // if the texture is not loaded yet, this call will get it loaded\r
1621   // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_xxxBase GL context\r
1622   // the plugin may set the GL context to whatever he likes, but then load would fail\r
1623   // NOTE: is context switching time-consuming? then maybe the plugin could handle the context\r
1624   // switch and only add a sanity check in debug mode here\r
1625   // read current context\r
1626   gtk_glwidget_make_current (g_qeglobals_gui.d_glBase);\r
1627 \r
1628   //++timo debugging\r
1629   Sys_Printf("WARNING: QERApp_Texture_ForName ... don't call that!!\n");\r
1630   qtexture_t* qtex = QERApp_Texture_ForName2( name );\r
1631   return qtex;\r
1632 }\r
1633 \r
1634 char* QERApp_Token()\r
1635 {\r
1636   return token;\r
1637 }\r
1638 \r
1639 int QERApp_ScriptLine()\r
1640 {\r
1641   return scriptline;\r
1642 }\r
1643 \r
1644 // we save the map and return the name .. either .map or .reg to support region compiling\r
1645 char* QERApp_GetMapName()\r
1646 {\r
1647   static char name[PATH_MAX];\r
1648   SaveWithRegion (name);\r
1649   return name;\r
1650 }\r
1651 \r
1652 void CPlugInManager::CommitEntityHandleToMap(void* vpEntity)\r
1653 {\r
1654   entity_t *pe;\r
1655   eclass_t *e;\r
1656   brush_t   *b;\r
1657   vec3_t mins,maxs;\r
1658   bool has_brushes;\r
1659   for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )\r
1660   {\r
1661     if (vpEntity == m_EntityHandles.GetAt(i))\r
1662     {\r
1663       m_EntityHandles.RemoveAt(i);\r
1664       pe = reinterpret_cast<entity_t*>(vpEntity);\r
1665       // fill additional fields\r
1666       // straight copy from Entity_Parse\r
1667       // entity_t::origin\r
1668       GetVectorForKey (pe, "origin", pe->origin);\r
1669       // entity_t::eclass\r
1670       if (pe->brushes.onext == &pe->brushes)\r
1671         has_brushes = false;\r
1672       else\r
1673         has_brushes = true;\r
1674       e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);\r
1675       pe->eclass = e;\r
1676       // fixedsize\r
1677       if (e->fixedsize)\r
1678       {\r
1679         if (pe->brushes.onext != &pe->brushes)\r
1680         {\r
1681           Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");\r
1682         }\r
1683         // create a custom brush\r
1684         VectorAdd(e->mins, pe->origin, mins);\r
1685         VectorAdd(e->maxs, pe->origin, maxs);\r
1686 /*\r
1687         float a = 0;\r
1688         if (e->nShowFlags & ECLASS_MISCMODEL)\r
1689         {\r
1690           char* p = ValueForKey(pe, "model");\r
1691           if (p != NULL && strlen(p) > 0)\r
1692           {\r
1693             vec3_t vMin, vMax;\r
1694             a = FloatForKey (pe, "angle");\r
1695             if (GetCachedModel(pe, p, vMin, vMax))\r
1696             {\r
1697               // create a custom brush\r
1698               VectorAdd (pe->md3Class->mins, pe->origin, mins);\r
1699               VectorAdd (pe->md3Class->maxs, pe->origin, maxs);\r
1700             }\r
1701           }\r
1702         }\r
1703 */\r
1704         b = Brush_Create (mins, maxs, &e->texdef);\r
1705 /*\r
1706         if (a)\r
1707         {\r
1708           vec3_t vAngle;\r
1709           vAngle[0] = vAngle[1] = 0;\r
1710           vAngle[2] = a;\r
1711           Brush_Rotate(b, vAngle, pe->origin, false);\r
1712         }\r
1713 */\r
1714         b->owner = pe;\r
1715 \r
1716         b->onext = pe->brushes.onext;\r
1717         b->oprev = &pe->brushes;\r
1718         pe->brushes.onext->oprev = b;\r
1719         pe->brushes.onext = b;\r
1720       } else\r
1721       { // brush entity\r
1722         if (pe->brushes.next == &pe->brushes)\r
1723           Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");\r
1724       }\r
1725 \r
1726       // add brushes to the active brushes list\r
1727       // and build them along the way\r
1728       for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)\r
1729       {\r
1730         // convert between old brushes and brush primitive\r
1731         if (g_qeglobals.m_bBrushPrimitMode)\r
1732         {\r
1733           // we only filled the shift scale rot fields, needs conversion\r
1734           Brush_Build( b, true, true, true );\r
1735         } else\r
1736         {\r
1737           // we are using old brushes\r
1738           Brush_Build( b );\r
1739         }\r
1740         b->next = active_brushes.next;\r
1741         active_brushes.next->prev = b;\r
1742         b->prev = &active_brushes;\r
1743         active_brushes.next = b;\r
1744       }\r
1745 \r
1746       // handle worldspawn entities\r
1747       // if worldspawn has no brushes, use the new one\r
1748       if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))\r
1749       {\r
1750         if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )\r
1751         {\r
1752           // worldspawn already has brushes\r
1753           Sys_Printf ("Commiting worldspawn as func_group\n");\r
1754           SetKeyValue(pe, "classname", "func_group");\r
1755           // add the entity to the end of the entity list\r
1756           pe->next = &entities;\r
1757           pe->prev = entities.prev;\r
1758           entities.prev->next = pe;\r
1759           entities.prev = pe;\r
1760           g_qeglobals.d_num_entities++;\r
1761         } else\r
1762         {\r
1763           // there's a worldspawn with no brushes, we assume the map is empty\r
1764           if ( world_entity )\r
1765           {\r
1766             Entity_Free( world_entity );\r
1767             world_entity = pe;\r
1768           } else\r
1769             Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");\r
1770         }\r
1771       } else\r
1772       {\r
1773         // add the entity to the end of the entity list\r
1774         pe->next = &entities;\r
1775         pe->prev = entities.prev;\r
1776         entities.prev->next = pe;\r
1777         entities.prev = pe;\r
1778         g_qeglobals.d_num_entities++;\r
1779       }\r
1780     }\r
1781   }\r
1782 }\r
1783 \r
1784 void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)\r
1785 {\r
1786   g_bScreenUpdates = bScreenUpdates; \r
1787 }\r
1788 \r
1789 texturewin_t* QERApp_QeglobalsTexturewin()\r
1790 {\r
1791   return &g_qeglobals.d_texturewin;\r
1792 }\r
1793 \r
1794 texdef_t* QERApp_QeglobalsSavedinfo_SIInc()\r
1795 {\r
1796   return &g_qeglobals.d_savedinfo.m_SIIncrement;\r
1797 }\r
1798 \r
1799 patchMesh_t* QERApp_GetSelectedPatch( )\r
1800 {\r
1801   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
1802   {\r
1803     if (pb->patchBrush)\r
1804     {\r
1805       return pb->pPatch;\r
1806     }\r
1807   }\r
1808 #ifdef _DEBUG\r
1809   Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");\r
1810 #endif\r
1811   return NULL;\r
1812 }\r
1813 \r
1814 const char* WINAPI QERApp_GetGamePath()\r
1815 {\r
1816   return g_pGameDescription->mEnginePath.GetBuffer();\r
1817 }\r
1818 \r
1819 /*!\r
1820 \todo the name of this API should prolly be changed\r
1821 would also need to prompt g_strAppPath / g_strGameToolsPath independently?\r
1822 */\r
1823 // SPoG\r
1824 // changed g_strGameToolsPath to g_strAppPath\r
1825 const char* WINAPI QERApp_GetQERPath()\r
1826 {\r
1827   return g_strAppPath.GetBuffer();\r
1828 }\r
1829 \r
1830 const char* WINAPI QERApp_GetGameFile()\r
1831 {\r
1832   // FIXME: Arnout: temp solution, need proper 'which game is this' indicator or a different solution for plugins/modules\r
1833   return g_pGameDescription->mGameFile.GetBuffer();\r
1834 }\r
1835 \r
1836 // patches in/out -----------------------------------\r
1837 int WINAPI QERApp_AllocateActivePatchHandles()\r
1838 {\r
1839   return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();\r
1840 }\r
1841 \r
1842 // Grid Size\r
1843 float QERApp_QeglobalsGetGridSize()\r
1844 {\r
1845   return g_qeglobals.d_gridsize;\r
1846 }\r
1847 \r
1848 int CPlugInManager::AllocateActivePatchHandles()\r
1849 {\r
1850   int n = 0;\r
1851   for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)\r
1852   {\r
1853     if (pb->patchBrush)\r
1854     {\r
1855       n++;\r
1856       m_PatchesHandles.Add(pb);\r
1857     }\r
1858   }\r
1859   return n;\r
1860 }\r
1861 \r
1862 int WINAPI QERApp_AllocateSelectedPatchHandles()\r
1863 {\r
1864   return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();\r
1865 }\r
1866 \r
1867 int CPlugInManager::AllocateSelectedPatchHandles()\r
1868 {\r
1869   int n = 0;\r
1870   // change mode\r
1871   PatchesMode = ESelectedPatches;\r
1872   for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)\r
1873   {\r
1874     if (pb->patchBrush)\r
1875     {\r
1876       n++;\r
1877       m_PatchesHandles.Add(pb);\r
1878     }\r
1879   }\r
1880   return n;\r
1881 }\r
1882 \r
1883 void WINAPI QERApp_ReleasePatchHandles()\r
1884 {\r
1885   g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();\r
1886 }\r
1887 \r
1888 patchMesh_t* WINAPI QERApp_GetPatchData(int index)\r
1889 {\r
1890   static patchMesh_t patch;\r
1891   patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
1892   if (pPatch)\r
1893   {\r
1894     memcpy( &patch, pPatch, sizeof(patchMesh_t) );\r
1895     return &patch;\r
1896   }\r
1897   return NULL;\r
1898 }\r
1899 \r
1900 patchMesh_t* WINAPI QERApp_GetPatchHandle(int index)\r
1901 {\r
1902   return g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
1903 }\r
1904 \r
1905 void WINAPI QERApp_DeletePatch(int index)\r
1906 {\r
1907   patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);\r
1908   if (pPatch)\r
1909   {\r
1910     brush_t *pb = pPatch->pSymbiot;\r
1911     Patch_Delete( pPatch );\r
1912     if (pb)\r
1913       Brush_Free( pb );\r
1914   }\r
1915 #ifdef _DEBUG\r
1916   Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");\r
1917 #endif\r
1918 }\r
1919 \r
1920 int WINAPI QERApp_CreatePatchHandle()\r
1921 {\r
1922   return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();\r
1923 }\r
1924 \r
1925 int CPlugInManager::CreatePatchHandle()\r
1926 {\r
1927   // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure\r
1928   patchMesh_t *pPatch = MakeNewPatch();\r
1929   m_PluginPatches.Add( pPatch );\r
1930   // change mode\r
1931   PatchesMode = EAllocatedPatches;\r
1932   return m_PluginPatches.GetSize()-1;\r
1933 }\r
1934 \r
1935 void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)\r
1936 {\r
1937 #ifdef DBG_PAPI\r
1938   Sys_Printf ("QERApp_CommitPatchHandleToMap %i..", index);\r
1939 #endif\r
1940   g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);\r
1941 #ifdef DBG_PAPI\r
1942   Sys_Printf ("Done\n");\r
1943 #endif\r
1944 }\r
1945 \r
1946 void WINAPI QERApp_CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void* vpEntity)\r
1947 {\r
1948 #ifdef DBG_PAPI\r
1949   Sys_Printf ("QERApp_CommitPatchHandleToEntity %i..", index);\r
1950 #endif\r
1951   g_pParentWnd->GetPlugInMgr().CommitPatchHandleToEntity(index, pMesh, texName, vpEntity);\r
1952 #ifdef DBG_PAPI\r
1953   Sys_Printf ("Done\n");\r
1954 #endif\r
1955 }\r
1956 \r
1957 void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)\r
1958 {\r
1959   if (PatchesMode==EAllocatedPatches)\r
1960   {\r
1961     patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );\r
1962     memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );\r
1963     // patch texturing, if none given use current texture\r
1964     if (texName)\r
1965       pPatch->pShader = QERApp_Shader_ForName (texName);\r
1966     else\r
1967       pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());\r
1968     pPatch->d_texture = pPatch->pShader->getTexture();\r
1969     pPatch->pShader->IncRef();\r
1970     g_bScreenUpdates = false;\r
1971     // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build\r
1972     brush_t *pb = AddBrushForPatch( pPatch, true );\r
1973     Select_Brush( pb );\r
1974     g_bScreenUpdates = true;\r
1975     Sys_UpdateWindows(W_ALL);\r
1976   } else\r
1977   {\r
1978     brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );\r
1979     patchMesh_t *pPatch = pBrush->pPatch;\r
1980     pPatch->width = pMesh->width;\r
1981     pPatch->height = pMesh->height;\r
1982     pPatch->contents = pMesh->contents;\r
1983     pPatch->flags = pMesh->flags;\r
1984     pPatch->value = pMesh->value;\r
1985     pPatch->type = pMesh->type;\r
1986     memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );\r
1987     pPatch->bDirty = true;\r
1988   }\r
1989 }\r
1990 \r
1991 void CPlugInManager::CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity)\r
1992 {\r
1993   entity_t* pe = reinterpret_cast<entity_t *>(vpEntity);\r
1994 \r
1995   if (PatchesMode==EAllocatedPatches)\r
1996   {\r
1997     patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );\r
1998     memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );\r
1999     // patch texturing, if none given use current texture\r
2000     if (texName)\r
2001       pPatch->pShader = QERApp_Shader_ForName (texName);\r
2002     else\r
2003       pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());\r
2004     pPatch->d_texture = pPatch->pShader->getTexture();\r
2005     pPatch->pShader->IncRef();\r
2006     g_bScreenUpdates = false;\r
2007     brush_t *pb = AddBrushForPatch( pPatch, false );  // false, sp have to do the brush building/entity linking ourself\r
2008     Brush_AddToList (pb, &active_brushes);\r
2009     Entity_LinkBrush (pe, pb);\r
2010     Brush_Build( pb );\r
2011     g_bScreenUpdates = true;\r
2012     Sys_UpdateWindows(W_ALL);\r
2013   } else\r
2014   {\r
2015     brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );\r
2016     patchMesh_t *pPatch = pBrush->pPatch;\r
2017     pPatch->width = pMesh->width;\r
2018     pPatch->height = pMesh->height;\r
2019     pPatch->contents = pMesh->contents;\r
2020     pPatch->flags = pMesh->flags;\r
2021     pPatch->value = pMesh->value;\r
2022     pPatch->type = pMesh->type;\r
2023     memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );\r
2024     pPatch->bDirty = true;\r
2025   }\r
2026 }\r
2027 \r
2028 #if 0\r
2029 \r
2030 #if defined (__linux__) || defined (__APPLE__)\r
2031   #include <gdk/gdkx.h>\r
2032 \r
2033 XVisualInfo* QEX_ChooseVisual (bool zbuffer)\r
2034 {\r
2035   int attrlist_z[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0};\r
2036   int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0};\r
2037   XVisualInfo *vi;\r
2038   Display *dpy;\r
2039 \r
2040   dpy = GDK_DISPLAY();\r
2041   if (dpy == NULL)\r
2042     Error ("OpenGL fatal error: Cannot get display.\n");\r
2043   vi = qglXChooseVisual(dpy, DefaultScreen(dpy), zbuffer ? attrlist_z : attrlist);\r
2044   if (vi == NULL)\r
2045     Error ("OpenGL fatal error: glXChooseVisual failed.\n");\r
2046 \r
2047   return vi;\r
2048 }\r
2049 #endif\r
2050 \r
2051 #endif\r
2052 \r
2053 /*!\r
2054 \todo FIXME TTimo broken most likely\r
2055 actually .. that's not enough, you have to go down for the game pack specific?\r
2056 */\r
2057 const char* WINAPI QERApp_ProfileGetDirectory ()\r
2058 {\r
2059   return g_strTempPath;\r
2060 }\r
2061 \r
2062 GtkWidget* WINAPI QERApp_GetQeGlobalsGLWidget ()\r
2063 {\r
2064   return g_qeglobals_gui.d_glBase;\r
2065 }\r
2066 \r
2067 qboolean WINAPI BrushPrimitMode ()\r
2068 {\r
2069   return g_qeglobals.m_bBrushPrimitMode;\r
2070 }\r
2071 \r
2072 brush_t* WINAPI QERApp_ActiveBrushes()\r
2073 {\r
2074   return &active_brushes;\r
2075 }\r
2076 \r
2077 brush_t* WINAPI QERApp_SelectedBrushes()\r
2078 {\r
2079   return &selected_brushes;\r
2080 }\r
2081 \r
2082 brush_t* WINAPI QERApp_FilteredBrushes()\r
2083 {\r
2084   return &filtered_brushes;\r
2085 }\r
2086 \r
2087 CPtrArray* WINAPI QERApp_LstSkinCache()\r
2088 {\r
2089   return &g_lstSkinCache;\r
2090 }\r
2091 \r
2092 qtexture_t** WINAPI QERApp_QTextures()\r
2093 {\r
2094   return &g_qeglobals.d_qtextures;\r
2095 }\r
2096 \r
2097 GHashTable* WINAPI QERApp_QTexmap()\r
2098 {\r
2099   return g_qeglobals.d_qtexmap;\r
2100 }\r
2101 \r
2102 // a simplified version of Texture_SetTexture\r
2103 void WINAPI QERApp_Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef)\r
2104 {\r
2105   Texture_SetTexture (texdef, brushprimit_texdef);\r
2106 }\r
2107 \r
2108 void QERApp_LoadImage (const char *name, unsigned char **pic, int *width, int *height)\r
2109 {\r
2110   g_ImageManager.LoadImage(name, pic, width, height);\r
2111 }\r
2112 \r
2113 unsigned long QERApp_GetTickCount()\r
2114 {\r
2115 #ifdef _WIN32\r
2116         return GetTickCount();\r
2117 #else\r
2118   struct timeval      tp;\r
2119   struct timezone     tzp;\r
2120   static int          basetime=0;\r
2121 \r
2122   gettimeofday(&tp, &tzp);\r
2123   if (!basetime)\r
2124     basetime = tp.tv_sec;\r
2125   return (tp.tv_sec-basetime) + tp.tv_usec/1000;        \r
2126 #endif\r
2127 }\r
2128 \r
2129 bool CSynapseClientRadiant::RequestAPI(APIDescriptor_t *pAPI)\r
2130 {\r
2131   if (!strcmp(pAPI->major_name, RADIANT_MAJOR))\r
2132   {\r
2133     _QERFuncTable_1* pTable= static_cast<_QERFuncTable_1*>(pAPI->mpTable);\r
2134     pTable->m_pfnCreateBrush = &QERApp_CreateBrush;\r
2135     pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;\r
2136     pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;\r
2137     pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;\r
2138     pTable->m_pfnAddFace = &QERApp_AddFace;\r
2139     pTable->m_pfnAddFaceData = &QERApp_AddFaceData;\r
2140     pTable->m_pfnGetFaceData = &QERApp_GetFaceData;\r
2141     pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;\r
2142     pTable->m_pfnSetFaceData = &QERApp_SetFaceData;\r
2143     pTable->m_pfnDeleteFace = &QERApp_DeleteFace;\r
2144     pTable->m_pfnTextureBrush = &QERApp_TextureBrush;\r
2145     pTable->m_pfnBuildBrush = &QERApp_BuildBrush;           // PGM\r
2146     pTable->m_pfnSelectBrush = &QERApp_SelectBrush;         // PGM\r
2147     pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush;       // PGM\r
2148     pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes;   // PGM\r
2149     pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;\r
2150     pTable->m_pfnGetPoints = &QERApp_GetPoints;\r
2151     pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;\r
2152     pTable->m_pfnAllocateSelectedBrushHandles  = &QERApp_AllocateSelectedBrushHandles;\r
2153     pTable->m_pfnReleaseSelectedBrushHandles  = &QERApp_ReleaseSelectedBrushHandles;\r
2154     pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;\r
2155     pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;\r
2156     pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;\r
2157     pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;\r
2158     pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;\r
2159     pTable->m_pfnTextureCount = &QERApp_TextureCount;\r
2160     pTable->m_pfnGetTexture = &QERApp_GetTexture;\r
2161     pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;\r
2162     pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;\r
2163     pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;\r
2164     pTable->m_pfnGetEClass = &QERApp_GetEClass;\r
2165     pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;\r
2166     pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;\r
2167     pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;\r
2168     pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;\r
2169     pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;\r
2170     pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;\r
2171     pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;\r
2172     pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;\r
2173     pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;\r
2174     pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;\r
2175     pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;\r
2176     pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;\r
2177     pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;\r
2178         pTable->m_pfnGetDispatchParams = &QERApp_GetDispatchParams;\r
2179 //    pTable->m_pfnRequestInterface = &QERApp_RequestInterface;\r
2180     pTable->m_pfnError = &Error;\r
2181     pTable->m_pfnLoadFile = &QERApp_LoadFile;\r
2182     pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;\r
2183     pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;\r
2184     pTable->m_pfnHasShader = QERApp_HasShader;\r
2185     pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;\r
2186     pTable->m_pfnGetGamePath = &QERApp_GetGamePath;\r
2187     pTable->m_pfnGetQERPath = &QERApp_GetQERPath;\r
2188     pTable->m_pfnGetGameFile = &QERApp_GetGameFile;\r
2189     pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;\r
2190     pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;\r
2191     pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;\r
2192     pTable->m_pfnGetPatchData = &QERApp_GetPatchData;\r
2193     pTable->m_pfnGetPatchHandle = &QERApp_GetPatchHandle;\r
2194     pTable->m_pfnDeletePatch = &QERApp_DeletePatch;\r
2195     pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;\r
2196     pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;\r
2197     pTable->m_pfnLoadImage = &QERApp_LoadImage;\r
2198     pTable->m_pfnMessageBox = &gtk_MessageBox;\r
2199     pTable->m_pfnFileDialog = &file_dialog;\r
2200     pTable->m_pfnColorDialog = &color_dialog;\r
2201     pTable->m_pfnDirDialog = &dir_dialog;\r
2202     pTable->m_pfnLoadBitmap = &load_plugin_bitmap;\r
2203     pTable->m_pfnProfileGetDirectory = &QERApp_ProfileGetDirectory;\r
2204     pTable->m_pfnProfileSaveInt = &profile_save_int;\r
2205     pTable->m_pfnProfileSaveString = &profile_save_string;\r
2206     pTable->m_pfnProfileLoadInt = &profile_load_int;\r
2207     pTable->m_pfnProfileLoadString = &profile_load_string;\r
2208     pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;\r
2209     pTable->m_pfnSysPrintf = &Sys_Printf;\r
2210     pTable->m_pfnSysFPrintf = &Sys_FPrintf;\r
2211     pTable->m_pfnSysBeginWait = &Sys_BeginWait;\r
2212     pTable->m_pfnSysEndWait = &Sys_EndWait;\r
2213     pTable->m_pfnSys_SetTitle = &Sys_SetTitle;\r
2214     pTable->m_pfnSysBeep = &Sys_Beep;\r
2215     pTable->m_pfnSys_Status = &Sys_Status;\r
2216     pTable->m_pfnMapFree = &Map_Free;\r
2217     pTable->m_pfnMapNew = &Map_New;\r
2218     pTable->m_pfnMapBuildBrushData = &Map_BuildBrushData;\r
2219     pTable->m_pfnMap_IsBrushFiltered = &Map_IsBrushFiltered;\r
2220     pTable->m_pfnMapStartPosition = &Map_StartPosition;\r
2221     pTable->m_pfnMapRegionOff = &Map_RegionOff;\r
2222     pTable->m_pfnSetBuildWindingsNoTexBuild = &Brush_SetBuildWindingsNoTexBuild;\r
2223     pTable->m_pfnPointFileClear = &Pointfile_Clear;\r
2224     pTable->m_pfnCSG_MakeHollow = &CSG_MakeHollow;\r
2225     pTable->m_pfnRegionSpawnPoint = &Region_SpawnPoint;\r
2226     pTable->m_pfnQGetTickCount = &QERApp_GetTickCount;\r
2227     pTable->m_pfnGetModelCache = &GetModelCache;\r
2228     pTable->m_pfnGetFileTypeRegistry = &GetFileTypeRegistry;\r
2229     pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;\r
2230     pTable->m_pfnGetMapName = &QERApp_GetMapName;\r
2231 \r
2232     return true;\r
2233   }\r
2234   if (!strcmp(pAPI->major_name, SCRIPLIB_MAJOR))\r
2235   {\r
2236     _QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pAPI->mpTable);\r
2237     pScripLibTable->m_pfnGetToken = &GetToken;\r
2238     pScripLibTable->m_pfnGetTokenExtra = &GetTokenExtra;\r
2239     pScripLibTable->m_pfnToken = &QERApp_Token;\r
2240     pScripLibTable->m_pfnUnGetToken = &UngetToken;\r
2241     pScripLibTable->m_pfnStartTokenParsing = &StartTokenParsing;\r
2242     pScripLibTable->m_pfnScriptLine = &QERApp_ScriptLine;\r
2243     pScripLibTable->m_pfnTokenAvailable = &TokenAvailable;\r
2244     pScripLibTable->m_pfnCOM_Parse = &COM_Parse;\r
2245     pScripLibTable->m_pfnGet_COM_Token = &Get_COM_Token;\r
2246 \r
2247     return true;\r
2248   }\r
2249   if (!strcmp(pAPI->major_name, BRUSH_MAJOR))\r
2250   {\r
2251     _QERBrushTable *pBrushTable = static_cast<_QERBrushTable *>(pAPI->mpTable);\r
2252     pBrushTable->m_pfnBP_MessageBox = &BP_MessageBox;\r
2253     pBrushTable->m_pfnBrush_AddToList = &Brush_AddToList;\r
2254     pBrushTable->m_pfnBrush_Build = &Brush_Build;\r
2255     pBrushTable->m_pfnBrush_Create = &Brush_Create;\r
2256     pBrushTable->m_pfnBrush_Free = &Brush_Free;\r
2257     pBrushTable->m_pfnBrush_Rotate = &Brush_Rotate;\r
2258     pBrushTable->m_pfnBrushAlloc = &Brush_Alloc;\r
2259     pBrushTable->m_pfnFace_Alloc = &Face_Alloc;\r
2260     pBrushTable->m_pfnHasModel = NULL;// &HasModel;\r
2261 \r
2262     return true;\r
2263   }\r
2264   if (!strcmp(pAPI->major_name, APPSHADERS_MAJOR))\r
2265   {\r
2266     _QERAppShadersTable *pShadersTable = static_cast<_QERAppShadersTable*>(pAPI->mpTable);\r
2267     pShadersTable->m_pfnQTextures = QERApp_QTextures;\r
2268     pShadersTable->m_pfnQTexmap = QERApp_QTexmap;\r
2269     pShadersTable->m_pfnQeglobalsTexturewin = QERApp_QeglobalsTexturewin;\r
2270     pShadersTable->m_pfnTexture_SetTexture = QERApp_Texture_SetTexture;\r
2271     pShadersTable->m_pfnTexture_ShowInuse = Texture_ShowInuse;\r
2272     pShadersTable->m_pfnBuildShaderList = &BuildShaderList;\r
2273     pShadersTable->m_pfnPreloadShaders = &PreloadShaders;\r
2274     \r
2275     return true;\r
2276   }\r
2277   if (!strcmp(pAPI->major_name, QGL_MAJOR))\r
2278   {\r
2279     _QERQglTable *pQglTable = static_cast<_QERQglTable *>(pAPI->mpTable);\r
2280     pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;\r
2281     pQglTable->m_pfn_qglBegin = qglBegin;\r
2282     pQglTable->m_pfn_qglBindTexture = qglBindTexture;\r
2283     pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;\r
2284     pQglTable->m_pfn_qglCallList = qglCallList;\r
2285     pQglTable->m_pfn_qglCallLists = qglCallLists;\r
2286     pQglTable->m_pfn_qglClear = qglClear;\r
2287     pQglTable->m_pfn_qglClearColor = qglClearColor;\r
2288     pQglTable->m_pfn_qglClearDepth = qglClearDepth;\r
2289     pQglTable->m_pfn_qglColor3f = qglColor3f;\r
2290     pQglTable->m_pfn_qglColor3fv = qglColor3fv;\r
2291     pQglTable->m_pfn_qglColor4f = qglColor4f;\r
2292     pQglTable->m_pfn_qglColor4fv = qglColor4fv;\r
2293         pQglTable->m_pfn_qglColor4ubv = qglColor4ubv;\r
2294     pQglTable->m_pfn_qglColorPointer = qglColorPointer;\r
2295     pQglTable->m_pfn_qglCullFace = qglCullFace;\r
2296     pQglTable->m_pfn_qglDepthFunc = qglDepthFunc;\r
2297     pQglTable->m_pfn_qglDepthMask = qglDepthMask;\r
2298     pQglTable->m_pfn_qglDisable = qglDisable;\r
2299     pQglTable->m_pfn_qglDisableClientState = qglDisableClientState;\r
2300     pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;\r
2301     pQglTable->m_pfn_qglDeleteTextures = qglDeleteTextures;\r
2302     pQglTable->m_pfn_qglDrawElements = qglDrawElements;\r
2303     pQglTable->m_pfn_qglEnable = qglEnable;\r
2304     pQglTable->m_pfn_qglEnableClientState = qglEnableClientState;       \r
2305     pQglTable->m_pfn_qglEnd = qglEnd;\r
2306     pQglTable->m_pfn_qglEndList = qglEndList;\r
2307     pQglTable->m_pfn_qglFogf = qglFogf;\r
2308     pQglTable->m_pfn_qglFogfv = qglFogfv;\r
2309     pQglTable->m_pfn_qglFogi = qglFogi;\r
2310     pQglTable->m_pfn_qglGenLists = qglGenLists;\r
2311     pQglTable->m_pfn_qglGenTextures = qglGenTextures;\r
2312     pQglTable->m_pfn_qglGetDoublev = qglGetDoublev;\r
2313     pQglTable->m_pfn_qglGetIntegerv = qglGetIntegerv;\r
2314     pQglTable->m_pfn_qglHint = qglHint;\r
2315     pQglTable->m_pfn_qglLightfv = qglLightfv;\r
2316     pQglTable->m_pfn_qglLineStipple = qglLineStipple;\r
2317     pQglTable->m_pfn_qglLineWidth = qglLineWidth;\r
2318     pQglTable->m_pfn_qglListBase = qglListBase;\r
2319     pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;\r
2320     pQglTable->m_pfn_qglMaterialf = qglMaterialf;\r
2321     pQglTable->m_pfn_qglMaterialfv = qglMaterialfv;\r
2322     pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;\r
2323     pQglTable->m_pfn_qglMultMatrixf = qglMultMatrixf;\r
2324     pQglTable->m_pfn_qglNewList = qglNewList;\r
2325     pQglTable->m_pfn_qglNormal3f = qglNormal3f;\r
2326     pQglTable->m_pfn_qglNormal3fv = qglNormal3fv;\r
2327     pQglTable->m_pfn_qglNormalPointer = qglNormalPointer;\r
2328     pQglTable->m_pfn_qglOrtho = qglOrtho;\r
2329     pQglTable->m_pfn_qglPointSize = qglPointSize;\r
2330     pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;\r
2331     pQglTable->m_pfn_qglPopAttrib = qglPopAttrib;\r
2332     pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;\r
2333     pQglTable->m_pfn_qglPushAttrib = qglPushAttrib;\r
2334     pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;\r
2335     pQglTable->m_pfn_qglRasterPos3fv = qglRasterPos3fv;\r
2336     pQglTable->m_pfn_qglRotated = qglRotated;\r
2337     pQglTable->m_pfn_qglRotatef = qglRotatef;\r
2338     pQglTable->m_pfn_qglScalef = qglScalef;\r
2339     pQglTable->m_pfn_qglScissor = qglScissor;\r
2340     pQglTable->m_pfn_qglShadeModel = qglShadeModel;\r
2341     pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;\r
2342     pQglTable->m_pfn_qglTexCoord2fv = qglTexCoord2fv;\r
2343     pQglTable->m_pfn_qglTexCoordPointer = qglTexCoordPointer;\r
2344     pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;\r
2345     pQglTable->m_pfn_qglTexGenf = qglTexGenf;\r
2346     pQglTable->m_pfn_qglTexImage1D = qglTexImage1D;\r
2347     pQglTable->m_pfn_qglTexImage2D = qglTexImage2D;\r
2348     pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;\r
2349     pQglTable->m_pfn_qglTexParameterfv = qglTexParameterfv;\r
2350     pQglTable->m_pfn_qglTexParameteri = qglTexParameteri;\r
2351     pQglTable->m_pfn_qglTexParameteriv = qglTexParameteriv;\r
2352     pQglTable->m_pfn_qglTexSubImage1D = qglTexSubImage1D;\r
2353     pQglTable->m_pfn_qglTexSubImage2D = qglTexSubImage2D;\r
2354     pQglTable->m_pfn_qglTranslated = qglTranslated;\r
2355     pQglTable->m_pfn_qglTranslatef = qglTranslatef;\r
2356     pQglTable->m_pfn_qglVertex2f = qglVertex2f;\r
2357     pQglTable->m_pfn_qglVertex3f = qglVertex3f;\r
2358     pQglTable->m_pfn_qglVertex3fv = qglVertex3fv;\r
2359     pQglTable->m_pfn_qglVertexPointer = qglVertexPointer;\r
2360     pQglTable->m_pfn_qglViewport = qglViewport;\r
2361 \r
2362     pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;\r
2363 \r
2364     pQglTable->m_pfn_qgluPerspective = qgluPerspective;\r
2365     pQglTable->m_pfn_qgluLookAt = qgluLookAt;\r
2366     pQglTable->m_pfnHookGL2DWindow = QERApp_HookGL2DWindow;\r
2367     pQglTable->m_pfnUnHookGL2DWindow = QERApp_UnHookGL2DWindow;\r
2368     pQglTable->m_pfnHookGL3DWindow = QERApp_HookGL3DWindow;\r
2369     pQglTable->m_pfnUnHookGL3DWindow = QERApp_UnHookGL3DWindow;\r
2370 \r
2371     return true;\r
2372   }\r
2373   if (!strcmp(pAPI->major_name, DATA_MAJOR))\r
2374   {\r
2375     _QERAppDataTable *pDataTable = static_cast<_QERAppDataTable *>(pAPI->mpTable);\r
2376     pDataTable->m_pfnActiveBrushes = QERApp_ActiveBrushes;\r
2377     pDataTable->m_pfnSelectedBrushes = QERApp_SelectedBrushes;\r
2378     pDataTable->m_pfnFilteredBrushes = QERApp_FilteredBrushes;\r
2379     pDataTable->m_pfnLstSkinCache = QERApp_LstSkinCache;\r
2380     \r
2381     return true;\r
2382   }\r
2383   if (!strcmp(pAPI->major_name, PATCH_MAJOR))\r
2384   {\r
2385     _QERPatchTable *pPatchTable = static_cast<_QERPatchTable *>(pAPI->mpTable);\r
2386     pPatchTable->m_pfnPatch_Alloc = &Patch_Alloc;\r
2387     pPatchTable->m_pfnAddBrushForPatch = &AddBrushForPatch;\r
2388     pPatchTable->m_pfnMakeNewPatch = &MakeNewPatch;\r
2389   \r
2390     return true;\r
2391   }\r
2392   if (!strcmp(pAPI->major_name, ECLASSMANAGER_MAJOR))\r
2393   {\r
2394     _EClassManagerTable *pEClassManTable = static_cast<_EClassManagerTable *>(pAPI->mpTable);\r
2395     \r
2396     pEClassManTable->m_pfnEclass_InsertAlphabetized = &Eclass_InsertAlphabetized;\r
2397     pEClassManTable->m_pfnGet_Eclass_E = &Get_EClass_E;\r
2398     pEClassManTable->m_pfnSet_Eclass_Found = &Set_Eclass_Found;\r
2399     pEClassManTable->m_pfnGet_Parsing_Single = &Get_Parsing_Single;\r
2400     pEClassManTable->m_pfnEClass_Create = &EClass_Create;\r
2401     pEClassManTable->m_pfnEclass_ForName = &Eclass_ForName;\r
2402   \r
2403     return true;\r
2404   }\r
2405   if (!strcmp(pAPI->major_name, SELECTEDFACE_MAJOR))\r
2406   { \r
2407     _QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pAPI->mpTable);\r
2408 \r
2409     pSelectedFaceTable->m_pfnGetSelectedFaceCount = &QERApp_GetSelectedFaceCount;\r
2410     pSelectedFaceTable->m_pfnGetFaceBrush = &QERApp_GetSelectedFaceBrush;\r
2411     pSelectedFaceTable->m_pfnGetFace = &QERApp_GetSelectedFace;\r
2412     pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;\r
2413     pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;\r
2414     pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;\r
2415     pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;\r
2416     pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;\r
2417     return true;\r
2418   }\r
2419   if (!strcmp(pAPI->major_name, APPSURFACEDIALOG_MAJOR))\r
2420   {\r
2421     _QERAppSurfaceTable *pSurfDialogTable = static_cast<_QERAppSurfaceTable *>(pAPI->mpTable);\r
2422     pSurfDialogTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;\r
2423     pSurfDialogTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;\r
2424     pSurfDialogTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;\r
2425     pSurfDialogTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;\r
2426     pSurfDialogTable->m_pfnTexMatToFakeTexCoords = &TexMatToFakeTexCoords;\r
2427     pSurfDialogTable->m_pfnConvertTexMatWithQTexture = &ConvertTexMatWithQTexture;\r
2428     pSurfDialogTable->m_pfnFakeTexCoordsToTexMat = &FakeTexCoordsToTexMat;\r
2429     pSurfDialogTable->m_pfnPatch_ResetTexturing = &Patch_ResetTexturing;\r
2430     pSurfDialogTable->m_pfnPatch_FitTexturing = &Patch_FitTexturing;\r
2431     pSurfDialogTable->m_pfnPatch_NaturalizeSelected = &Patch_NaturalizeSelected;\r
2432     pSurfDialogTable->m_pfnPatch_GetTextureName = &Patch_GetTextureName;\r
2433     pSurfDialogTable->m_pfnQE_SingleBrush = &QE_SingleBrush;\r
2434     pSurfDialogTable->m_pfnIsBrushPrimitMode = &IsBrushPrimitMode;\r
2435     pSurfDialogTable->m_pfnComputeAxisBase = &ComputeAxisBase;\r
2436     pSurfDialogTable->m_pfnBPMatMul = &BPMatMul;\r
2437     pSurfDialogTable->m_pfnEmitBrushPrimitTextureCoordinates = &EmitBrushPrimitTextureCoordinates;\r
2438     pSurfDialogTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;\r
2439     pSurfDialogTable->m_pfnSelect_FitTexture = &Select_FitTexture;\r
2440     pSurfDialogTable->m_pfnQERApp_QeglobalsSavedinfo_SIInc = &QERApp_QeglobalsSavedinfo_SIInc;\r
2441     pSurfDialogTable->m_pfnQeglobalsGetGridSize = &QERApp_QeglobalsGetGridSize;\r
2442     pSurfDialogTable->m_pfnFaceList_FitTexture = &SI_FaceList_FitTexture;\r
2443     pSurfDialogTable->m_pfnGetMainWindow = &SI_GetMainWindow;\r
2444     pSurfDialogTable->m_pfnSetWinPos_From_Prefs = &SI_SetWinPos_from_Prefs;\r
2445     pSurfDialogTable->m_pfnGetSelectedFaceCountfromBrushes = &SI_GetSelectedFaceCountfromBrushes;\r
2446     pSurfDialogTable->m_pfnGetSelFacesTexdef = &SI_GetSelFacesTexdef;\r
2447     pSurfDialogTable->m_pfnSetTexdef_FaceList = &SI_SetTexdef_FaceList;\r
2448 \r
2449     return true;\r
2450   }\r
2451   if (!strcmp(pAPI->major_name, UNDO_MAJOR))\r
2452   { \r
2453     _QERUndoTable *pUndoTable = static_cast<_QERUndoTable *>(pAPI->mpTable);\r
2454 \r
2455     pUndoTable->m_pfnUndo_Start = &Undo_Start;\r
2456     pUndoTable->m_pfnUndo_End = &Undo_End;\r
2457     pUndoTable->m_pfnUndo_AddBrush = &Undo_AddBrush;\r
2458     pUndoTable->m_pfnUndo_EndBrush = &Undo_EndBrush;\r
2459     pUndoTable->m_pfnUndo_AddBrushList = &Undo_AddBrushList;\r
2460     pUndoTable->m_pfnUndo_EndBrushList = &Undo_EndBrushList;\r
2461     pUndoTable->m_pfnUndo_AddEntity = &Undo_AddEntity;\r
2462     pUndoTable->m_pfnUndo_EndEntity = &Undo_EndEntity;\r
2463     pUndoTable->m_pfnUndo_Undo = &Undo_Undo;                     // Nurail\r
2464     pUndoTable->m_pfnUndo_Redo = &Undo_Redo;                     // Nurail\r
2465     pUndoTable->m_pfnUndo_GetUndoId = &Undo_GetUndoId;           // Nurail\r
2466     pUndoTable->m_pfnUndo_UndoAvailable = &Undo_UndoAvailable;   // Nurail\r
2467     pUndoTable->m_pfnUndo_RedoAvailable = &Undo_RedoAvailable;   // Nurail\r
2468 \r
2469     return true;\r
2470   }\r
2471   if (!strcmp(pAPI->major_name, CAMERA_MAJOR))\r
2472   {\r
2473     _QERCameraTable *pCameraTable = static_cast<_QERCameraTable *>(pAPI->mpTable);\r
2474 \r
2475     pCameraTable->m_pfnGetCamera = &QERApp_GetCamera;\r
2476     pCameraTable->m_pfnSetCamera = &QERApp_SetCamera;\r
2477     pCameraTable->m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;\r
2478 \r
2479     return true;\r
2480   }\r
2481   if (!strcmp(pAPI->major_name, UI_MAJOR))\r
2482   { \r
2483     _QERUITable *pUITable = static_cast<_QERUITable *>(pAPI->mpTable);\r
2484 \r
2485     pUITable->m_pfnCreateGLWindow = QERApp_CreateGLWindow;\r
2486     pUITable->m_pfnHookWindow = QERApp_HookWindow;\r
2487     pUITable->m_pfnUnHookWindow = QERApp_UnHookWindow;\r
2488     pUITable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;\r
2489     pUITable->m_pfnHookListener = QERApp_HookListener;\r
2490     pUITable->m_pfnUnHookListener = QERApp_UnHookListener;\r
2491 \r
2492     return true;\r
2493   }\r
2494   if (!strcmp(pAPI->major_name, UIGTK_MAJOR))\r
2495   { \r
2496     _QERUIGtkTable *pUIGtkTable = static_cast<_QERUIGtkTable *>(pAPI->mpTable);\r
2497 \r
2498     pUIGtkTable->m_pfn_GetQeglobalsGLWidget = &QERApp_GetQeGlobalsGLWidget;\r
2499     pUIGtkTable->m_pfn_glwidget_new = &gtk_glwidget_new;\r
2500     pUIGtkTable-> m_pfn_glwidget_swap_buffers = &gtk_glwidget_swap_buffers;\r
2501     pUIGtkTable->m_pfn_glwidget_make_current = &gtk_glwidget_make_current;\r
2502     pUIGtkTable->m_pfn_glwidget_destroy_context = &gtk_glwidget_destroy_context;\r
2503     pUIGtkTable->m_pfn_glwidget_create_context = &gtk_glwidget_create_context;\r
2504 #if 0\r
2505     pUIGtkTable->m_pfn_glwidget_get_context = &gtk_glwidget_get_context;\r
2506 #endif\r
2507 \r
2508     return true;\r
2509   }\r
2510 \r
2511   return false;\r
2512 }\r
2513 \r
2514 const char* CSynapseClientRadiant::GetInfo()\r
2515 {\r
2516   return "Radiant - synapse core built " __DATE__ " " RADIANT_VERSION;\r
2517 }\r
2518 \r
2519 const char* CSynapseClientRadiant::GetName()\r
2520 {\r
2521   return "core";\r
2522 }\r