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