* moved zeroradiant (1.6) into trunk
[xonotic/netradiant.git] / contrib / bobtoolz / misc.cpp
1 /*
2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include "StdAfx.h"
21
22 #include "DEntity.h"
23 #include "funchandlers.h"
24
25 #ifdef __linux__
26 #include <sys/types.h>
27 #include <unistd.h>
28 #endif
29
30 /*==========================
31                 Global Vars
32 ==========================*/
33
34 //HANDLE bsp_process;
35 char    g_CurrentTexture[256] = "";
36
37 //=============================================================
38 //=============================================================
39
40 void ReadCurrentTexture()
41 {
42         const char* textureName = g_FuncTable.m_pfnGetCurrentTexture();
43         strcpy(g_CurrentTexture, textureName);
44 }
45
46 const char*  GetCurrentTexture()
47 {
48         ReadCurrentTexture();
49         return g_CurrentTexture;
50 }
51
52 epair_t* GetNextChainItem(epair_t* lastItem, char* key, char* value)
53 {
54         epair_t* nextEPair = g_FuncTable.m_pfnAllocateEpair(key, value);
55
56         if(lastItem != NULL)
57                 lastItem->next = nextEPair;
58
59         return nextEPair;
60 }
61
62 void MoveBlock(int dir, vec3_t min, vec3_t max, float dist)
63 {
64         switch(dir)
65         {
66                 case MOVE_EAST:
67                 {
68                         min[0]+=dist;
69                         max[0]+=dist;
70                         break;
71                 }
72                 case MOVE_WEST:
73                 {
74                         min[0]-=dist;
75                         max[0]-=dist;
76                         break;
77                 }
78                 case MOVE_NORTH:
79                 {
80                         min[1]+=dist;
81                         max[1]+=dist;
82                         break;
83                 }
84                 case MOVE_SOUTH:
85                 {
86                         min[1]-=dist;
87                         max[1]-=dist;
88                         break;
89                 }
90         }
91 }
92
93 void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width)
94 {
95         switch(dir)
96         {
97                 case MOVE_EAST:
98                 {
99                         max[0] = min[0] + width;
100                         break;
101                 }
102                 case MOVE_WEST:
103                 {
104                         min[0] = max[0] - width;
105                         break;
106                 }
107                 case MOVE_NORTH:
108                 {
109                         max[1] = min[1] + width;
110                         break;
111                 }
112                 case MOVE_SOUTH:
113                 {
114                         min[1] = max[1] - width;
115                         break;
116                 }
117         }
118 }
119
120 char* TranslateString (char *buf)
121 {
122         static  char    buf2[32768];
123         int             i, l;
124         char    *out;
125
126         l = strlen(buf);
127         out = buf2;
128         for (i=0 ; i<l ; i++)
129         {
130                 if (buf[i] == '\n')
131                 {
132                         *out++ = '\r';
133                         *out++ = '\n';
134                 }
135                 else
136                         *out++ = buf[i];
137         }
138         *out++ = 0;
139
140         return buf2;
141 }
142
143 void Sys_ERROR (char* text, ...)
144 {
145         va_list argptr;
146         char    buf[32768];
147
148         va_start (argptr,text);
149         vsprintf (buf, text,argptr);
150         va_end (argptr);
151
152         Sys_Printf("BobToolz::ERROR->%s", buf);
153 }
154
155 /*void Sys_Printf (char *text, ...)
156 {
157         va_list argptr;
158         char    buf[32768];
159
160         va_start (argptr,text);
161         vsprintf (buf, text,argptr);
162         va_end (argptr);
163
164         g_FuncTable.m_pfnSysMsg ( buf );
165 }*/
166
167 char* UnixToDosPath(char* path)
168 {
169 #ifndef _WIN32
170         return path;
171 #else
172         for(char* p = path; *p; p++)
173         {
174                 if(*p == '/')
175                         *p = '\\';
176         }
177         return path;
178 #endif
179 }
180
181 const char* ExtractFilename(const char* path)
182 {
183         char* p = strrchr(path, '/');
184         if(!p)
185         {
186                 p = strrchr(path, '\\');
187
188                 if(!p)
189                         return path;
190         }
191         return ++p;
192 }
193
194 extern char* PLUGIN_NAME;
195 /*char* GetGameFilename(char* buffer, const char* filename)
196 {
197         strcpy(buffer, g_FuncTable.m_pfnGetGamePath());
198         char* p = strrchr(buffer, '/');
199         *++p = '\0';
200         strcat(buffer, filename);
201         buffer = UnixToDosPath(buffer);
202         return buffer;
203 }*/
204
205 #if defined (__linux__) || defined (__APPLE__)
206 // the bCreateConsole parameter is ignored on linux ..
207 bool Q_Exec( const char *pCmd, bool bCreateConsole )
208 {
209         switch (fork())
210     {
211         case -1:
212       return false;
213 //      Error ("CreateProcess failed");
214       break;
215     case 0:
216 #ifdef _DEBUG
217                   printf("Running system...\n");
218                         printf("Command: %s\n", pCmd);
219 #endif
220                         // NOTE: we could use that to detect when a step finishes. But then it
221                         // would not work for remote compiling stuff.
222 //      execlp (pCmd, pCmd, NULL);
223                         system( pCmd );
224       printf ("system() returned");
225       _exit (0);
226       break;
227     }
228     return true;
229 }
230 #endif
231
232 #ifdef _WIN32
233 bool Q_Exec( const char *pCmd, bool bCreateConsole )
234 {
235         // G_DeWan: Don't know if this is needed for linux version
236
237         PROCESS_INFORMATION pi;
238         STARTUPINFO si = {0};            // Initialize all members to zero
239         si.cb = sizeof(STARTUPINFO);     // Set byte count
240   DWORD dwCreationFlags;
241
242   if (bCreateConsole)
243     dwCreationFlags = CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS;
244   else
245     dwCreationFlags = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS;
246
247         for(; *pCmd == ' '; pCmd++);
248
249         if(!CreateProcess(NULL, (char *)pCmd, NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &si, &pi))
250                 return false;
251
252   return true;
253 }
254 #endif
255
256 void StartBSP()
257 {
258         char exename[256];
259         GetFilename(exename, "q3map");
260         UnixToDosPath(exename); // do we want this done in linux version?
261
262         char mapname[256];  
263   const char *pn = g_FuncTable.m_pfnReadProjectKey("mapspath");
264   
265         strcpy( mapname, pn );
266         strcat( mapname, "/ac_prt.map" );
267         UnixToDosPath(mapname);
268
269         char command[1024];
270         sprintf(command, "%s -nowater -fulldetail %s", exename, mapname);
271
272         Q_Exec( command, TRUE );
273 }
274
275 void BuildMiniPrt(list<Str>* exclusionList)
276 {
277         // yes, we could just use -fulldetail option, but, as SPOG said
278         // it'd be faster without all the hint, donotenter etc textures and
279         // doors, etc
280
281         DEntity world;
282         
283         char buffer[128];
284   const char *pn = g_FuncTable.m_pfnReadProjectKey("mapspath");
285
286         strcpy( buffer, pn );
287         strcat( buffer, "/ac_prt.map" );
288         FILE* pFile = fopen(buffer, "w");
289
290         // ahem, thx rr2
291         if(!pFile)
292                 return;
293
294         int count = g_FuncTable.m_pfnGetEntityCount();
295         for(int i = 0; i < count; i++)
296         {
297                 entity_t* ent = (entity_t*)g_FuncTable.m_pfnGetEntityHandle(i);
298
299                 epair_t* epl = *g_EntityTable.m_pfnGetEntityKeyValList(ent);
300
301                 epair_t* ep = epl;
302                 while(ep)
303                 {
304                         if(!strcmp(ep->key, "classname"))
305                         {
306                                 if(!strcmp(ep->value, "worldspawn"))
307                                 {
308                                         world.LoadFromEntity(i, FALSE);
309                                         world.RemoveNonCheckBrushes(exclusionList, TRUE);
310                                         world.SaveToFile(pFile);
311                                 }
312                                 else if(strstr(ep->value, "info_"))
313                                 {
314                                         world.ClearBrushes();
315                                         world.ClearEPairs();
316                                         world.LoadEPairList(epl);
317                                         world.SaveToFile(pFile);
318                                 }
319                                 break;
320                         }
321
322                         ep = ep->next;
323                 }
324         }
325
326         fclose(pFile);
327
328         StartBSP();
329 }
330
331 entity_s* FindEntityFromTargetname(const char* targetname, int* entNum)
332 {
333         DEntity world;
334
335         int count = g_FuncTable.m_pfnGetEntityCount();
336         for(int i = 0; i < count; i++)
337         {
338                 world.ClearEPairs();
339
340                 entity_s* ent = (entity_s*)g_FuncTable.m_pfnGetEntityHandle(i);
341
342                 world.LoadEPairList(*g_EntityTable.m_pfnGetEntityKeyValList(ent));
343
344                 DEPair* tn = world.FindEPairByKey("targetname");
345                 if(tn)
346                 {
347                         if(!stricmp(tn->value, targetname)) {
348                                 if(entNum) {
349                                         *entNum = i;
350                                 }
351                                 return ent;
352                         }
353                 }
354         }
355         return NULL;
356 }
357
358 void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture)
359 {
360         faceData->m_bBPrimit = FALSE;
361         faceData->m_fRotate = 0;
362         faceData->m_fScale[0] = 0.5;
363         faceData->m_fScale[1] = 0.5;
364         faceData->m_fShift[0] = 0;
365         faceData->m_fShift[1] = 0;
366         faceData->m_nContents = 0;
367         faceData->m_nFlags = 0;
368         faceData->m_nValue = 0;
369         if(*texture)
370                 strcpy(faceData->m_TextureName, texture);
371         else
372                 strcpy(faceData->m_TextureName, "textures/common/caulk");
373         VectorCopy(va, faceData->m_v1);
374         VectorCopy(vb, faceData->m_v2);
375         VectorCopy(vc, faceData->m_v3);
376 }
377
378 float Determinant3x3(float a1, float a2, float a3,
379                                          float b1, float b2, float b3,
380                                          float c1, float c2, float c3)
381 {
382         return a1*(b2*c3-b3*c2) - a2*(b1*c3-b3*c1) + a3*(b1*c2-b2*c1);
383 }
384
385 bool GetEntityCentre(const char* entity, vec3_t centre)
386 {
387         entity_s* ent = FindEntityFromTargetname(entity, NULL);
388         if(!ent)
389                 return FALSE;
390
391         int cnt = g_FuncTable.m_pfnAllocateEntityBrushHandles(ent);
392         if(cnt == 0)
393         {
394                 g_FuncTable.m_pfnReleaseEntityBrushHandles();
395                 return FALSE;
396         }
397
398         brush_t* brush = (brush_t*)g_FuncTable.m_pfnGetEntityBrushHandle(0);
399         DBrush cBrush;
400         cBrush.LoadFromBrush_t(brush, FALSE);
401
402         vec3_t min, max;
403         cBrush.GetBounds(min, max);
404
405         VectorAdd(min, max, centre);
406         VectorScale(centre, 0.5f, centre);
407
408         g_FuncTable.m_pfnReleaseEntityBrushHandles();
409         return TRUE;
410 }
411
412 vec_t Min(vec_t a, vec_t b)
413 {
414         if(a < b)
415                 return a;
416         return b;
417 }
418
419 void MakeNormal( vec_t* va, vec_t* vb, vec_t* vc, vec_t* out ) {
420         vec3_t v1, v2;
421         VectorSubtract(va, vb, v1);
422         VectorSubtract(vc, vb, v2);
423         CrossProduct(v1, v2, out);
424 }