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