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