some updates to the Linux build system - obtained a core binary and all required...
[xonotic/netradiant.git] / contrib / hydratoolz / plugin.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 #include "plugin.h"\r
23 #include "version.h"\r
24 \r
25 /*! \file plugin.cpp\r
26     \brief HydraToolz!\r
27 \r
28     HydraToolz by Dominic Clifton - Hydra (Hydra@Hydras-World.com)\r
29 \r
30     Overview\r
31     ========\r
32 \r
33     This plugin allows the user to rebuild the "wad" key pair in the worldspawn\r
34     so that it has a list of all the .wad files in use.\r
35 \r
36     Version History\r
37     ===============\r
38 \r
39     v0.1 - 28/May/2002\r
40       - Initial version.\r
41 \r
42     v1.0 - 10/March/2003\r
43       - Added more console output\r
44       - Removed some old test code\r
45       - Tweaked dialog box.\r
46       - Fixed up for Radiant 1.3.5\r
47 \r
48 \r
49     ToDo\r
50     ====\r
51 \r
52     Nothing...\r
53 \r
54 */\r
55 \r
56 // =============================================================================\r
57 // Globals\r
58 \r
59 _QERFuncTable_1 g_FuncTable;\r
60 _QERFileSystemTable g_FileSystemTable;\r
61 _QEREntityTable g_EntityTable;\r
62 \r
63 \r
64 // =============================================================================\r
65 // Ripped from cmdlib.cpp\r
66 \r
67 /*\r
68 ====================\r
69 Extract file parts\r
70 ====================\r
71 */\r
72 void ExtractFilePath (const char *path, char *dest)\r
73 {\r
74   const char *src;\r
75 \r
76   src = path + strlen(path) - 1;\r
77 \r
78 //\r
79 // back up until a \ or the start\r
80 //\r
81   while (src != path && *(src-1) != '/' && *(src-1) != '\\')\r
82     src--;\r
83 \r
84   memcpy (dest, path, src-path);\r
85   dest[src-path] = 0;\r
86 }\r
87 \r
88 void ExtractFileName (const char *path, char *dest)\r
89 {\r
90   const char *src;\r
91 \r
92   src = path + strlen(path) - 1;\r
93 \r
94 //\r
95 // back up until a \ or the start\r
96 //\r
97   while (src != path && *(src-1) != '/'\r
98          && *(src-1) != '\\' )\r
99     src--;\r
100 \r
101   while (*src)\r
102   {\r
103     *dest++ = *src++;\r
104   }\r
105   *dest = 0;\r
106 }\r
107 \r
108 void ConvertDOSToUnixName( char *dst, const char *src )\r
109 {\r
110   while ( *src )\r
111   {\r
112     if ( *src == '\\' )\r
113       *dst = '/';\r
114     else\r
115       *dst = *src;\r
116     dst++; src++;\r
117   }\r
118   *dst = 0;\r
119 }\r
120 \r
121 // End of rip from cmdlib.cpp\r
122 \r
123 // =============================================================================\r
124 // Actual Plugin Code\r
125 \r
126 // get the wad name from the shader name (or an actual wadname) and add to a list of wad names making\r
127 // sure we don't add duplicates.\r
128 \r
129 GSList *AddToWadList(GSList *wadlist, const char *shadername, const char *wad)\r
130 {\r
131   char tmpstr[QER_MAX_NAMELEN];\r
132   char *wadname;\r
133   if (!shadername && !wad) return wadlist;\r
134 \r
135   if (shadername)\r
136   {\r
137     if (strcmp(shadername,"color") == 0)\r
138       return wadlist;\r
139     ExtractFilePath(shadername,tmpstr);\r
140     // Sys_Printf("checking: %s\n",shadername);\r
141 \r
142     int l = strlen(tmpstr) - 1;\r
143 \r
144     if (tmpstr[l] == '/' || tmpstr[l] == '\\')\r
145       tmpstr[l] = 0;\r
146     else\r
147     {\r
148       Sys_Printf("HydraToolz: WARNING: Unknown wad file for shader %s\n",shadername);\r
149       return wadlist;\r
150     }\r
151 \r
152     ExtractFileName(tmpstr,tmpstr);\r
153 \r
154     wadname = (char *)malloc(strlen(tmpstr) + 5);\r
155     sprintf(wadname,"%s.wad",tmpstr);\r
156   }\r
157   else\r
158   {\r
159     wadname=strdup(wad);\r
160   }\r
161 \r
162   for (GSList *l = wadlist; l != NULL ; l = l->next)\r
163   {\r
164     if (!stricmp((char *)l->data,wadname))\r
165     {\r
166       free( wadname );\r
167       return wadlist;\r
168     }\r
169   }\r
170 \r
171   Sys_Printf("HydraToolz: Adding Wad File to WAD list: %s (reason: ",wadname);\r
172   if (shadername)\r
173     Sys_Printf("see shader \"%s\")\n", shadername);\r
174   else\r
175     Sys_Printf("already in WAD key. )\n");\r
176   return ( g_slist_append (wadlist, wadname ) );\r
177 }\r
178 \r
179 void UpdateWadKeyPair( void )\r
180 {\r
181   int i,nb;\r
182 \r
183   char wads[2048]; // change to CString usage ?\r
184   *wads = 0;\r
185   char *p1,*p2;\r
186   entity_t *pEntity;\r
187   epair_t *pEpair;\r
188   GSList *wadlist = NULL;\r
189   face_t  *f;\r
190   brush_t *b;\r
191   char cleanwadname[QER_MAX_NAMELEN];\r
192   char *actualwad;\r
193 \r
194 \r
195   pEntity = (entity_t *)g_FuncTable.m_pfnGetEntityHandle(0); // get the worldspawn ent\r
196 \r
197   Sys_Printf("HydraToolz: Searching for in-use wad files...\n");\r
198   for(pEpair = pEntity->epairs; pEpair != NULL; pEpair = pEpair->next)\r
199   {\r
200     if (stricmp(pEpair->key,"wad") == 0)\r
201     {\r
202       strcpy(wads,pEpair->value);\r
203       ConvertDOSToUnixName(wads,wads);\r
204 \r
205       Sys_Printf("HydraToolz: Current wad key is \"%s\"!\n",wads);\r
206 \r
207       // ok, we got the list of ; delimited wads, now split it into a GSList that contains\r
208       // just the wad names themselves.\r
209 \r
210       p1 = wads;\r
211 \r
212       do\r
213       {\r
214         p2 = strchr(p1,';');\r
215         if (p2)\r
216           *p2 = 0; // swap the ; with a null terminator\r
217 \r
218         if (strchr(p1,'/') || strchr(p1,'\\'))\r
219         {\r
220           ExtractFileName(p1,cleanwadname);\r
221           wadlist = AddToWadList (wadlist, NULL, cleanwadname);\r
222         }\r
223         else\r
224         {\r
225           wadlist = AddToWadList (wadlist, NULL, p1);\r
226         }\r
227         if (p2)\r
228           p1 = p2+1; // point back to the remainder of the string\r
229         else\r
230           p1 = NULL; // make it so we exit the loop.\r
231 \r
232       } while (p1);\r
233 \r
234       // ok, now we have a list of wads in GSList.\r
235       // now we need to add any new wadfiles (with their paths) to this list\r
236       // so scan all brushes and see what wads are in use\r
237       // FIXME: scan brushes only in the region ?\r
238 \r
239       break; // we don't need to process any more key/pairs.\r
240     }\r
241   }\r
242 \r
243   if (!*wads)\r
244     Sys_Printf("HydraToolz: No \"wad\" keypair wound in worldspawn\n");\r
245 \r
246 \r
247   nb = g_FuncTable.m_pfnAllocateActiveBrushHandles();\r
248   for( i = 0; i < nb; i++ )\r
249         {\r
250     b = (brush_t *)g_FuncTable.m_pfnGetActiveBrushHandle(i);\r
251     if (b->patchBrush) // patches in halflife ?\r
252     {\r
253       wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(),NULL);\r
254     } else\r
255     {\r
256       for (f=b->brush_faces ; f ; f=f->next)\r
257       {\r
258         wadlist = AddToWadList(wadlist, f->pShader->getName(),NULL);\r
259       }\r
260     }\r
261   }\r
262   g_FuncTable.m_pfnReleaseActiveBrushHandles();\r
263 \r
264   nb = g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
265   for( i = 0; i < nb; i++ )\r
266         {\r
267     b = (brush_t *)g_FuncTable.m_pfnGetSelectedBrushHandle(i);\r
268     if (b->patchBrush) // patches in halflife ?\r
269     {\r
270       wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(),NULL);\r
271     } else\r
272     {\r
273       for (f=b->brush_faces ; f ; f=f->next)\r
274       {\r
275         wadlist = AddToWadList(wadlist, f->pShader->getName(),NULL);\r
276       }\r
277     }\r
278   }\r
279   g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
280 \r
281   Sys_Printf("HydraToolz: Rebuilding worldspawn's \"wad\" key-pair...\n");\r
282   // Now we have a complete list of wadnames (without paths) so we just have to turn this\r
283   // back to a ; delimited list.\r
284 \r
285   *wads = 0;\r
286   while (wadlist)\r
287   {\r
288     // skip wad files if they start with "common-"\r
289     if (strnicmp((char *)wadlist->data,"common-",7) == 0)\r
290     {\r
291       Sys_Printf("HydraToolz: Skipping radiant/user-supplied wad file %s\n",(char *)wadlist->data);\r
292     }\r
293     else\r
294     {\r
295       if (wads[0])\r
296         strcat(wads,";");\r
297 \r
298       actualwad = vfsGetFullPath((char *)wadlist->data);\r
299 \r
300       if (actualwad)\r
301       {\r
302         strcat(wads, actualwad);\r
303       }\r
304       else\r
305       {\r
306         Sys_Printf("HydraToolz: WARNING: could not locate wad file %s\n",(char *)wadlist->data);\r
307         strcat(wads, (char *)wadlist->data);\r
308       }\r
309     }\r
310 \r
311     free (wadlist->data);\r
312     wadlist = g_slist_remove (wadlist, wadlist->data);\r
313   }\r
314 \r
315   // store the wad list back in the worldspawn.\r
316   if (*wads)\r
317   {\r
318     //free(pEpair->value);\r
319     //pEpair->value = strdup(wads);\r
320     SetKeyValue(pEntity, "wad", wads);\r
321     Sys_Printf("HydraToolz: Setting worldspawn \"wad\" key value to \"%s\"\n",wads);\r
322 \r
323   }\r
324 \r
325   Sys_Printf("HydraToolz: Finished rebuilding wad keypair!\n");\r
326 \r
327 }\r
328 \r
329 // =============================================================================\r
330 // PLUGIN INTERFACE STUFF\r
331 \r
332 // plugin name\r
333 const char *PLUGIN_NAME = "HydraToolz";\r
334 \r
335 // commands in the menu\r
336 const char *PLUGIN_COMMANDS = "About...;Create/Update WAD keypair";\r
337 \r
338 const char *PLUGIN_ABOUT = "HydraToolz v1.0 for GTKRadiant\n\n"\r
339                            "By Hydra!";\r
340 \r
341 extern "C" void* WINAPI QERPlug_GetFuncTable ()\r
342 {\r
343   return &g_FuncTable;\r
344 }\r
345 \r
346 const char* QERPlug_Init (void* hApp, void *pWidget)\r
347 {\r
348   return "HydraToolz for GTKRadiant"; // do we need this ? hmmm\r
349 }\r
350 \r
351 const char* QERPlug_GetName()\r
352 {\r
353   return (char*)PLUGIN_NAME;\r
354 }\r
355 \r
356 const char* QERPlug_GetCommandList()\r
357 {\r
358   return PLUGIN_COMMANDS;\r
359 }\r
360 \r
361 extern "C" void QERPlug_Dispatch(const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)\r
362 {\r
363         if(!strcmp(p, "Create/Update WAD keypair"))\r
364                 UpdateWadKeyPair();\r
365         else if(!strcmp(p, "About..."))\r
366                 g_FuncTable.m_pfnMessageBox(NULL, PLUGIN_ABOUT, "About", MB_OK, NULL);\r
367 }\r
368 \r
369 // =============================================================================\r
370 // SYNAPSE\r
371 \r
372 CSynapseServer* g_pSynapseServer = NULL;\r
373 CSynapseClientHydraToolz g_SynapseClient;\r
374 \r
375 #if __GNUC__ >= 4\r
376 #pragma GCC visibility push(default)\r
377 #endif\r
378 extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {\r
379 #if __GNUC__ >= 4\r
380 #pragma GCC visibility pop\r
381 #endif\r
382   if (strcmp(version, SYNAPSE_VERSION))\r
383   {\r
384     Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);\r
385     return NULL;\r
386   }\r
387   g_pSynapseServer = pServer;\r
388   g_pSynapseServer->IncRef();\r
389   Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());\r
390 \r
391   g_SynapseClient.AddAPI(PLUGIN_MAJOR, "HydraToolz", sizeof(_QERPluginTable));\r
392   g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);\r
393   g_SynapseClient.AddAPI(VFS_MAJOR, "wad", sizeof(g_FileSystemTable), SYN_REQUIRE, &g_FileSystemTable);\r
394   g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);\r
395   return &g_SynapseClient;\r
396 }\r
397 \r
398 bool CSynapseClientHydraToolz::RequestAPI(APIDescriptor_t *pAPI)\r
399 {\r
400   if (!strcmp(pAPI->major_name, PLUGIN_MAJOR))\r
401   {\r
402     _QERPluginTable *pTable = static_cast<_QERPluginTable*>(pAPI->mpTable);\r
403     pTable->m_pfnQERPlug_Init = QERPlug_Init;\r
404     pTable->m_pfnQERPlug_GetName = QERPlug_GetName;\r
405     pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;\r
406     pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;\r
407     return true;\r
408   }\r
409 \r
410   Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());\r
411   return false;\r
412 }\r
413 \r
414 const char* CSynapseClientHydraToolz::GetInfo()\r
415 {\r
416   return "HydraToolz plugin built " __DATE__ " " RADIANT_VERSION;\r
417 }\r