]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/misc.cpp
Merge commit '6e687efe8899278a955efd1e3ba4de5300f7949a' into garux-merge
[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 "misc.h"
21 #include "globaldefs.h"
22
23 #include <list>
24 #include "str.h"
25
26 #include "DPoint.h"
27 #include "DPlane.h"
28 #include "DBrush.h"
29 #include "DEPair.h"
30 #include "DPatch.h"
31 #include "DEntity.h"
32
33 #include "funchandlers.h"
34
35 #if GDEF_OS_POSIX
36 #include <sys/types.h>
37 #include <unistd.h>
38 #endif
39
40 #include "iundo.h"
41 #include "ientity.h"
42 #include "iscenegraph.h"
43 #include "qerplugin.h"
44
45 #include <vector>
46 #include <list>
47 #include <map>
48 #include <algorithm>
49
50 #include "scenelib.h"
51
52 /*==========================
53         Global Vars
54    ==========================*/
55
56 //HANDLE bsp_process;
57 char g_CurrentTexture[256] = "";
58
59 //=============================================================
60 //=============================================================
61
62 void ReadCurrentTexture(){
63         const char* textureName = GlobalRadiant().TextureBrowser_getSelectedShader();
64         strcpy( g_CurrentTexture, textureName );
65 }
66
67 const char*  GetCurrentTexture(){
68         ReadCurrentTexture();
69         return g_CurrentTexture;
70 }
71
72 void MoveBlock( int dir, vec3_t min, vec3_t max, float dist ){
73         switch ( dir )
74         {
75         case MOVE_EAST:
76         {
77                 min[0] += dist;
78                 max[0] += dist;
79                 break;
80         }
81         case MOVE_WEST:
82         {
83                 min[0] -= dist;
84                 max[0] -= dist;
85                 break;
86         }
87         case MOVE_NORTH:
88         {
89                 min[1] += dist;
90                 max[1] += dist;
91                 break;
92         }
93         case MOVE_SOUTH:
94         {
95                 min[1] -= dist;
96                 max[1] -= dist;
97                 break;
98         }
99         }
100 }
101
102 void SetInitialStairPos( int dir, vec3_t min, vec3_t max, float width ){
103         switch ( dir )
104         {
105         case MOVE_EAST:
106         {
107                 max[0] = min[0] + width;
108                 break;
109         }
110         case MOVE_WEST:
111         {
112                 min[0] = max[0] - width;
113                 break;
114         }
115         case MOVE_NORTH:
116         {
117                 max[1] = min[1] + width;
118                 break;
119         }
120         case MOVE_SOUTH:
121         {
122                 min[1] = max[1] - width;
123                 break;
124         }
125         }
126 }
127
128 char* TranslateString( char *buf ){
129         static char buf2[32768];
130
131         std::size_t l = strlen( buf );
132         char* out = buf2;
133         for ( std::size_t i = 0 ; i < l ; i++ )
134         {
135                 if ( buf[i] == '\n' ) {
136                         *out++ = '\r';
137                         *out++ = '\n';
138                 }
139                 else{
140                         *out++ = buf[i];
141                 }
142         }
143         *out++ = 0;
144
145         return buf2;
146 }
147
148
149 char* UnixToDosPath( char* path ){
150 #if !GDEF_OS_WINDOWS
151         return path;
152 #else
153         for ( char* p = path; *p; p++ )
154         {
155                 if ( *p == '/' ) {
156                         *p = '\\';
157                 }
158         }
159         return path;
160 #endif
161 }
162
163 const char* ExtractFilename( const char* path ){
164         const char* p = strrchr( path, '/' );
165         if ( !p ) {
166                 p = strrchr( path, '\\' );
167
168                 if ( !p ) {
169                         return path;
170                 }
171         }
172         return ++p;
173 }
174
175 extern char* PLUGIN_NAME;
176 /*char* GetGameFilename(char* buffer, const char* filename)
177    {
178     strcpy(buffer, g_FuncTable.m_pfnGetGamePath());
179     char* p = strrchr(buffer, '/');
180    *++p = '\0';
181     strcat(buffer, filename);
182     buffer = UnixToDosPath(buffer);
183     return buffer;
184    }*/
185
186 #if GDEF_OS_POSIX
187 // the bCreateConsole parameter is ignored on linux ..
188 bool Q_Exec( const char *pCmd, bool bCreateConsole ){
189         switch ( fork() )
190         {
191         case -1:
192                 return false;
193 //      Error ("CreateProcess failed");
194                 break;
195         case 0:
196 #if GDEF_DEBUG
197                 printf( "Running system...\n" );
198                 printf( "Command: %s\n", pCmd );
199 #endif
200                 // NOTE: we could use that to detect when a step finishes. But then it
201                 // would not work for remote compiling stuff.
202 //      execlp (pCmd, pCmd, NULL);
203                 system( pCmd );
204                 printf( "system() returned" );
205                 _exit( 0 );
206                 break;
207         }
208         return true;
209 }
210 #endif
211
212 #if GDEF_OS_WINDOWS
213
214 #include <windows.h>
215
216 bool Q_Exec( const char *pCmd, bool bCreateConsole ){
217         // G_DeWan: Don't know if this is needed for linux version
218
219         PROCESS_INFORMATION pi;
220         STARTUPINFO si = {0};            // Initialize all members to zero
221         si.cb = sizeof( STARTUPINFO );     // Set byte count
222         DWORD dwCreationFlags;
223
224         if ( bCreateConsole ) {
225                 dwCreationFlags = CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS;
226         }
227         else{
228                 dwCreationFlags = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS;
229         }
230
231         for (; *pCmd == ' '; pCmd++ ) ;
232
233         if ( !CreateProcess( NULL, (char *)pCmd, NULL, NULL, false, dwCreationFlags, NULL, NULL, &si, &pi ) ) {
234                 return false;
235         }
236
237         return true;
238 }
239 #endif
240
241 void StartBSP(){
242         char exename[256];
243         GetFilename( exename, "q3map" );
244         UnixToDosPath( exename ); // do we want this done in linux version?
245
246         char mapname[256];
247         const char *pn = GlobalRadiant().getMapsPath();
248
249         strcpy( mapname, pn );
250         strcat( mapname, "/ac_prt.map" );
251         UnixToDosPath( mapname );
252
253         char command[1024];
254         sprintf( command, "%s -nowater -fulldetail %s", exename, mapname );
255
256         Q_Exec( command, true );
257 }
258
259 class EntityWriteMiniPrt
260 {
261 mutable DEntity world;
262 FILE* pFile;
263 std::list<Str>* exclusionList;
264 public:
265 EntityWriteMiniPrt( FILE* pFile, std::list<Str>* exclusionList )
266         : pFile( pFile ), exclusionList( exclusionList ){
267 }
268 void operator()( scene::Instance& instance ) const {
269         const char* classname = Node_getEntity( instance.path().top() )->getKeyValue( "classname" );
270
271         if ( !strcmp( classname, "worldspawn" ) ) {
272                 world.LoadFromEntity( instance.path().top(), false );
273                 world.RemoveNonCheckBrushes( exclusionList, true );
274                 world.SaveToFile( pFile );
275         }
276         else if ( strstr( classname, "info_" ) ) {
277                 world.ClearBrushes();
278                 world.ClearEPairs();
279                 world.LoadEPairList( Node_getEntity( instance.path().top() ) );
280                 world.SaveToFile( pFile );
281         }
282 }
283 };
284
285 void BuildMiniPrt( std::list<Str>* exclusionList ){
286         // yes, we could just use -fulldetail option, but, as SPOG said
287         // it'd be faster without all the hint, donotenter etc textures and
288         // doors, etc
289
290
291
292         char buffer[128];
293         const char *pn = GlobalRadiant().getMapsPath();
294
295         strcpy( buffer, pn );
296         strcat( buffer, "/ac_prt.map" );
297         FILE* pFile = fopen( buffer, "w" );
298
299         // ahem, thx rr2
300         if ( !pFile ) {
301                 return;
302         }
303
304         Scene_forEachEntity( EntityWriteMiniPrt( pFile, exclusionList ) );
305
306         fclose( pFile );
307
308         StartBSP();
309 }
310
311 class EntityFindByTargetName
312 {
313 const char* targetname;
314 public:
315 mutable const scene::Path* result;
316 EntityFindByTargetName( const char* targetname )
317         : targetname( targetname ), result( 0 ){
318 }
319 void operator()( scene::Instance& instance ) const {
320         if ( result == 0 ) {
321                 const char* value = Node_getEntity( instance.path().top() )->getKeyValue( "targetname" );
322
323                 if ( !strcmp( value, targetname ) ) {
324                         result = &instance.path();
325                 }
326         }
327 }
328 };
329
330 const scene::Path* FindEntityFromTargetname( const char* targetname ){
331         return Scene_forEachEntity( EntityFindByTargetName( targetname ) ).result;
332 }
333
334 void FillDefaultTexture( _QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture ){
335         faceData->m_texdef.rotate = 0;
336         faceData->m_texdef.scale[0] = 0.5;
337         faceData->m_texdef.scale[1] = 0.5;
338         faceData->m_texdef.shift[0] = 0;
339         faceData->m_texdef.shift[1] = 0;
340         faceData->contents = 0;
341         faceData->flags = 0;
342         faceData->value = 0;
343         if ( *texture ) {
344                 faceData->m_shader = texture;
345         }
346         else{
347                 faceData->m_shader = "textures/common/caulk";
348         }
349         VectorCopy( va, faceData->m_p0 );
350         VectorCopy( vb, faceData->m_p1 );
351         VectorCopy( vc, faceData->m_p2 );
352 }
353
354 float Determinant3x3( float a1, float a2, float a3,
355                                           float b1, float b2, float b3,
356                                           float c1, float c2, float c3 ){
357         return a1 * ( b2 * c3 - b3 * c2 ) - a2 * ( b1 * c3 - b3 * c1 ) + a3 * ( b1 * c2 - b2 * c1 );
358 }
359
360 bool GetEntityCentre( const char* entity, vec3_t centre ){
361         const scene::Path* ent = FindEntityFromTargetname( entity );
362         if ( !ent ) {
363                 return false;
364         }
365
366         scene::Instance& instance = *GlobalSceneGraph().find( *ent );
367         VectorCopy( instance.worldAABB().origin, centre );
368
369         return true;
370 }
371
372 vec_t Min( vec_t a, vec_t b ){
373         if ( a < b ) {
374                 return a;
375         }
376         return b;
377 }
378
379 void MakeNormal( const vec_t* va, const vec_t* vb, const vec_t* vc, vec_t* out ) {
380         vec3_t v1, v2;
381         VectorSubtract( va, vb, v1 );
382         VectorSubtract( vc, vb, v2 );
383         CrossProduct( v1, v2, out );
384 }
385
386 char* GetFilename( char* buffer, const char* filename ) {
387         strcpy( buffer, GlobalRadiant().getAppPath() );
388         strcat( buffer, "plugins/" );
389         strcat( buffer, filename );
390         return buffer;
391 }