]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/prtview/prtview.cpp
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / contrib / prtview / prtview.cpp
1 /*
2    PrtView plugin for GtkRadiant
3    Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
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 // PrtView.cpp : Defines the initialization routines for the DLL.
21 //
22
23 #include "stdafx.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #define Q3R_CMD_SPLITTER "-"
28 #define Q3R_CMD_ABOUT "About Portal Viewer"
29 #define Q3R_CMD_LOAD "Load .prt file"
30 #define Q3R_CMD_RELEASE "Unload .prt file"
31 #define Q3R_CMD_SHOW_3D "Toggle portals (3D)"
32 #define Q3R_CMD_SHOW_2D "Toggle portals (2D)"
33 #define Q3R_CMD_OPTIONS "Configure Portal Viewer"
34
35 static char INIfn[NAME_MAX];
36
37 /////////////////////////////////////////////////////////////////////////////
38 // CPrtViewApp construction
39
40 #define RENDER_2D "Render2D"
41 #define WIDTH_2D "Width2D"
42 #define AA_2D "AntiAlias2D"
43 #define COLOR_2D "Color2D"
44
45 #define RENDER_3D "Render3D"
46 #define WIDTH_3D "Width3D"
47 #define AA_3D "AntiAlias3D"
48 #define COLOR_3D "Color3D"
49 #define COLOR_FOG "ColorFog"
50 #define FOG "Fog"
51 #define ZBUFFER "ZBuffer"
52 #define POLYGON "Polygons"
53 #define LINE "Lines"
54 #define TRANS_3D "Transparency"
55 #define CLIP_RANGE "ClipRange"
56 #define CLIP "Clip"
57
58 void InitInstance(){
59 #ifdef _WIN32
60         char fn[_MAX_PATH];
61         char fn_drive[_MAX_DRIVE];
62         char fn_dir[_MAX_DIR];
63         char fn_name[_MAX_FNAME];
64         char fn_ext[_MAX_EXT];
65
66         GetModuleFileName( GetModuleHandle( "PrtView.dll" ), fn, _MAX_PATH );
67
68         _splitpath( fn, fn_drive, fn_dir, fn_name, fn_ext );
69
70         strcpy( INIfn, fn_drive );
71         strcat( INIfn, fn_dir );
72         strcat( INIfn, fn_name );
73         strcat( INIfn, ".ini" );
74 #else // if def __linux__
75         strcpy( INIfn, g_get_home_dir() );
76         strcat( INIfn, "/.radiant/" );
77         strcat( INIfn, RADIANT_VERSION );
78         strcat( INIfn, "/prtview.ini" );
79 #endif
80
81         portals.show_2d = INIGetInt( RENDER_2D, FALSE ) ? true : false;
82         portals.aa_2d = INIGetInt( AA_2D, FALSE ) ? true : false;
83         portals.width_2d = (float)INIGetInt( WIDTH_2D, 10 );
84         portals.color_2d = (COLORREF)INIGetInt( COLOR_2D, RGB( 0, 0, 255 ) ) & 0xFFFFFF;
85
86         if ( portals.width_2d > 40.0f ) {
87                 portals.width_2d = 40.0f;
88         }
89         else if ( portals.width_2d < 2.0f ) {
90                 portals.width_2d = 2.0f;
91         }
92
93         portals.show_3d = INIGetInt( RENDER_3D, TRUE ) ? true : false;
94
95         portals.zbuffer = INIGetInt( ZBUFFER, 1 );
96         portals.fog = INIGetInt( FOG, FALSE ) ? true : false;
97         portals.polygons = INIGetInt( POLYGON, TRUE );
98         portals.lines = INIGetInt( LINE, TRUE );
99         portals.aa_3d = INIGetInt( AA_3D, FALSE ) ? true : false;
100         portals.width_3d = (float)INIGetInt( WIDTH_3D, 4 );
101         portals.color_3d = (COLORREF)INIGetInt( COLOR_3D, RGB( 255, 255, 0 ) ) & 0xFFFFFF;
102         portals.color_fog = (COLORREF)INIGetInt( COLOR_FOG, RGB( 127, 127, 127 ) ) & 0xFFFFFF;
103         portals.trans_3d = (float)INIGetInt( TRANS_3D, 50 );
104         portals.clip = INIGetInt( CLIP, FALSE ) ? true : false;
105         portals.clip_range = (float)INIGetInt( CLIP_RANGE, 16 );
106
107         if ( portals.clip_range < 1 ) {
108                 portals.clip_range = 1;
109         }
110         else if ( portals.clip_range > 128 ) {
111                 portals.clip_range = 128;
112         }
113
114         if ( portals.zbuffer < 0 ) {
115                 portals.zbuffer = 0;
116         }
117         else if ( portals.zbuffer > 2 ) {
118                 portals.zbuffer = 0;
119         }
120
121         if ( portals.width_3d > 40.0f ) {
122                 portals.width_3d = 40.0f;
123         }
124         else if ( portals.width_3d < 2.0f ) {
125                 portals.width_3d = 2.0f;
126         }
127
128         if ( portals.trans_3d > 100.0f ) {
129                 portals.trans_3d = 100.0f;
130         }
131         else if ( portals.trans_3d < 0.0f ) {
132                 portals.trans_3d = 0.0f;
133         }
134
135         SaveConfig();
136
137         portals.FixColors();
138 }
139
140 void SaveConfig(){
141         INISetInt( RENDER_2D, portals.show_2d, "Draw in 2D windows" );
142         INISetInt( WIDTH_2D, (int)portals.width_2d, "Width of lines in 2D windows (in units of 1/2)" );
143         INISetInt( COLOR_2D, (int)portals.color_2d, "Color of lines in 2D windows" );
144         INISetInt( AA_2D, portals.aa_2d, "Draw lines in 2D window anti-aliased" );
145
146         INISetInt( ZBUFFER, portals.zbuffer, "ZBuffer level in 3D window" );
147         INISetInt( FOG, portals.fog, "Use depth cueing in 3D window" );
148         INISetInt( POLYGON, portals.polygons, "Render using polygons polygons in 3D window" );
149         INISetInt( LINE, portals.polygons, "Render using lines in 3D window" );
150         INISetInt( RENDER_3D, portals.show_3d, "Draw in 3D windows" );
151         INISetInt( WIDTH_3D, (int)portals.width_3d, "Width of lines in 3D window (in units of 1/2)" );
152         INISetInt( COLOR_3D, (int)portals.color_3d, "Color of lines/polygons in 3D window" );
153         INISetInt( COLOR_FOG, (int)portals.color_fog, "Color of distant lines/polygons in 3D window" );
154         INISetInt( AA_3D, portals.aa_3d, "Draw lines in 3D window anti-aliased" );
155         INISetInt( TRANS_3D, (int)portals.trans_3d, "Transparency in 3d view (0 = solid, 100 = invisible)" );
156         INISetInt( CLIP, portals.clip, "Cubic clipper active for portal viewer" );
157         INISetInt( CLIP_RANGE, (int)portals.clip_range, "Portal viewer cubic clip distance (in units of 64)" );
158 }
159
160 // Radiant function table
161 // use to access what Radiant provides
162 _QERFuncTable_1 g_FuncTable;
163 _QERQglTable g_QglTable;
164
165 #define CONFIG_SECTION "Configuration"
166
167 #if defined( __linux__ ) || defined( __APPLE__ )
168
169 static bool read_var( const char *filename, const char *section, const char *key, char *value ){
170         char line[1024], *ptr;
171         FILE *rc;
172
173         rc = fopen( filename, "rt" );
174
175         if ( rc == NULL ) {
176                 return false;
177         }
178
179         while ( fgets( line, 1024, rc ) != 0 )
180         {
181                 // First we find the section
182                 if ( line[0] != '[' ) {
183                         continue;
184                 }
185
186                 ptr = strchr( line, ']' );
187                 *ptr = '\0';
188
189                 if ( strcmp( &line[1], section ) == 0 ) {
190                         while ( fgets( line, 1024, rc ) != 0 )
191                         {
192                                 ptr = strchr( line, '=' );
193
194                                 if ( ptr == NULL ) {
195                                         // reached the end of the section
196                                         fclose( rc );
197                                         return false;
198                                 }
199                                 *ptr = '\0';
200
201                                 if ( strcmp( line, key ) == 0 ) {
202                                         strcpy( value, ptr + 1 );
203                                         fclose( rc );
204
205                                         while ( value[strlen( value ) - 1] == 10 ||
206                                                         value[strlen( value ) - 1] == 13 ||
207                                                         value[strlen( value ) - 1] == 32 )
208                                                 value[strlen( value ) - 1] = 0;
209                                         return true;
210                                 }
211                         }
212                 }
213         }
214
215         fclose( rc );
216         return false;
217 }
218
219 static bool save_var( const char *filename, const char *section, const char *key, const char *value ){
220         char line[1024], *ptr;
221         FILE *old_rc = NULL, *rc;
222         bool found;
223
224         rc = fopen( filename, "rb" );
225
226         if ( rc != NULL ) {
227                 guint32 len;
228                 void *buf;
229
230                 char *tmpname = g_strdup_printf( "%s.tmp", filename );
231                 old_rc = fopen( tmpname, "w+b" );
232                 g_free( tmpname );
233
234                 fseek( rc, 0, SEEK_END );
235                 len = ftell( rc );
236                 rewind( rc );
237                 buf = g_malloc( len );
238                 fread( buf, len, 1, rc );
239                 fwrite( buf, len, 1, old_rc );
240                 g_free( buf );
241                 fclose( rc );
242                 rewind( old_rc );
243         }
244
245         rc = fopen( filename, "wb" );
246
247         if ( rc == NULL ) {
248                 return false;
249         }
250
251         // First we need to find the section
252         found = false;
253         if ( old_rc != NULL ) {
254                 while ( fgets( line, 1024, old_rc ) != NULL )
255                 {
256                         fputs( line, rc );
257
258                         if ( line[0] == '[' ) {
259                                 ptr = strchr( line, ']' );
260                                 *ptr = '\0';
261
262                                 if ( strcmp( &line[1], section ) == 0 ) {
263                                         found = true;
264                                         break;
265                                 }
266                         }
267                 }
268         }
269
270         if ( !found ) {
271                 fputs( "\n", rc );
272                 fprintf( rc, "[%s]\n", section );
273         }
274
275         fprintf( rc, "%s=%s\n", key, value );
276
277         if ( old_rc != NULL ) {
278                 while ( fgets( line, 1024, old_rc ) != NULL )
279                 {
280                         ptr = strchr( line, '=' );
281
282                         if ( ptr != NULL ) {
283                                 *ptr = '\0';
284
285                                 if ( strcmp( line, key ) == 0 ) {
286                                         break;
287                                 }
288
289                                 *ptr = '=';
290                                 fputs( line, rc );
291                         }
292                         else
293                         {
294                                 fputs( line, rc );
295                                 break;
296                         }
297                 }
298
299                 while ( fgets( line, 1024, old_rc ) != NULL )
300                         fputs( line, rc );
301
302                 fclose( old_rc );
303
304                 char *tmpname = g_strdup_printf( "%s.tmp", filename );
305                 remove( tmpname );
306                 g_free( tmpname );
307         }
308
309         fclose( rc );
310
311         return true;
312 }
313
314 #endif
315
316 int INIGetInt( const char *key, int def ){
317 #if defined( __linux__ ) || defined( __APPLE__ )
318         char value[1024];
319
320         if ( read_var( INIfn, CONFIG_SECTION, key, value ) ) {
321                 return atoi( value );
322         }
323         else{
324                 return def;
325         }
326 #else
327         return GetPrivateProfileInt( CONFIG_SECTION, key, def, INIfn );
328 #endif
329 }
330
331 void INISetInt( const char *key, int val, const char *comment /* = NULL */ ){
332         char s[1000];
333
334         if ( comment ) {
335                 sprintf( s, "%d        ; %s", val, comment );
336         }
337         else{
338                 sprintf( s, "%d", val );
339         }
340 #if defined( __linux__ ) || defined( __APPLE__ )
341         save_var( INIfn, CONFIG_SECTION, key, s );
342 #else
343         WritePrivateProfileString( CONFIG_SECTION, key, s, INIfn );
344 #endif
345 }
346
347
348 // plugin name
349 static const char *PLUGIN_NAME = "Portal Viewer";
350 // commands in the menu
351 static const char *PLUGIN_COMMANDS =
352         Q3R_CMD_ABOUT ";"
353         Q3R_CMD_SPLITTER ";"
354         Q3R_CMD_OPTIONS ";"
355         Q3R_CMD_SPLITTER ";"
356         Q3R_CMD_SHOW_2D ";"
357         Q3R_CMD_SHOW_3D ";"
358         Q3R_CMD_SPLITTER ";"
359         Q3R_CMD_RELEASE ";"
360         Q3R_CMD_LOAD;
361
362 extern "C" LPVOID WINAPI QERPlug_GetFuncTable(){
363         return &g_FuncTable;
364 }
365
366
367 //extern "C" LPCSTR WINAPI QERPlug_Init (HMODULE hApp, GtkWidget* hwndMain)
368 extern "C" const char* QERPlug_Init( void *hApp, void* pMainWidget ){
369         // Setup defaults & load config
370         InitInstance();
371
372         return "Portal Viewer for Q3Radiant";
373 }
374
375 extern "C" const char* QERPlug_GetName(){
376         return (char*)PLUGIN_NAME;
377 }
378
379 extern "C" const char* QERPlug_GetCommandList(){
380         return (char*)PLUGIN_COMMANDS;
381 }
382
383 /*
384    void Sys_Printf (char *text, ...)
385    {
386    va_list argptr;
387    char buf[32768];
388
389    va_start (argptr,text);
390    vsprintf (buf, text, argptr);
391    va_end (argptr);
392
393    g_FuncTable.m_pfnSysMsg (buf);
394    }
395  */
396
397 bool interfaces_started = false;
398
399 static void CheckInterfaces(){
400         if ( interfaces_started ) {
401                 return;
402         }
403
404         render.Register();
405
406         interfaces_started = true;
407 }
408
409 extern "C" void QERPlug_Dispatch( const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush ){
410         Sys_Printf( MSG_PREFIX "Command \"%s\"\n",p );
411
412         if ( !strcmp( p,Q3R_CMD_ABOUT ) ) {
413                 DoAboutDlg();
414         }
415         else if ( !strcmp( p,Q3R_CMD_LOAD ) ) {
416                 CheckInterfaces();
417
418                 if ( interfaces_started ) {
419                         if ( DoLoadPortalFileDialog() == IDOK ) {
420                                 portals.Load();
421                                 g_FuncTable.m_pfnSysUpdateWindows( UPDATE_ALL );
422                         }
423                         else
424                         {
425                                 Sys_Printf( MSG_PREFIX "Portal file load aborted.\n", portals.fn );
426                         }
427                 }
428         }
429         else if ( !strcmp( p,Q3R_CMD_RELEASE ) ) {
430                 portals.Purge();
431
432                 if ( interfaces_started ) {
433                         g_FuncTable.m_pfnSysUpdateWindows( UPDATE_ALL );
434                 }
435
436                 Sys_Printf( MSG_PREFIX "Portals unloaded.\n" );
437         }
438         else if ( !strcmp( p,Q3R_CMD_SHOW_2D ) ) {
439                 portals.show_2d = !portals.show_2d;
440
441                 if ( interfaces_started ) {
442                         g_FuncTable.m_pfnSysUpdateWindows( UPDATE_ALL );
443                 }
444                 SaveConfig();
445
446                 if ( portals.show_2d ) {
447                         Sys_Printf( MSG_PREFIX "Portals will be rendered in 2D view.\n" );
448                 }
449                 else{
450                         Sys_Printf( MSG_PREFIX "Portals will NOT be rendered in 2D view.\n" );
451                 }
452         }
453         else if ( !strcmp( p,Q3R_CMD_SHOW_3D ) ) {
454                 portals.show_3d = !portals.show_3d;
455                 SaveConfig();
456
457                 if ( interfaces_started ) {
458                         g_FuncTable.m_pfnSysUpdateWindows( UPDATE_ALL );
459                 }
460
461                 if ( portals.show_3d ) {
462                         Sys_Printf( MSG_PREFIX "Portals will be rendered in 3D view.\n" );
463                 }
464                 else{
465                         Sys_Printf( MSG_PREFIX "Portals will NOT be rendered in 3D view.\n" );
466                 }
467         }
468         else if ( !strcmp( p,Q3R_CMD_OPTIONS ) ) {
469                 DoConfigDialog();
470                 SaveConfig();
471
472                 if ( interfaces_started ) {
473                         g_FuncTable.m_pfnSysUpdateWindows( UPDATE_ALL );
474                 }
475         }
476 }
477
478
479
480 // =============================================================================
481 // SYNAPSE
482
483 class CSynapseClientPrtView : public CSynapseClient
484 {
485 public:
486 // CSynapseClient API
487 bool RequestAPI( APIDescriptor_t *pAPI );
488 const char* GetInfo();
489
490 CSynapseClientPrtView() { }
491 virtual ~CSynapseClientPrtView() { }
492 };
493
494
495 CSynapseServer* g_pSynapseServer = NULL;
496 CSynapseClientPrtView g_SynapseClient;
497
498 #if __GNUC__ >= 4
499 #pragma GCC visibility push(default)
500 #endif
501 extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
502 #if __GNUC__ >= 4
503 #pragma GCC visibility pop
504 #endif
505         if ( strcmp( version, SYNAPSE_VERSION ) ) {
506                 Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version );
507                 return NULL;
508         }
509         g_pSynapseServer = pServer;
510         g_pSynapseServer->IncRef();
511         Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() );
512
513         g_SynapseClient.AddAPI( PLUGIN_MAJOR, PRTVIEW_MINOR, sizeof( _QERPluginTable ) );
514
515         g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable );
516         g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable );
517
518         return &g_SynapseClient;
519 }
520
521 bool CSynapseClientPrtView::RequestAPI( APIDescriptor_t *pAPI ){
522         if ( !strcmp( pAPI->major_name, PLUGIN_MAJOR ) ) {
523                 if ( !strcmp( pAPI->minor_name, PRTVIEW_MINOR ) ) {
524                         _QERPluginTable* pTable = static_cast<_QERPluginTable*>( pAPI->mpTable );
525
526                         pTable->m_pfnQERPlug_Init = QERPlug_Init;
527                         pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
528                         pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
529                         pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
530                         return true;
531                 }
532         }
533
534         Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() );
535         return false;
536 }
537
538 #include "version.h"
539
540 const char* CSynapseClientPrtView::GetInfo(){
541         return "PrtView module built " __DATE__ " " RADIANT_VERSION;
542 }